Compare commits

...

182 Commits

Author SHA1 Message Date
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
124 changed files with 4657 additions and 6581 deletions

13
.gitignore vendored
View File

@@ -7,15 +7,4 @@ src/.copts_*
contrib/lease-tools/dhcp_lease_time
contrib/lease-tools/dhcp_release
contrib/lease-tools/dhcp_release6
debian/.debhelper
debian/auto-build
debian/debhelper-build-stamp
debian/files
debian/*.substvars
debian/*.debhelper
debian/*.log
debian/dnsmasq-base-lua/
debian/dnsmasq-base/
debian/dnsmasq-utils/
debian/dnsmasq/
debian/tmp

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

220
CHANGELOG
View File

@@ -1,3 +1,154 @@
version 2.92
Redesign the interaction between DNSSEC validation and per-domain
servers, specified as --server=/<domain>/<ip-address>. 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 delegated 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-existence-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. This change should be backwards
compatible for all existing working configurations; it extends the
space of possible configurations which are functional.
Fix a couple of problems with DNSSEC validation and DNAME. One
could cause validation failure on correct domains, and the other
would fail to spot an invalid domain. Thanks to Graham Clinch
for spotting the problem.
version 2.91
Fix spurious "resource limit exceeded messages". Thanks to
Dominik Derigs for the bug report.
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, e.g., --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 SIGSEGV. Thanks to Daniel Rhea for fuzzing this one.
Fix buffer overflow when configured lease-change script name
is too long.
Thanks to Daniel Rhea for finding this one.
Improve behaviour in the face of non-responsive upstream TCP DNS
servers. Without shorter timeouts, clients are blocked for too long
and fail with their own timeouts.
Set --fast-dns-retries by default when doing DNSSEC. A single
downstream query can trigger many upstream queries. On an
unreliable network, there may not be enough downstream retries
to ensure that all these queries complete.
Improve behaviour in the face of truncated answers to queries
for DNSSEC records. Getting these answers by TCP doesn't now
involve a faked truncated answer to the downstream client to
force it to move to TCP. This improves performance and robustness
in the face of broken clients which can't fall back to TCP.
No longer remove data from truncated upstream answers. If an
upstream replies with a truncated answer, but the answer has some
RRs included, return those RRs, rather than returning and
empty answer.
Fix handling of EDNS0 UDP packet sizes.
When talking upstream we always add a pseudo header, and set the
UDP packet size to --edns-packet-max. 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 an EDNS0 header) return truncated. If upstream
returns truncated, do likewise. If upstream is OK, but the
answer is too big for downstream, truncate the answer.
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
Fix broken dhcp-relay on *BSD. Thanks to Harold for finding
this problem.
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.
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.
Fix erroneous "DNSSEC validated" state with non-DNSSEC
upstream servers. Thanks to Dominik Derigs for the bug report.
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.
Handle DS queries to auth zones. When dnsmasq is configured to
act as an authoritative server and has an authoritative zone
configured, and receives 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 recursor upstream, which 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-non-existence
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.
Implement "DNS-0x20 encoding", for 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 resource
allocation easy. This about doubles entropy over the standard
random ID and random port combination. This technique can interact
badly with rare broken DNS servers which don't preserve the case
of the query in their reply. The first time a reply is returned
which matches the query in all respects except case, a warning
will be logged. In this release, 0x020-encoding is default-off
and must be explicitly enabled with --do-0x20-encoding. In future
releases it may default on. You can avoid a future release
changing the behaviour of an installation with --no-x20-encode.
Fix a long-standing problem when two queries which are identical
in every respect _except_ case, get combined by dnsmasq. If
dnsmasq gets eg, two queries for example.com and Example.com
in quick succession it will get the answer for example.com from
upstream and send that answer to both requestors. This means that
the query for Example.com will get an answer for example.com, and
in the modern DNS, that answer may not be accepted.
version 2.90
Fix reversion in --rev-server introduced in 2.88 which
caused breakage if the prefix length is not exactly divisible
@@ -8,7 +159,7 @@ version 2.90
for a particular domain. Thanks to Daniel Danzberger for
spotting this bug.
Set the default maximum DNS UDP packet sice to 1232. This
Set the default maximum DNS UDP packet size to 1232. This
has been the recommended value since 2020 because it's the
largest value that avoid fragmentation, and fragmentation
is just not reliable on the modern internet, especially
@@ -16,16 +167,61 @@ version 2.90
--edns-packet-max for special circumstances.
Add --no-dhcpv4-interface and --no-dhcpv6-interface for
better control over which inetrfaces are providing DHCP service.
better control over which interfaces are providing DHCP service.
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
when the upstream server is a DOH/DOT proxy. Thanks to Justin He
for the bug report.
Add configurable caching for arbitrary RR-types.
Add --filter-rr option, to filter arbitrary RR-types.
--filter-rr=ANY has a special meaning: it filters the
answers to queries for the ANY RR-type.
Add limits on the resources used to do DNSSEC validation.
DNSSEC introduces a potential CPU DoS, because a crafted domain
can force a validator to a large number of cryptographic
operations whilst attempting to do validation. When using TCP
transport a DNSKEY RRset contain thousands of members and any
RRset can have thousands of signatures. The potential number
of signature validations to follow the RFC for validation
for one RRset is the cross product of the keys and signatures,
so millions. In practice, the actual numbers are much lower,
so attacks can be mitigated by limiting the amount of
cryptographic "work" to a much lower amount. The actual
limits are number a signature validation fails per RRset(20),
number of signature validations and hash computations
per query(200), number of sub-queries to fetch DS and DNSKEY
RRsets per query(40), and the number of iterations in a
NSEC3 record(150). These values are sensible, but there is, as yet,
no standardisation on the values for a "conforming" domain, so a
new option --dnssec-limit is provided should they need to be altered.
The algorithm to validate DS records has also been altered to reduce
the maximum work from cross product of the number of DS records and
number of DNSKEYs to the cross product of the number of DS records
and supported DS digest types. As the number of DS digest types
is in single figures, this reduces the exposure.
Credit is due to Elias Heftrig, Haya Schulmann, Niklas Vogel,
and Michael Waidner from the German National Research Center for
Applied Cybersecurity ATHENE for finding this vulnerability.
CVE 2023-50387 and CVE 2023-50868 apply.
Note that this a security vulnerability only when DNSSEC validation
is enabled.
Fix memory-leak when attempting to cache SRV records with zero TTL.
Thanks to Damian Sawicki for the bug report.
Add --max-tcp-connections option to make limit on TCP handling
processes configurable. Also keep stats on how near the limit
we're getting, to help with tuning. Patch from Damian Sawicki.
version 2.89
Fix bug introduced in 2.88 (commit fe91134b) which can result
@@ -102,7 +298,7 @@ version 2.88
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.
searching 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.
@@ -165,7 +361,7 @@ version 2.87
Enhance --domain to accept, for instance,
--domain=net2.thekelleys.org.uk,eth2 so that hosts get a domain
which relects the interface they are attached to in a way which
which reflects the interface they are attached to in a way which
doesn't require hard-coding addresses. Thanks to Sten Spans for
the idea.
@@ -539,22 +735,22 @@ version 2.80
but those which used the default of no checking will need to be
altered to explicitly select no checking. The new default is
because switching off checking for unsigned replies is
inherently dangerous. Not only does it open the possiblity of forged
inherently dangerous. Not only does it open the possibility of forged
replies, but it allows everything to appear to be working even
when the upstream namesevers do not support DNSSEC, and in this
case no DNSSEC validation at all is occuring.
case no DNSSEC validation at all is occurring.
Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip
are set. Thanks to Daniel Miess for help with this.
Add a facilty to store DNS packets sent/recieved in a
Add a facility to store DNS packets sent/received in a
pcap-format file for later debugging. The file location
is given by the --dumpfile option, and a bitmap controlling
which packets should be dumped is given by the --dumpmask
option.
Handle the case of both standard and constructed dhcp-ranges on the
same interface better. We don't now contruct a dhcp-range if there's
same interface better. We don't now construct a dhcp-range if there's
already one specified. This allows the specified interface to
have different parameters and avoids advertising the same
prefix twice. Thanks to Luis Marsano for spotting this case.
@@ -1024,7 +1220,7 @@ version 2.73
Use inotify for checking on updates to /etc/resolv.conf and
friends under Linux. This fixes race conditions when the files are
updated rapidly and saves CPU by noy polling. To build
updated rapidly and saves CPU by not polling. To build
a binary that runs on old Linux kernels without inotify,
use make COPTS=-DNO_INOTIFY
@@ -1364,7 +1560,7 @@ version 2.68
are dynamic and works much better than the previous
work-around which exempted constructed DHCP ranges from the
IP address filtering. As a consequence, that work-around
is removed. Under certain circumstances, this change wil
is removed. Under certain circumstances, this change will
break existing configuration: if you're relying on the
constructed-range exception, you need to change --auth-zone
to specify the same interface as is used to construct your
@@ -1821,7 +2017,7 @@ version 2.61
Set the environment variable DNSMASQ_LOG_DHCP when running
the script id --log-dhcp is in effect, so that script can
taylor their logging verbosity. Suggestion from Malte
tailor their logging verbosity. Suggestion from Malte
Forkel.
Arrange that addresses specified with --listen-address

View File

@@ -1,4 +1,4 @@
# dnsmasq is Copyright (c) 2000-2024 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
#################################################################
@@ -60,22 +61,18 @@ idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFI
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.4`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.4`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags 'nettle hogweed' \
HAVE_CRYPTOHASH $(PKG_CONFIG) --cflags nettle \
HAVE_NETTLEHASH $(PKG_CONFIG) --cflags nettle`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs 'nettle hogweed' \
HAVE_CRYPTOHASH $(PKG_CONFIG) --libs nettle \
HAVE_NETTLEHASH $(PKG_CONFIG) --libs nettle`
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`
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 $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
sum!=$(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' '
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 \
@@ -84,7 +81,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.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 hash-questions.o domain-match.o nftset.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 metrics.h
@@ -105,9 +102,7 @@ clean : mostly_clean
rm -f core */core
rm -f *~ contrib/*/*~ */*~
install : all install-common
install-common :
install : all
$(INSTALL) -d $(DESTDIR)$(BINDIR)
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
@@ -124,7 +119,11 @@ all-i18n : $(BUILDDIR)
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)

View File

@@ -11,14 +11,14 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
crypto.c dump.c ubus.c metrics.c hash-questions.c \
domain-match.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

1
debian Symbolic link
View File

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

1548
debian/changelog vendored

File diff suppressed because it is too large Load Diff

68
debian/control vendored
View File

@@ -1,68 +0,0 @@
Source: dnsmasq
Section: net
Priority: optional
Build-Depends: dh-exec, gettext, libnetfilter-conntrack-dev [linux-any],
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
liblua5.4-dev, dh-runit, debhelper-compat (= 13),
pkg-config, libnftables-dev
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
Homepage: https://www.thekelleys.org.uk/dnsmasq/doc.html
Vcs-Git: https://thekelleys.org.uk/git/dnsmasq.git
Vcs-Browser: https://thekelleys.org.uk/gitweb/?p=dnsmasq.git
Standards-Version: 4.6.2
Rules-Requires-Root: no
Package: dnsmasq
Architecture: all
Pre-Depends: ${misc:Pre-Depends}
Depends: netbase, dnsmasq-base,
${misc:Depends}
Suggests: resolvconf
Breaks: ${runit:Breaks}
Conflicts: resolvconf (<<1.15), ${runit:Conflicts}
Description: Small caching DNS proxy and DHCP/TFTP server - system daemon
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: ${misc:Depends}, ${shlibs:Depends}
Breaks: dnsmasq (<< 2.63-1~)
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
Recommends: dns-root-data
Provides: dnsmasq-base
Conflicts: dnsmasq-base-lua
Description: Small caching DNS proxy and DHCP/TFTP server - executable
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-base-lua
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Breaks: dnsmasq (<< 2.63-1~)
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
Recommends: dns-root-data
Provides: dnsmasq-base
Conflicts: dnsmasq-base
Description: Small caching DNS proxy and DHCP/TFTP server - executable, Lua-enabled
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. This package is an alternative
to dnsmasq-base which includes the Lua interpreter.
Package: dnsmasq-utils
Architecture: linux-any
Depends: ${misc: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.

58
debian/copyright vendored
View File

@@ -1,58 +0,0 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: dnsmasq
Upstream-Contact: Simon Kelley <simon@thekelleys.org.uk>
Source: https://thekelleys.org.uk/dnsmasq/
Files: *
Copyright: 2000-2024 Simon Kelley <simon@thekelleys.org.uk>
License: GPL-2 or GPL-3
Files: src/dnssec.c
Copyright: 2012-2024 Simon Kelley <simon@thekelleys.org.uk>
2012 Giovanni Bajo <rasky@develer.com>
Files: debian/*
Copyright: 2004-2024 Simon Kelley <simon@thekelleys.org.uk>
2012 Lars Bahner <bahner@debian.org>
2024 Sven Geuer <debmaint@g-e-u-e-r.de>
License: GPL-2 or GPL-3
License: GPL-2
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.
.
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
<https://www.gnu.org/licenses/gpl-2.0>.
.
On Debian systems, the full text of the GNU General Public
License can be found in the file
`/usr/share/common-licenses/GPL-2'.
License: GPL-3
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 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
<https://www.gnu.org/licenses/gpl-3.0>.
.
On Debian systems, the full text of the GNU General Public
License can be found in the file
`/usr/share/common-licenses/GPL-3'.

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>

View File

@@ -1 +0,0 @@
dnsmasq-base.dirs

View File

@@ -1 +0,0 @@
dnsmasq-base.docs

View File

@@ -1,3 +0,0 @@
#!/usr/bin/dh-exec
debian/dbus.conf => /usr/share/dbus-1/system.d/dnsmasq.conf
trust-anchors.conf /usr/share/dnsmasq-base-lua

View File

@@ -1,2 +0,0 @@
usr/share/dnsmasq-base-lua usr/share/dnsmasq-base
usr/share/doc/dnsmasq-base-lua usr/share/doc/dnsmasq-base

View File

@@ -1,9 +0,0 @@
# With the use of debhelper /usr/share/doc/dnsmasq-base-lua has become a
# directory as required in
# https://www.debian.org/doc/debian-policy/ch-docs.html#additional-documentation
# thus /usr/share/doc/dnsmasq-base will be a link from now onwards.
symlink_to_dir /usr/share/doc/dnsmasq-base-lua /usr/share/doc/dnsmasq-base 2.89-1.1~ dnsmasq-base-lua
dir_to_symlink /usr/share/doc/dnsmasq-base /usr/share/doc/dnsmasq-base-lua 2.89-1.1~ dnsmasq-base-lua
# Due to lintian warning dbus-policy-in-etc this file has been moved to
# /usr/share/dbus-1/system.d/dnsmasq.conf and thus is not a conffile any more.
rm_conffile /etc/dbus-1/system.d/dnsmasq.conf 2.89-1.1~ dnsmasq-base-lua

View File

@@ -1 +0,0 @@
dnsmasq-base.postinst

View File

@@ -1 +0,0 @@
dnsmasq-base.postrm

View File

@@ -1 +0,0 @@
/var/lib/misc

View File

@@ -1,8 +0,0 @@
doc.html
setup.html
dnsmasq.conf.example
FAQ
CHANGELOG.archive
dbus/DBus-interface
debian/systemd_howto
debian/readme

View File

@@ -1,3 +0,0 @@
#!/usr/bin/dh-exec
debian/dbus.conf => /usr/share/dbus-1/system.d/dnsmasq.conf
trust-anchors.conf /usr/share/dnsmasq-base

View File

@@ -1,3 +0,0 @@
# Due to lintian warning dbus-policy-in-etc this file has been moved to
# /usr/share/dbus-1/system.d/dnsmasq.conf and thus is not a conffile any more.
rm_conffile /etc/dbus-1/system.d/dnsmasq.conf 2.89-1.1~ dnsmasq-base

View File

@@ -1,30 +0,0 @@
#!/bin/sh
set -e
# Create the dnsmasq user in dnsmasq-base, so that Dbus doesn't complain.
if [ "$1" = "configure" ]; then
# Create the user to run as.
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
useradd --system \
--gid nogroup \
--comment dnsmasq \
--home-dir /var/lib/misc --no-create-home \
--shell /usr/sbin/nologin \
dnsmasq
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 /run/dnsmasq ]; then
mkdir /run/dnsmasq
chown dnsmasq:nogroup /run/dnsmasq
fi
fi
#DEBHELPER#

View File

@@ -1,10 +0,0 @@
#!/bin/sh
set -e
if [ purge = "$1" ]; then
userdel dnsmasq
rm -rf /run/dnsmasq
fi
#DEBHELPER#

View File

@@ -1,3 +0,0 @@
dhcp_lease_time /usr/bin
dhcp_release /usr/bin
dhcp_release6 /usr/bin

View File

@@ -1,3 +0,0 @@
dhcp_lease_time.1
dhcp_release.1
dhcp_release6.1

View File

@@ -1,42 +0,0 @@
# This file has six functions:
# 1) to completely disable starting this dnsmasq instance
# 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.
# 6) to avoid using this dnsmasq instance as the system's default resolver
# by setting DNSMASQ_EXCEPT="lo"
# 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"
# The dnsmasq daemon is run by default conforming to the Debian Policy.
# To disable the service,
# for SYSV init, use "update-rc.d dnsmasq disable",
# for systemd, use "systemctl disable dnsmasq".
# 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
# If the resolvconf package is installed, dnsmasq will tell resolvconf
# to use dnsmasq under 127.0.0.1 as the system's default resolver.
# Uncommenting this line inhibits this behaviour.
#DNSMASQ_EXCEPT="lo"

170
debian/dnsmasq.init vendored
View File

@@ -1,170 +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
# Don't exit on error status
set +e
# The following test ensures the dnsmasq service is not started, when the
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
# package is still in place.
if [ -r /usr/share/dnsmasq/init-system-common ]; then
# 'dnsmasq' is installed: source initial code used also with systemd.
. /usr/share/dnsmasq/init-system-common
else
# 'dnsmasq' is removed but not purged, or damaged: do nothing.
exit 0
fi
# Double-check 'dnsmasq-base' or 'dnsmasq-base-lua' is installed.
test -x ${DAEMON} || exit 0
# Source the SysV init-functions which should always be available.
. /lib/lsb/init-functions || exit 0
start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# 2 if daemon could not be started
# /run may be volatile, so we need to ensure that
# /run/dnsmasq exists here as well as in postinst
if [ ! -d /run/dnsmasq ]; then
mkdir /run/dnsmasq || { [ -d /run/dnsmasq ] || return 2 ; }
chown dnsmasq:nogroup /run/dnsmasq || return 2
fi
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} --test > /dev/null || return 1
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} -- \
-x /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.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
}
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 /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --name ${NAME}
}
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 /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} --test > /dev/null
case "${?}" in
0) [ -e "/run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid" ] && return 1 ; return 3 ;;
1) return 0 ;;
*) return 4 ;;
esac
}
case "${1}" in
start)
log_daemon_msg "Starting ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
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
log_daemon_msg "Stopping ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
stop
RETVAL="${?}"
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)
checkconfig
if [ ${?} -ne 0 ]; then
NAME="configuration syntax check"
RETVAL="2"
else
stop_resolvconf
stop
RETVAL="${?}"
fi
log_daemon_msg "Restarting ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
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}${INSTANCE:+.${INSTANCE}}"
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 /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid`
;;
*)
echo "Usage: /etc/init.d/${NAME} {start|stop|restart|force-reload|dump-stats|status}" >&2
exit 3
;;
esac
exit 0

View File

@@ -1,8 +0,0 @@
#!/usr/bin/dh-exec
debian/resolvconf => /etc/resolvconf/update.d/dnsmasq
debian/resolvconf-package => /usr/lib/resolvconf/dpkg-event.d/dnsmasq
debian/init-system-common => /usr/share/dnsmasq/init-system-common
debian/systemd-helper => /usr/share/dnsmasq/systemd-helper
dnsmasq.conf.example => /etc/dnsmasq.conf
debian/readme.dnsmasq.d => /etc/dnsmasq.d/README
debian/insserv => /etc/insserv.conf.d/dnsmasq

View File

@@ -1 +0,0 @@
usr/share/dnsmasq-base/trust-anchors.conf usr/share/dnsmasq/trust-anchors.conf

View File

@@ -1,2 +0,0 @@
# /usr/share/doc/dnsmasq was a symlink in versions < 2.81-1 (see #985282)
symlink_to_dir /usr/share/doc/dnsmasq dnsmasq-base 2.84-1.2~ dnsmasq

View File

@@ -1 +0,0 @@
debian/dnsmasq.runscript name=dnsmasq,logscript,presubj

View File

@@ -1,5 +0,0 @@
#!/bin/sh -eu
if [ -x /sbin/resolvconf ] ; then
/sbin/resolvconf -d lo.dnsmasq
fi

View File

@@ -1,43 +0,0 @@
#!/lib/runit/invoke-run
readonly name=dnsmasq
readonly daemon=/usr/sbin/dnsmasq
readonly marker=/usr/share/dnsmasq/installed-marker
test -e "${marker}" || exec sv down "${name}"
test -x "${daemon}" || exec sv down "${name}"
if [ ! "${RESOLV_CONF:-}" ] &&
[ "${IGNORE_RESOLVCONF:-}" != "yes" ] &&
[ -x /sbin/resolvconf ]
then
RESOLV_CONF=/run/dnsmasq/resolv.conf
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 `env LC_ALL=C sed -rne "s/^([.a-zA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
fi
mkdir -p /run/dnsmasq
chown dnsmasq:nogroup /run/dnsmasq
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
exec "${daemon}" \
--keep-in-foreground \
--log-facility=/dev/stdout \
${RESOLV_CONF:+ -r $RESOLV_CONF} \
${DNSMASQ_OPTS} \
-u dnsmasq

View File

@@ -1,31 +0,0 @@
[Unit]
Description=dnsmasq - A lightweight DHCP and caching DNS server
Requires=network.target
Wants=nss-lookup.target
Before=nss-lookup.target
After=network.target
[Service]
Type=forking
PIDFile=/run/dnsmasq/dnsmasq.pid
# Test the config file and refuse starting if it is not valid.
ExecStartPre=/usr/share/dnsmasq/systemd-helper checkconfig
# We run dnsmasq via the /usr/share/dnsmasq/systemd-helper script which acts
# as a wrapper picking up extra configuration files and then execs dnsmasq
# itself, when called with the "exec" function.
ExecStart=/usr/share/dnsmasq/systemd-helper exec
# The *-resolvconf functions configure (and deconfigure)
# resolvconf to work with the dnsmasq DNS server. They're called like
# this to get correct error handling (ie don't start-resolvconf if the
# dnsmasq daemon fails to start).
ExecStartPost=/usr/share/dnsmasq/systemd-helper start-resolvconf
ExecStop=/usr/share/dnsmasq/systemd-helper stop-resolvconf
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target

View File

@@ -1 +0,0 @@
d /run/dnsmasq 755 dnsmasq nogroup

View File

@@ -1,31 +0,0 @@
[Unit]
Description=dnsmasq (%i) - A lightweight DHCP and caching DNS server
Requires=network.target
Wants=nss-lookup.target
Before=nss-lookup.target
After=network.target
[Service]
Type=forking
PIDFile=/run/dnsmasq/dnsmasq.%i.pid
# Test the config file and refuse starting if it is not valid.
ExecStartPre=/usr/share/dnsmasq/systemd-helper checkconfig "%i"
# We run dnsmasq via the /usr/share/dnsmasq/systemd-helper script which acts
# as a wrapper picking up extra configuration files and then execs dnsmasq
# itself, when called with the "exec" function.
ExecStart=/usr/share/dnsmasq/systemd-helper exec "%i"
# The *-resolvconf functions configure (and deconfigure)
# resolvconf to work with the dnsmasq DNS server. They're called like
# this to get correct error handling (ie don't start-resolvconf if the
# dnsmasq daemon fails to start).
ExecStartPost=/usr/share/dnsmasq/systemd-helper start-resolvconf "%i"
ExecStop=/usr/share/dnsmasq/systemd-helper stop-resolvconf "%i"
ExecReload=/bin/kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target

View File

@@ -1,102 +0,0 @@
# -*- shell-script -*-
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"
INSTANCE="${2}"
# Most configuration options in /etc/default/dnsmasq are deprecated
# but still honoured.
if [ -r /etc/default/${NAME}${INSTANCE:+.${INSTANCE}} ]; then
. /etc/default/${NAME}${INSTANCE:+.${INSTANCE}}
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
# 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=/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 `env LC_ALL=C sed -rne "s/^([.a-zA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
fi
checkconfig()
{
${DAEMON} --test ${CONFIG_DIR:+ -7 ${CONFIG_DIR}} ${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} >/dev/null 2>&1
}
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
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
if grep -qs '^port=0' /etc/dnsmasq.conf; then
return
fi
if [ -x /sbin/resolvconf ] ; then
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.${NAME}${INSTANCE:+.${INSTANCE}}
fi
return 0
}
stop_resolvconf()
{
if [ -x /sbin/resolvconf ] ; then
/sbin/resolvconf -d lo.${NAME}${INSTANCE:+.${INSTANCE}}
fi
return 0
}

1
debian/insserv vendored
View File

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

View File

@@ -1,40 +0,0 @@
Description: Remove or replace privacy breaching logos and forms
Lintian complains about these by issuing the tags privacy-breach-logo and
privacy-breach-donation.
Forwarded: not-needed
Author: Sven Geuer <debmaint@g-e-u-e-r.de>
Last-Update: 2023-11-18
--- a/doc.html
+++ b/doc.html
@@ -1,14 +1,11 @@
<HTML>
<HEAD>
<TITLE> Dnsmasq - network services for small networks.</TITLE>
-<link rel="icon" href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
</HEAD>
<BODY BGCOLOR="WHITE">
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
-<td align="left" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td>
<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
-<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
</table>
Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot. It is designed to be
lightweight and have a small footprint, suitable for resource constrained routers and firewalls. It has also been widely used
@@ -88,14 +85,6 @@
Dnsmasq is mainly written and maintained by Simon Kelley. For most of its life, dnsmasq has been a spare-time project.
These days I'm working on it as my main activity.
I don't have an employer or anyone who pays me regularly to work on dnsmasq. If you'd like to make
-a contribution towards my expenses, please use the donation button below.
-<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
-<input type="hidden" name="cmd" value="_s-xclick">
-<input type="hidden" name="hosted_button_id" value="V3X9GVW5GX6DA">
-<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>
-
-
+a contribution towards my expenses, please use the donation button at <A HREF="https://www.thekelleys.org.uk/dnsmasq/doc.html">the project's home page</A>.
</BODY>

View File

@@ -1 +0,0 @@
eliminate-privacy-breaches.patch

80
debian/readme vendored
View File

@@ -1,80 +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 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.
uselua : 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.
nonftset : omit nftset 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 than 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="/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

127
debian/rules vendored
View File

@@ -1,127 +0,0 @@
#!/usr/bin/make -f
# -*- makefile -*-
# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
# Make sure lintian does not complain about missing hardenings.
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
include /usr/share/dpkg/architecture.mk
PREFIX = /usr
# Upstream does not handle CPPFLAGS, so we add it to CFLAGS here.
CFLAGS += $(CPPFLAGS)
COPTS =
ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
COPTS += -DHAVE_DBUS
endif
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
COPTS += -DHAVE_LIBIDN2
endif
ifeq (,$(filter nonftset, $(DEB_BUILD_OPTIONS)))
COPTS += -DHAVE_NFTSET
endif
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
ifeq ($(DEB_HOST_ARCH_OS),linux)
COPTS += -DHAVE_CONNTRACK
endif
endif
ifneq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_IPSET
endif
ifneq (,$(filter nodhcp6,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_DHCP6
endif
ifneq (,$(filter noipv6,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_IPV6
endif
ifneq (,$(filter notftp,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_TFTP
endif
ifneq (,$(filter nodhcp,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_DHCP
endif
ifneq (,$(filter noscript,$(DEB_BUILD_OPTIONS)))
COPTS += -DNO_SCRIPT
endif
ifneq (,$(filter nortc,$(DEB_BUILD_OPTIONS)))
COPTS += -DHAVE_BROKEN_RTC
endif
ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
COPTS += -DHAVE_DNSSEC
endif
%:
# Ubuntu and derivates do not support runit, see
# https://bugs.debian.org/960401 for details.
if dpkg-vendor --derives-from Ubuntu; then \
dh $@; \
else \
dh $@ --with runit; \
fi
# Upstream builds and installs in one go, so do we.
override_dh_auto_build:
override_dh_auto_install:
dh_auto_build -p dnsmasq-base --no-parallel -- install-i18n \
BUILDDIR=debian/auto-build/dnsmasq-base \
DESTDIR=$(CURDIR)/debian/dnsmasq-base \
PREFIX=$(PREFIX) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
COPTS="$(COPTS)"
dh_auto_build -p dnsmasq-base-lua --no-parallel -- install-i18n \
BUILDDIR=debian/auto-build/dnsmasq-base-lua \
DESTDIR=$(CURDIR)/debian/dnsmasq-base-lua \
PREFIX=$(PREFIX) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
COPTS="$(COPTS) -DHAVE_LUASCRIPT"
dh_auto_build -p dnsmasq-utils -D contrib/lease-tools
override_dh_auto_clean:
dh_auto_clean -p dnsmasq-base -- \
BUILDDIR=debian/auto-build/dnsmasq-base
dh_auto_clean -p dnsmasq-base-lua -- \
BUILDDIR=debian/auto-build/dnsmasq-base-lua
rm -rf debian/auto-build
dh_auto_clean -p dnsmasq-utils -D contrib/lease-tools
override_dh_install:
dh_install -p dnsmasq-utils --sourcedir=contrib/lease-tools
dh_install --remaining-packages
# If 'nodoc' is absent from DEB_BUILD_OPTIONS, Correct name or location of
# some doc files.
# We would prefer do this via dh-exec if it would support dh_installdocs.
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
execute_after_dh_installdocs:
for d in $(CURDIR)/debian/dnsmasq-base*/usr/share/doc/dnsmasq-base*; do \
cd $$d; \
mv readme README.Debian; \
mv CHANGELOG.archive changelog.archive; \
mkdir examples; \
mv dnsmasq.conf.example examples/; \
done
endif
# If 'nodoc' is present in DEB_BUILD_OPTIONS, drop the man pages already
# installed by the upstream build script. Then, let dh_installman do what
# else needs doing.
override_dh_installman:
ifneq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
rm -rf debian/dnsmasq-base*/usr/share/man
endif
dh_installman -p dnsmasq-utils --sourcedir=contrib/lease-tools
dh_installman --remaining-packages

View File

@@ -1 +0,0 @@
3.0 (quilt)

34
debian/systemd-helper vendored
View File

@@ -1,34 +0,0 @@
#!/bin/sh
. /usr/share/dnsmasq/init-system-common
case "$1" in
checkconfig)
checkconfig
;;
start-resolvconf)
start_resolvconf
;;
stop-resolvconf)
stop_resolvconf
;;
exec)
# /run may be volatile, so we need to ensure that
# /run/dnsmasq exists here as well as in postinst
if [ ! -d /run/dnsmasq ]; then
mkdir /run/dnsmasq || { [ -d /run/dnsmasq ] || exit 2 ; }
chown dnsmasq:nogroup /run/dnsmasq || exit 2
fi
exec ${DAEMON} -x /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.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}}
;;
esac

41
debian/systemd_howto vendored
View File

@@ -1,41 +0,0 @@
HOWTO
=====
dnsmasq comes with the possibility to run multiple systemd service instances on the same machine.
There is the main service which is enabled by default via `systemctl enable dnsmasq.service` and uses the configuration from `/etc/default/dnsmasq`.
Additional service instances can be enabled via `systemctl enable dnsmasq@<instance name>.service` that use the configuration from `/etc/default/dnsmasq.<instance name>`.
It is recommended to use a separate configuration file and directory for each instance.
Additionally make sure that all instances use either different ports and/or ip addresses to avoid binding collisions.
Example setup for an instance called "alt"
#1 File `/etc/dnsmasq.alt.conf` copied from `/etc/dnsmasq.conf`
#2 Directory `/etc/dnsmasq.alt.d`
#3 File `/etc/default/dnsmasq.alt` copied from `/etc/default/dnsmasq` with following adaptions:
* The options DNSMASQ_OPTS and CONFIG_DIR point to the correct configuration file and directory.
DNSMASQ_OPTS="... --conf-file=/etc/dnsmasq.alt.conf ..."
CONFIG_DIR=/etc/dnsmasq.alt.d,.dpkg-dist,.dpkg-old,.dpkg-new
* The option DNSMASQ_EXCEPT must contain "lo" to avoid that an instance becomes the machine's DNS resolver.
DNSMASQ_EXCEPT="lo"
* If the additional instance should bind to all IP addresses of a specific interface, e.g. "dnsalt01", then the following addition could be used:
DNSMASQ_OPTS="... --bind-dynamic --interface=dnsalt01 ..."
Additionally the main instance must be stopped from binding to interfaces that are used by other instances:
DNSMASQ_OPTS="... --bind-dynamic --except-interface=dnsalt* ..."
* If the additional instance should not use the machine's DNS resolver, normally that's the dnsmasq main instance, as upstream server, then the following addition could be used:
IGNORE_RESOLVCONF=yes
#4 Enable additional instance via `systemctl enable dnsmasq@alt.service`
#5 Start additional instance without reboot via `systemctl start dnsmasq@alt.service`
TODO
====
#1 - Found shortcoming on 2019-03-10
Only the option DNSMASQ_EXCEPT="lo" avoids that an DNS instance will be set as the machine's DNS resolver.
This may interfere with the wish to run an additional instance on a different port on the localhost addresses.
My suggestion in the initial Debian report [1] was to specify an explicit variable for this.
[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914305#5
#2 - Preferred configuration way
Should the variables DNSMASQ_INTERFACE and DNSMASQ_EXCEPT be used instead of --interface and --except-interface? (while "lo" still has to be in DNSMASQ_EXCEPT as of now)

View File

@@ -1,7 +0,0 @@
#!/bin/sh
set -e
. debian/tests/functions
check_compile_time_options

View File

@@ -1,7 +0,0 @@
#!/bin/sh
set -e
. debian/tests/functions
check_compile_time_options +lua

39
debian/tests/control vendored
View File

@@ -1,39 +0,0 @@
Tests: compile-time-options
Depends: dnsmasq,
dnsmasq-base,
Restrictions: needs-root,
isolation-container,
Tests: compile-time-options+lua
Depends: dnsmasq,
dnsmasq-base-lua,
Restrictions: needs-root,
isolation-container,
Tests: get-address+query-dns+check-utils
Depends: bind9,
bind9-dnsutils,
dnsmasq,
dnsmasq-base,
dnsmasq-utils,
Restrictions: needs-root,
allow-stderr,
isolation-container,
Tests: get-address+query-dns+lua+alt
Depends: bind9,
bind9-dnsutils,
dnsmasq,
dnsmasq-base-lua,
Restrictions: needs-root,
allow-stderr,
isolation-container,
Tests: get-address+query-dns+sysv+alt
Depends: bind9,
bind9-dnsutils,
dnsmasq,
dnsmasq-base,
Restrictions: needs-root,
allow-stderr,
isolation-container,

151
debian/tests/functions vendored
View File

@@ -1,151 +0,0 @@
# -*- shell-script -*-
FUNCTIONS_DIR="debian/tests/functions.d"
match_or_exit () {
file_to_match="$1"
pattern_file="$2"
while read line_to_match <&3 && read pattern_line <&4 ; do
if [ "${line_to_match##$pattern_line}" ]; then
echo '!!! MISMATCH !!!' >&2
echo "Line: ${line_to_match}" >&2
echo "Pattern: ${pattern_line}" >&2
exit 1
fi;
done 3<"${file_to_match}" 4<"${pattern_file}"
}
linecount () {
wc -l $1 | cut -d' ' -f1
}
error_exit () {
echo "ERROR: $1"
exit 1
}
stop_dnsmasq_bind_networking () {
systemctl stop dnsmasq.service
systemctl stop named.service
systemctl stop networking.service
}
configure_and_start_networking () {
#Add interfaces needed for the test
cat ${FUNCTIONS_DIR}/add-to.interfaces >> /etc/network/interfaces
systemctl start networking.service
}
configure_and_start_bind () {
cp ${FUNCTIONS_DIR}/db.autopkg.test /etc/bind/
cat ${FUNCTIONS_DIR}/add-to.named.conf.local >> /etc/bind/named.conf.local
cp ${FUNCTIONS_DIR}/named.conf.options /etc/bind/named.conf.options
systemctl start named.service
}
configure_and_start_dnsmasq () {
alt_mode=0
lua_mode=0
sysv_mode=0
service='dnsmasq.service'
sysv_param2=''
conf_dir='/etc/dnsmasq.d'
while [ -n "$1" ]; do
case "$1" in
alt|lua|sysv) eval ${1}_mode=1 ;;
*) error_exit "configure_and_start_dnsmasq(): invalid flag '$1'"
esac
shift
done
if [ ${alt_mode} -eq 1 ]; then
cp ${FUNCTIONS_DIR}/dnsmasq.alt-autopkgtest.default /etc/default/dnsmasq.alt
cp /etc/dnsmasq.conf /etc/dnsmasq.alt.conf
mkdir /etc/dnsmasq.alt.d
service='dnsmasq@alt.service'
sysv_param2='alt'
conf_dir='/etc/dnsmasq.alt.d'
fi
cp ${FUNCTIONS_DIR}/dnsmasq-autopkgtest.conf "${conf_dir}"
if [ ${lua_mode} -eq 1 ]; then
mkdir -p /usr/local/share/dnsmasq
cp ${FUNCTIONS_DIR}/log.lua /usr/local/share/dnsmasq/
echo "dhcp-luascript=/usr/local/share/dnsmasq/log.lua\n" \
>>"${conf_dir}"/dnsmasq-autopkgtest.conf
fi
if [ ${sysv_mode} -eq 1 ]; then
SYSTEMCTL_SKIP_REDIRECT=1 /etc/init.d/dnsmasq start "${sysv_param2}"
else
systemctl enable "${service}"
systemctl start "${service}"
fi
}
check_compile_time_options () {
journalctl -b -u dnsmasq
echo ~~~ Check compile time options...
journalctl -b -u dnsmasq -g '[a-z]+: ' --output cat >options.msg
cat options.msg
match_or_exit options.msg ${FUNCTIONS_DIR}/options${1}.patterns
}
get_address_on_veth1_and_check_the_result () {
echo ~~~ Get an address on veth1 and check the result...
ip netns exec clientnet ifup veth1
ip netns exec clientnet ip addr show dev veth1 >ip-addr.out 2>&1
cat ip-addr.out
match_or_exit ip-addr.out ${FUNCTIONS_DIR}/ip-addr.patterns
}
query_test_zone_records_and_check_the_result () {
echo ~~~ Query some test zone records and check the result...
ip netns exec clientnet dig +short SOA autopkg.test >dig.out 2>&1
ip netns exec clientnet dig +short NS autopkg.test >>dig.out 2>&1
ip netns exec clientnet dig +short A ns.autopkg.test >>dig.out 2>&1
ip netns exec clientnet dig +short A dhcp3.autopkg.test >>dig.out 2>&1
cat dig.out
if [ `linecount dig.out` -ne `linecount ${FUNCTIONS_DIR}/dig.patterns` ] ; then
error_exit 'empty or unexpected output'
fi
match_or_exit dig.out ${FUNCTIONS_DIR}/dig.patterns
}
check_utils () {
#Test dhcp_lease_time and dhcp_release
leases_file='/var/lib/misc/dnsmasq.leases'
client_ip_address=`cut -d' ' -f3 $leases_file`
client_mac_address=`cut -d' ' -f2 $leases_file`
echo ~~~ Test dhcp_lease_time...
if ! dhcp_lease_time $client_ip_address; then
error_exit "'dhcp_lease_time $client_ip_address' failed with return code $?"
else
#Add \n to dhcp_lease_time's output
echo ''
fi
echo ~~~ Test dhcp_release...
cat $leases_file
if ! dhcp_release veth0 $client_ip_address 1-$client_mac_address; then
error_exit "'dhcp_release veth0 $client_ip_address 1-$client_mac_address' failed with return code $?0"
fi
if [ -n "`cat $leases_file`" ]; then
cat $leases_file
error_exit "$leases_file is not empty"
fi
}
check_lua_log () {
log_file='/var/log/dnsmasq-lua.log'
echo ~~~ Check log file generated by lua script
ls -l ${log_file}
if [ -s ${log_file} ]; then
cat ${log_file}
match_or_exit ${log_file} ${FUNCTIONS_DIR}/log.patterns
else
error_exit "${log_file} is empty"
fi
}

View File

@@ -1,18 +0,0 @@
auto dummy0
iface dummy0 inet static
pre-up ip link add dummy0 type dummy
address 192.168.141.1
netmask 255.255.255.248
post-down ip link del dummy0
auto veth0
iface veth0 inet static
pre-up ip netns add clientnet
pre-up ip link add veth0 type veth peer veth1 netns clientnet
address 192.168.142.1
netmask 255.255.255.248
post-down ip link del veth0
post-down ip netns del clientnet
iface veth1 inet dhcp

View File

@@ -1,2 +0,0 @@
zone "autopkg.test" { type master; file "/etc/bind/db.autopkg.test"; };

View File

@@ -1,18 +0,0 @@
$TTL 604800
@ IN SOA ns.autopkg.test. hostmaster.autopkg.test. (
2 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
300 ) ; Negative Cache TTL
;
@ IN NS ns
ns IN A 192.168.141.1
host IN A 192.168.142.1
dhcp0 IN A 192.168.142.2
dhcp1 IN A 192.168.142.3
dhcp2 IN A 192.168.142.4
dhcp3 IN A 192.168.142.5
dhcp4 IN A 192.168.142.6
brdcst IN A 192.168.142.7

View File

@@ -1,4 +0,0 @@
ns.autopkg.test. hostmaster.autopkg.test. 2 604800 86400 2419200 300
ns.autopkg.test.
192.168.141.1
192.168.142.5

View File

@@ -1,6 +0,0 @@
no-resolv
server=/autopkg.test/192.168.141.1
listen-address=192.168.142.1,127.0.0.1
bind-interfaces
dhcp-range=192.168.142.2,192.168.142.6
dhcp-authoritative

View File

@@ -1,42 +0,0 @@
# This file has six functions:
# 1) to completely disable starting this dnsmasq instance
# 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.
# 6) to avoid using this dnsmasq instance as the system's default resolver
# by setting DNSMASQ_EXCEPT="lo"
# 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.conf"
# The dnsmasq daemon is run by default conforming to the Debian Policy.
# To disable the service,
# for SYSV init, use "update-rc.d dnsmasq disable",
# for systemd, use "systemctl disable dnsmasq".
# 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.alt.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
# If the resolvconf package is installed, dnsmasq will tell resolvconf
# to use dnsmasq under 127.0.0.1 as the system's default resolver.
# Uncommenting this line inhibits this behaviour.
#DNSMASQ_EXCEPT="lo"

View File

@@ -1,6 +0,0 @@
?: veth1@if?: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ??:??:??:??:??:?? brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.142.?/29 brd 192.168.142.7 scope global dynamic veth1
valid_lft 3[56][0-9][0-9]sec preferred_lft 3[56][0-9][0-9]sec
inet6 fe80::*:*:*:*/64 scope link*
valid_lft forever preferred_lft forever

View File

@@ -1,40 +0,0 @@
-- Lua script logging calls from dnsmasq
-- Open the log file in append mode
logfile = assert(io.open("/var/log/dnsmasq-lua.log", "a"))
-- Prepend date and time to a string and write the result to the log file
function __log(str)
logfile:write(os.date("!%FT%TZ ")..str.."\n")
end
-- flush the log file
function __flush_log()
logfile:flush()
end
-- Log a call to init()
function init()
__log("initialising")
__flush_log()
end
-- Log a call to shutdown()
function shutdown()
__log("shutting down")
__flush_log()
end
-- Log a call to lease() including all arguments
function lease(operation, params)
local lines = {}
__log(operation.." lease")
for key,value in pairs(params) do
table.insert(lines, key..": "..value)
end
table.sort(lines)
for index,line in ipairs(lines) do
__log("\t"..line)
end
__flush_log()
end

View File

@@ -1,10 +0,0 @@
????-??-??T??:??:??Z initialising
????-??-??T??:??:??Z add lease
????-??-??T??:??:??Z client_id: ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
????-??-??T??:??:??Z data_missing: 1.0
????-??-??T??:??:??Z hostname: ?*
????-??-??T??:??:??Z interface: veth0
????-??-??T??:??:??Z ip_address: 192.168.142.[2-6]
????-??-??T??:??:??Z lease_expires: [1-9]*
????-??-??T??:??:??Z mac_address: ??:??:??:??:??:??
????-??-??T??:??:??Z time_remaining: 3600.0

View File

@@ -1,6 +0,0 @@
options {
directory "/var/cache/bind";
listen-on { 192.168.141.1; };
recursion no;
};

View File

@@ -1 +0,0 @@
*: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCPv6 Lua TFTP conntrack ipset nftset auth cryptohash DNSSEC loop-detect inotify dumpfile

View File

@@ -1 +0,0 @@
*: IPv6 GNU-getopt DBus no-UBus i18n IDN2 DHCP DHCPv6 no-Lua TFTP conntrack ipset nftset auth cryptohash DNSSEC loop-detect inotify dumpfile

View File

@@ -1,19 +0,0 @@
#!/bin/sh
set -e
. debian/tests/functions
stop_dnsmasq_bind_networking
configure_and_start_networking
configure_and_start_bind
configure_and_start_dnsmasq
get_address_on_veth1_and_check_the_result
query_test_zone_records_and_check_the_result
check_utils
#Done
echo Looks good.

View File

@@ -1,19 +0,0 @@
#!/bin/sh
set -e
. debian/tests/functions
stop_dnsmasq_bind_networking
configure_and_start_networking
configure_and_start_bind
configure_and_start_dnsmasq lua alt
get_address_on_veth1_and_check_the_result
query_test_zone_records_and_check_the_result
check_lua_log
#Done
echo Looks good.

View File

@@ -1,18 +0,0 @@
#!/bin/sh
set -e
. debian/tests/functions
stop_dnsmasq_bind_networking
configure_and_start_networking
configure_and_start_bind
configure_and_start_dnsmasq sysv alt
get_address_on_veth1_and_check_the_result
query_test_zone_records_and_check_the_result
#Done
echo Looks good.
SYSTEMCTL_SKIP_REDIRECT=1 /etc/init.d/dnsmasq stop alt

View File

@@ -1,9 +0,0 @@
Cite-As: dnsmasq
Contact: simon@thekelleys.org.uk
Security-Contact: https://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
Repository: https://thekelleys.org.uk/git/dnsmasq.git
Repository-Browse: https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=summary
Changelog: https://thekelleys.org.uk/dnsmasq/CHANGELOG
Documentation: https://thekelleys.org.uk/dnsmasq/docs/dnsmasq-man.html
FAQ: https://thekelleys.org.uk/dnsmasq/docs/FAQ
Bug-Submit: https://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss

View File

@@ -1,63 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFMbjUMBEACsU1Xk8+uu/EsGVJTh9Tn31C2e0ycd0voBVT7cTdtXpzeiNR+o
/zUAi95ds7FiecpZJp1nRO4vNzvaaAPZhFsFVLzZYyIVABgTXsskT88xbZvzb4W5
KKRWVhoTQxVDgj1+dXLUXULTB6rg02WEhqnix/qf/zFdM9I4/3pRHJn9k+3XKygR
on+nYtljfn3AKBelCo1y28istC6wCncoH11b/qdQtlfxVXaJY4HF27V0MqFFmDMg
cuhOHR7DnhymeDh7GmLfTHJ4LUFG+TecqCjiYhyWcuv2wuSb0EPXUKHJQVViQ8qg
KyPm1ly6uFP0CYdVavO7/oJwKFBIChECrj7BQ4GsImMHeuSzfWno7qy6Fxoxx2+g
0F9cdXWvcxFDGPQsL5vXp8KYNwBrzmijRzQ2ZAnrbG+ilFCkJCbxXcrhzpd4tKwE
0dgcyPL1Ma/lrznhL4ZuOzjVMgLNne7WiPpBNRqI1GoT0pUn6as4pU3En8B+K7zy
MLVfHvI1+iH45fP5bZwYSbXCa85v4+xqljYrzs9giaROEsXe/tsXvuc6JPCcmJXk
CUO3c3QVxqDFt9OYuTHIR8hqehDPLgFgzKqVuoAwMkhTf/zZNGlsy4jvKXQNcZ50
uD4mWO3e+gykNW/OH+88IoCR0rgjQ6trMLOceZFnrtvxwRL//lMndGCTYQARAQAB
tB1TaW1vbiBLZWxsZXkgPHNya0BkZWJpYW4ub3JnPokCNwQTAQgAIQUCUyDDdAIb
AwULCQgHAwUVCgkICwUWAgMBAAIeAQIXgAAKCRAVzdpq4ZE1oqFGD/9LkbZFigc1
jbZ5zIbmGkGvfniWp1mJhEcpgKNfb2MMiu1lKULccIvfVyIY5WDrrpoPnHLnhYA9
OXHcwVADGBayoVOQgIePrMV0V24uYjUh9+9zGRwQrCLo0rl/l07GKH0S1dxDUeyh
JRYZGYEqW2+3XDJqIbfsDzSmPNCyjVvqSvkkt0YyuNbH0+cVEoJ1Q2HmfEhvgd4L
lHZDyhMVqKlKmlnCa8DmhwK+EyzJgLKITqjxBO3NOqPmYZlp8irLXyHAH1sDafaB
wRjV9cNX2TLTwn3wDdUmoAwMz1jopi/61A0kEglENYaa+NH/UnqfWOo7riXuZNwG
VP/F/KlMV+JdXMY34fcSIQMWk9cpxzhpuOJjwhoK7g/yq8q9578QXv4VR6ndH+Le
HDRrm2Ftnih/Ut8unqqDteMJnd3YxSK3Ep78WgVBL9y2Qo3CyKY6VSXlshWZokwy
rwVS8uLqIGAUzLwsKTYi1nmsDb7mQZqUbPBxYN2mrroD7Pr1/XAV8oNxw6l84nzf
zObEKvNZLFtWctNpFJXhWhtm/AeQBdkYKcMyTrwQt9Q0XMYKUGE05U+oAdtTvgCR
JLltqzmt5yMpTPncNmXVoA5YvEVdCU6/Gxpn3Aea8ckBmIqxxQY1QFdEr2nvxPNA
SbkvHDNDr9XUlKQDqjherurKBIBEiKCMnLQmU2ltb24gS2VsbGV5IDxzaW1vbkB0
aGVrZWxsZXlzLm9yZy51az6JAjoEEwEIACQCGwMFCwkIBwMFFQoJCAsFFgIDAQAC
HgECF4AFAlMgw44CGQEACgkQFc3aauGRNaLaZg/+PR41J3P7omGv6XD+TiAXfJQo
R5RfzQoeLNUQEnir/XBulg45203cYHEurchEhSTn2f4WVtFgxJrgId7XGYdf8oIZ
IjBd82fpwdMwhbfcv/6iqzWL0+2vaPmBqE7iwDTatI888q5TyXppGe8L5/VjX0aB
vmVIPyEE9BFQas+vv5byUkU542FxPApGsv0W0P1pKabLl0F7ItPFPuaD0+K1kwBr
WbuGhBKMV9jGHB4qdX/21FBczgAf3J9yJ22vm6orCwwhptxde+DSn7vqZNjDtHGr
kUWDzKAQBy1g4BmTl6IoVgYKZXAVBGMtYUjS+80VV+QE9meVqmtX1aJJEnf0/BRd
v9CeD46hZArwXwi/AWFs300pEfzwcC+9T5xc3jlSdYdWxeQDV7XwK2VCOhxjFqTm
+ehP2Gh14Wfpc34jN9jMJ3OowxzN5iZxGYzkHLFhM+0IKEeWEjxRWOoJgV5PmNvG
7IBbzt8O9xo550h7JmXZVsfSpkFpzJPy0Puz1JeyH/niCeDwKkhEHXQTk/4O+EOD
RxruJbwIYGeO2lNfPn2Hcb1aHvSclx7GGOYDzI4jN0UcYroJpvHZU+0X2ClpCTAW
5IshgHkOkdUQ1c7S+5zPTeLbW+pxTlbWClA0NYMbSn68//i/DMstyBEwtTWYJLmg
5V3HWzRd/6BwKZfDSuu5Ag0EUyDDoQEQAMfQfa2tw3+OJFGMQEzLJSoXYN8/HnZE
gKNlcMuYzhheQLgu/MfcQJ7mnCIdn6xdPaalfLmYx63tM47/NGEM1+MSEvovPiRG
0OLxzSgwei9DiGeNEgsPTLXSZ5EVSXCM1+e9mT1ExT9aGLNnpCd6kIyWIcKCVMot
+XC70R9prWLeyKSh0FAZ0Pwv9i23osJVGOtJjND+WZ0uCeN29ocfN0b64yF4nPRc
9IbcmYIDgNU3RybK2Z/dupbthTisRjHRI3iX3/tiymXF3J0sSvsCluWIJWmyltS3
Xyk/wfKVJz6OouiJjTj5utXVnCGptCDw+DCcj89vx1N0+0Dhm1cQcNZvXjMbVDTs
uU+eVpJbxU6y8N+nXpAXjEw4jMi3zNpqKtkyv2YpoqY5HhGLybgrY0zwSQOyMNf9
lZ5J7znq5gEmiMXnG9OPEw7PPSvm6QfbHPY/jAOgxsu7Fme7k303D5KkyGkkbzQi
YyEtMZvbOMH/uECi2uHGB72qiGpEYjMtHhihaRCBl+0bY8sH83He690qNQHSdStj
aKXcecduE/v5iO0mOYIHdsEHhKlWsE1GXXVLofBr68UBhYV6/AGXko4Pr+dXLzau
N4kALDx6WltFu3qUvoD+uEoLq7IXULMo5Pyd7bO4qGQMKykaXTb5o6dqdu4GzWIU
w1fr9kLEmo29ABEBAAGJAh8EGAEIAAkFAlMgw6ECGwwACgkQFc3aauGRNaIjqA/+
PXuaM6JHuudLycmB0iKAwyB5csOFGpF3b9FgMR68TC4jzi5J5hJZASl0cO/e0ytQ
srDUBbH74y+WaA4ldwBVYr0j/2hqzIjrnGMtgWeHFPLV3sKw8DGuNx1/cOoljJXz
i1WWSHIwDvaj3uZ9CwHt+4/abR7kdvMcnFhQVA4zuzZWFqpp+CDkkJNVwB9zxtAQ
wGTGF4cQ0IvTkhCo6DQhZZVTeyn+nBKxzzWijniWc0LyRsum03MxZ6E7UVIInCTj
dXTalnO8wColwIx5FV4nTMxdsKKgnIXmLexBdd03bW9TkowWf2C2XfDN+pDS8X3M
zO6zAyogqJhAiBFjnRzkOw0cw1VTL00o8uiWdMeu7OKOKeQbUilMAn4MweKB57mc
582kjeGmwdZgWFA4BJ2eiH7HwjxiynwMdZwQEBdOTNLbggHk3/mScF8U1KcJhjAF
f7Ne+Z0feG/8GgKl5aj3ucl821+dfpzB79lLo+kmd1qkDyDiUR5yN6P8l8k6IAUJ
z2KUe0BjtO6VFFw0xni05dkrXdfo7IO79ictHmEn+g3QO8ZLUGRwdtZ1cMhTkm7F
hH8Bdby0y4SoqluvHbri++cC91i1I3a92kHi/8O45rnLhVt+sOfxY1QnSIYh5OFw
GMqMCNDTEL7ESiFaFhSXkmzzVntlyvOBMlgz3IGh2hA=
=otES
-----END PGP PUBLIC KEY BLOCK-----

5
debian/watch vendored
View File

@@ -1,5 +0,0 @@
version=4
opts=\
pgpmode=auto \
https://thekelleys.org.uk/dnsmasq/ \
dnsmasq-([\d.]+)@ARCHIVE_EXT@

View File

@@ -1,4 +1,4 @@
.TH DNSMASQ 8 2021-08-16
.TH DNSMASQ 8 2025-02-05
.SH NAME
dnsmasq \- A lightweight DHCP and caching DNS server.
.SH SYNOPSIS
@@ -114,7 +114,8 @@ which defaults to 1000ms. If the second parameter is given this controls
how long the retries will continue for
otherwise this defaults to 10000ms. Retries are repeated with exponential
backoff. Using this option increases memory usage and
network bandwidth.
network bandwidth. If not otherwise configured, this option is activated
with the default parameters when \fB--dnssec\fP is set.
.TP
.B \-k, --keep-in-foreground
Do not go into the background at startup but otherwise run as
@@ -133,7 +134,7 @@ only, to stop dnsmasq daemonising in production, use
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1. If the argument "extra" is supplied, ie
.B --log-queries=extra
then the log has extra information at the start of each line.
This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor.
This consists of a serial number which ties together the log lines associated with an individual query, and the IP address of the requestor. If the argument "proto" is supplied, this shows everything that "extra" does and also the network protocol used to communicate the queries.
.TP
.B \-8, --log-facility=<facility>
Set the facility to which dnsmasq will send syslog entries, this
@@ -386,7 +387,11 @@ Remove A records from answers. No IPv4 addresses will be returned.
Remove AAAA records from answers. No IPv6 addresses will be returned.
.TP
.B --filter-rr=<rrtype>[,<rrtype>...]
Remove records of the specified type(s) from answers.
Remove records of the specified type(s) from answers. The otherwise-nonsensical --filter-rr=ANY has
a special meaning: it filters replies to queries for type ANY. Everything other than A, AAAA, MX and CNAME
records are removed. Since ANY queries with forged source addresses can be used in DNS amplification attacks
(replies to ANY queries can be large) this defangs such attacks, whilst still supporting the
one remaining possible use of ANY queries. See RFC 8482 para 4.3 for details.
.TP
.B --cache-rr=<rrtype>[,<rrtype>...]
By default, dnsmasq caches A, AAAA, CNAME and SRV DNS record types.
@@ -493,10 +498,7 @@ xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag
.B --server=/internal.thekelleys.org.uk/192.168.1.1
will send all queries for
internal machines to that nameserver, everything else will go to the
servers in /etc/resolv.conf. DNSSEC validation is turned off for such
private nameservers, UNLESS a
.B --trust-anchor
is specified for the domain in question. An empty domain specification,
servers in /etc/resolv.conf. An empty domain specification,
.B //
has the special meaning of "unqualified names only" ie names without any
dots in them. A non-standard port may be specified as
@@ -764,19 +766,18 @@ results in the name internal-0.thekelleys.org.uk. returning 192.168.0.50, intern
Second,
.B --synth-domain=thekelleys.org.uk,192.168.0.0/24,internal- (no *)
will result in a query for internal-192-168-0-56.thekelleys.org.uk returning
192.168.0.56 and a reverse query vice versa. The same applies to IPv6,
but IPv6 addresses may start with '::'
but DNS labels may not start with '-' so in this case if no prefix is
configured a zero is added in front of the label. ::1 becomes 0--1.
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
192.168.0.56 and a reverse query vice versa. The same applies to IPv6;
the representation doesn't use the :: compression feature or
the special representation of V4 mapped IPv6 addresses as these
can generate illegal domain names, so all domains are of the form
internal-1000-0000-0000-0000-0000-0000-0000-0008.example.com
The address range can be of the form
<start address>,<end address> or <ip address>/<prefix-length> in both forms of the option. For IPv6 the start and end addresses
must fall in the same /64 network, or prefix-length must be greater than or equal to 64 except that shorter prefix lengths than 64 are allowed only if non-sequential names are in use.
.TP
.B --dumpfile=<path/to/file>
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end.
Specify the location of a pcap-format file which dnsmasq uses to dump copies of network packets for debugging purposes. If the file exists when dnsmasq starts, it is not deleted; new packets are added to the end. The file may be a named-pipe which Wireshark is listening to.
.TP
.B --dumpmask=<mask>
Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask
@@ -848,6 +849,18 @@ name on successive queries, for load-balancing. This turns off that
behaviour, so that the records are always returned in the order
that they are received from upstream.
.TP
.B --do-0x20-encode, --no-0x20-encode
Dnsmasq can scramble the case of letters in DNS queries it sends upstream as a security feature.
This technique can interact badly with rare broken DNS servers which don't preserve the case
of the query in their reply. The first time a reply is returned
which matches the query in all respects except case, a warning
will be logged. If this coincides with DNS not functioning, it
is necessary to disable the feature. As at version 2.91, 0x20 encoding
is disabled by default, and must be enabled with --do-0x20-encode. The default
may change in the future, so to be sure of its status after an upgrade, set --do-0x20-encode
or --no-0x20-encode in your config. --no-0x20-encode overrides --do-x20-encode or a future default
0x20-encode enable.
.TP
.B --use-stale-cache[=<max TTL excess in s>]
When set, if a DNS name exists in the cache, but its time-to-live has expired, dnsmasq will return the data anyway. (It attempts to refresh the
data with an upstream query after returning the stale data.) This can improve speed and reliability. It comes at the expense
@@ -860,7 +873,7 @@ Set the maximum number of concurrent DNS queries. The default value is
150, which should be fine for most setups. The only known situation
where this needs to be increased is when using web-server log file
resolvers, which can generate large numbers of concurrent queries. This
parameter actually controls the number of concurrent queries per server group, where a server group is the set of server(s) associated with a single domain. So if a domain has it's own server via --server=/example.com/1.2.3.4 and 1.2.3.4 is not responding, but queries for *.example.com cannot go elsewhere, then other queries will not be affected. On configurations with many such server groups and tight resources, this value may need to be reduced.
parameter actually controls the number of concurrent queries per server group, where a server group is the set of server(s) associated with a single domain. So if a domain has its own server via --server=/example.com/1.2.3.4 and 1.2.3.4 is not responding, but queries for *.example.com cannot go elsewhere, then other queries will not be affected. On configurations with many such server groups and tight resources, this value may need to be reduced.
.TP
.B --dnssec
Validate DNS replies and cache DNSSEC data. When forwarding DNS queries, dnsmasq requests the
@@ -878,12 +891,15 @@ ie capable of returning DNSSEC records with data. If they are not,
then dnsmasq will not be able to determine the trusted status of
answers and this means that DNS service will be entirely broken.
.TP
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
.B --trust-anchor=<domain>,[<class>,][<key-tag>,<algorithm>,<digest-type>,<digest>]
Provide DS records to act a trust anchors for DNSSEC
validation. Typically these will be the DS record(s) for Key Signing
validation. The class defaults to IN. Typically these will be the DS record(s) for Key Signing
key(s) (KSK) of the root zone,
but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
but trust anchors for limited domains are also possible.
A negative trust anchor (ie. proof that a DS record doesn't exist) may be configured be specifying
only the name or only the name and class. This can be useful for forcing dnsmasq to treat zones delegated
using \fB--server=/<domain>/<ip-address>\fP as unsigned. The current
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
.TP
.B --dnssec-check-unsigned[=no]
As a default, dnsmasq checks that unsigned DNS replies are
@@ -927,6 +943,15 @@ Authenticated Data bit correctly in all cases is not technically possible. If th
when using this option, then the cache should be disabled using --cache-size=0. In most cases, enabling DNSSEC validation
within dnsmasq is a better option. See --dnssec for details.
.TP
.B --dnssec-limits=<limit>[,<limit>.......]
Override the default resource limits applied to DNSSEC validation. Cryptographic operations are expensive and crafted domains
can DoS a DNSSEC validator by forcing it to do hundreds of thousands of such operations. To avoid this, the dnsmasq validation code
applies limits on how much work will be expended in validation. If any of the limits are exceeded, the validation will fail and the
domain treated as BOGUS. There are four limits, in order(default values in parens): number a signature validation fails per RRset(20), number of signature validations and
hash computations per query(200), number of sub-queries to fetch DS and DNSKEY RRsets per query(40), and the number of iterations in a NSEC3 record(150).
The maximum values reached during validation are stored, and dumped as part of the stats generated by SIGUSR1. Supplying a limit value of 0 leaves the default in place, so
\fB--dnssec-limits=0,0,20\fP sets the number of sub-queries to 20 whilst leaving the other limits at default values.
.TP
.B --dnssec-debug
Set debugging mode for the DNSSEC validation, set the Checking Disabled bit on upstream queries,
and don't convert replies which do not validate to responses with
@@ -1175,7 +1200,7 @@ available, though it normally is for direct-connected clients, or
clients using DHCP relays which support RFC 6939.
For DHCPv4, the special option id:* means "ignore any client-id
For DHCPv4, the special option \fBid:*\fP means "ignore any client-id
and use MAC addresses only." This is useful when a client presents a client-id sometimes
but not others.
@@ -1203,36 +1228,34 @@ the result is undefined. A corollary to this is that the name associated with a
does not appear in the DNS until the host obtains a DHCP lease.
The special keyword "ignore"
tells dnsmasq to never offer a DHCP lease to a machine. The machine
can be specified by hardware address, client ID or hostname, for
instance
.B --dhcp-host=00:20:e0:3b:13:af,ignore
This is
useful when there is another DHCP server on the network which should
The special keyword \fBignore\fP tells dnsmasq never to offer a DHCP lease
to a machine. The machine
can be specified by hardware address, client ID or hostname. For
example: \fB--dhcp-host=00:20:e0:3b:13:af,ignore\fP.
This can be useful when there is another DHCP server on the network which should
be used by some machines.
The set:<tag> construct sets the tag
The \fBset:<tag>\fP construct sets the tag
whenever this \fB--dhcp-host\fP directive is in use. This can be used to
selectively send DHCP options just for this host. More than one tag
can be set in a \fB--dhcp-host\fP directive (but not in other places where
"set:<tag>" is allowed). When a host matches any
\fBset:<tag>\fP is allowed). When a host matches any
\fB--dhcp-host\fP directive (or one implied by /etc/ethers) then the special
tag "known" is set. This allows dnsmasq to be configured to
tag \fBknown\fP is set. This allows dnsmasq to be configured to
ignore requests from unknown machines using
.B --dhcp-ignore=tag:!known
\fB--dhcp-ignore=tag:!known\fP.
If the host matches only a \fB--dhcp-host\fP directive which cannot
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
be used because it specifies an address on a different subnet, the tag \fBknown-othernet\fP is set.
The tag:<tag> construct filters which dhcp-host directives are used; more than
one can be provided, in this case the request must match all of them. Tagged
The \fBtag:<tag>\fP construct filters which dhcp-host directives are used. More than
one tag can be provided. In this case, the request must match all tags. Tagged
directives are used in preference to untagged ones. Note that one of <hwaddr>,
<client_id> or <hostname> still needs to be specified (can be a wildcard).
<client_id> or <hostname> still must be specified (can be a wildcard).
Ethernet addresses (but not client-ids) may have
wildcard bytes, so for example
.B --dhcp-host=00:20:e0:3b:13:*,ignore
will cause dnsmasq to ignore a range of hardware addresses. Note that
will cause dnsmasq to ignore the given range of hardware addresses. Note that
the "*" will need to be escaped or quoted on a command line, but not
in the configuration file.
@@ -1246,11 +1269,11 @@ is 6.
As a special case, in DHCPv4, it is possible to include more than one
hardware address. eg:
.B --dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2
\fB--dhcp-host=11:22:33:44:55:66,12:34:56:78:90:12,192.168.0.2\fP.
This allows an IP address to be associated with
multiple hardware addresses, and gives dnsmasq permission to abandon a
DHCP lease to one of the hardware addresses when another one asks for
a lease. Beware that this is a dangerous thing to do, it will only
a lease. Beware that this is a dangerous thing to do: it will only
work reliably if only one of the hardware addresses is active at any
time and there is no way for dnsmasq to enforce this. It is, for instance,
useful to allocate a stable IP address to a laptop which
@@ -1297,27 +1320,25 @@ options containing the same information. /etc/ethers is re-read when
dnsmasq receives SIGHUP. IPv6 addresses are NOT read from /etc/ethers.
.TP
.B \-O, --dhcp-option=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,][vendor:[<vendor-class>],][<opt>|option:<opt-name>|option6:<opt>|option6:<opt-name>],[<value>[,<value>]]
Specify different or extra options to DHCP clients. By default,
Send various extra options to DHCP clients. By default,
dnsmasq sends some standard options to DHCP clients, the netmask and
broadcast address are set to the same as the host running dnsmasq, and
the DNS server and default route are set to the address of the machine
running dnsmasq. (Equivalent rules apply for IPv6.) If the domain name option has been set, that is sent.
This configuration allows these defaults to be overridden,
or other options specified. The option, to be sent may be given as a
decimal number or as "option:<option-name>" The option numbers are
or other options specified. The option to be sent may be given as a
decimal number or as \fBoption:<option-name>\fP.
Option numbers are
specified in RFC2132 and subsequent RFCs. The set of option-names
known by dnsmasq can be discovered by running "dnsmasq --help dhcp".
For example, to set the default route option to
192.168.4.4, do
.B --dhcp-option=3,192.168.4.4
or
.B --dhcp-option = option:router, 192.168.4.4
and to set the time-server address to 192.168.0.4, do
.B --dhcp-option = 42,192.168.0.4
or
.B --dhcp-option = option:ntp-server, 192.168.0.4
The special address 0.0.0.0 is taken to mean "the address of the
machine running dnsmasq".
known by dnsmasq can be discovered by running \fBdnsmasq --help dhcp\fP.
For example, to set the default route option to 192.168.4.4, use
\fB--dhcp-option=3,192.168.4.4\fP or
\fB--dhcp-option=option:router,192.168.4.4\fP
and to set the time-server address to 192.168.0.4, use
\fB--dhcp-option=42,192.168.0.4\fP or
\fB--dhcp-option=option:ntp-server,192.168.0.4\fP.
The special address 0.0.0.0 means "the address of the system running dnsmasq".
An option without data is valid, and includes just the option without data.
(There is only one option with a zero length data field currently defined for DHCPv4, 80:rapid commit, so this feature is not very useful in practice). Options for which dnsmasq normally
@@ -1338,30 +1359,29 @@ to option 120 are handled as per RFC 3361. Dotted-quad IP addresses
which are followed by a slash and then a netmask size are encoded as
described in RFC 3442.
IPv6 options are specified using the
.B option6:
IPv6 options are specified using the \fBoption6:\fP
keyword, followed by the option number or option name. The IPv6 option
name space is disjoint from the IPv4 option name space. IPv6 addresses
in options must be bracketed with square brackets, eg.
.B --dhcp-option=option6:ntp-server,[1234::56]
\fB --dhcp-option=option6:ntp-server,[1234::56]\fP.
For IPv6, [::] means "the global address of
the machine running dnsmasq", whilst [fd00::] is replaced with the
ULA, if it exists, and [fe80::] with the link-local address.
Be careful: no checking is done that the correct type of data for the
option number is sent, it is quite possible to
persuade dnsmasq to generate illegal DHCP packets with injudicious use
of this flag. When the value is a decimal number, dnsmasq must determine how
Be careful: data-type suitability for the option number sent is not checked.
It is quite possible to persuade dnsmasq to generate illegal DHCP packets with
injudicious use of this flag.
When the value is a decimal number, dnsmasq must determine how
large the data item is. It does this by examining the option number and/or the
value, but can be overridden by appending a single letter flag as follows:
b = one byte, s = two bytes, i = four bytes. This is mainly useful with
encapsulated vendor class options (see below) where dnsmasq cannot
determine data size from the option number. Option data which
determine data size from the option number. Option data which
consists solely of periods and digits will be interpreted by dnsmasq
as an IP address, and inserted into an option as such. To force a
literal string, use quotes. For instance when using option 66 to send
a literal IP address as TFTP server name, it is necessary to do
.B --dhcp-option=66,"1.2.3.4"
a literal IP address as TFTP server name, it is necessary to do
\fB--dhcp-option=66,"1.2.3.4"\fP.
Encapsulated Vendor-class options may also be specified (IPv4 only) using
\fB--dhcp-option\fP: for instance
@@ -1382,7 +1402,7 @@ Options may be encapsulated (IPv4 only) within other options: for instance
will send option 175, within which is the option 190. If multiple
options are given which are encapsulated with the same option number
then they will be correctly combined into one encapsulated option.
encap: and vendor: are may not both be set in the same \fB--dhcp-option\fP.
encap: and vendor: may not both be set in the same \fB--dhcp-option\fP.
The final variant on encapsulated options is "Vendor-Identifying
Vendor Options" as specified by RFC3925. These are denoted like this:
@@ -1390,7 +1410,7 @@ Vendor Options" as specified by RFC3925. These are denoted like this:
The number in the vi-encap: section is the IANA enterprise number
used to identify this option. This form of encapsulation is supported
in IPv6.
The address 0.0.0.0 is not treated specially in
encapsulated options.
.TP
@@ -1401,6 +1421,10 @@ except that the option will always be sent, even if the client does
not ask for it in the parameter request list. This is sometimes
needed, for example when sending options to PXELinux.
.TP
.B --dhcp-option-pxe=[tag:<tag>,[tag:<tag>,]][encap:<opt>,][vi-encap:<enterprise>,]<opt>,[<value>[,<value>]]
A variant of --dhcp-option which defines options only sent in reply to PXE clients. In addition, such options are
sent in reply to PXE clients when dnsmasq is acting as a PXE proxy, unlike other options. A typical use-case is option 175, sent to iPXE.
.TP
.B --dhcp-no-override
(IPv4 only) Disable re-use of the DHCP servername and filename fields as extra
option space. If it can, dnsmasq moves the boot server and filename
@@ -1412,7 +1436,7 @@ forces "simple and safe" behaviour to avoid problems in such a case.
.B --dhcp-relay=<local address>[,<server address>[#<server port>]][,<interface]
Configure dnsmasq to do DHCP relay. The local address is an address
allocated to an interface on the host running dnsmasq. All DHCP
requests arriving on that interface will we relayed to a remote DHCP
requests arriving on that interface will be relayed to a remote DHCP
server at the server address. It is possible to relay from a single local
address to multiple remote servers by using multiple \fB--dhcp-relay\fP
configs with the same local address and different server
@@ -1512,45 +1536,47 @@ via relays. If a list of IP addresses is given, only interactions via
relays at those addresses are affected.
.TP
.B --dhcp-match=set:<tag>,<option number>|option:<option name>|vi-encap:<enterprise>[,<value>]
Without a value, set the tag if the client sends a DHCP
option of the given number or name. When a value is given, set the tag only if
the option is sent and matches the value. The value may be of the form
Without \fB<value>\fP, set \fB<tag>\fP if the client sends a DHCP
\fBoption\fP of the given number or name. With \fB<value>\fP, set \fB<tag>\fP only if
the client sends the \fBoption\fP matching or containing \fB<value>\fP.
The value may be of the form
"01:ff:*:02" in which case the value must match (apart from wildcards)
but the option sent may have unmatched data past the end of the
value. The value may also be of the same form as in
.B --dhcp-option
in which case the option sent is treated as an array, and one element
must match, so
must match.
.B --dhcp-match=set:efi-ia32,option:client-arch,6
will set the tag "efi-ia32" if the the number 6 appears in the list of
sets the tag \fBefi-ia32\fP if the number \fB6\fP appears in the list of
architectures sent by the client in option 93. (See RFC 4578 for
details.) If the value is a string, substring matching is used.
details.) If the value is a string, substring matching is used.
The special form with vi-encap:<enterprise number> matches against
vendor-identifying vendor classes for the specified enterprise. Please
see RFC 3925 for more details of these rare and interesting beasts.
.TP
.B --dhcp-name-match=set:<tag>,<name>[*]
Set the tag if the given name is supplied by a DHCP client. There may be a single trailing wildcard *, which has the usual meaning. Combined with dhcp-ignore or dhcp-ignore-names this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
Set a \fB<tag>\fP if the given \fB<name>\fP is supplied by a DHCP client. There may be a single trailing wildcard *, with a glob meaning. Combined with \fBdhcp-ignore\fP or \fBdhcp-ignore-names\fP this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
.TP
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
If no tag:<tag> appears set:<tag> tags are set unconditionally.
Any number of set: and tag: forms may appear, in any order.
\fB--tag-if\fP lines are executed in order, so if the tag in tag:<tag> is a
Perform boolean operations on tags. All \fBset:<tag>\fP tags are set if
all \fBtag:<tag>\fP are already set, (or unset when \fBtag:!<tag>\fP is used).
If no \fBtag:<tag>\fP appears, \fBset:<tag>\fP tags are set unconditionally.
Any number of \fBset:\fP and \fBtag:\fP forms may appear, in any order.
\fB--tag-if\fP lines are executed in order, so if the tag in \fBtag:<tag>\fP is a
tag set by another
.B --tag-if,
the line which sets the tag must precede the one which tests it.
the line which sets the tag must precede the line which tests it.
As an extension, the tag:<tag> clauses support limited wildcard matching,
similar to the matching in the \fB--interface\fP directive. This allows, for
example, using \fB--tag-if=set:ppp,tag:ppp*\fP to set the tag 'ppp' for all requests
received on any matching interface (ppp0, ppp1, etc). This can be used in conjunction
with the tag:!<tag> format meaning that no tag matching the wildcard may be set.
As an extension, the \fBtag:<tag>\fP clauses support limited wildcard matching,
similar to the matching in the \fB--interface\fP directive. This allows the
example \fB--tag-if=set:ppp,tag:ppp*\fP to set the tag 'ppp' for all requests
received on any matching interface (ppp0, ppp1, etc). This can be used in conjunction
with the \fBtag:!<tag>\fP format meaning that no tag matching the wildcard may be set.
.TP
.B \-J, --dhcp-ignore=tag:<tag>[,tag:<tag>]
When all the given tags appear in the tag set ignore the host and do
When all the given tags appear in the tag set, ignore the host and do
not allocate it a DHCP lease.
.TP
.B --dhcp-ignore-names[=tag:<tag>[,tag:<tag>]]
@@ -1663,6 +1689,11 @@ to allow netbooting. This mode is enabled using the
.B proxy
keyword in
.B --dhcp-range.
If the "other" DHCP server is on a remote network, it is
possible, and useful, to configure dnsmasq as both a PXE proxy-DHCP server
and a DHCP relay to the remote DHCP server. See
.B --dhcp-relay
for details. PXE is only supported over IPv4 at this time.
.TP
.B --dhcp-pxe-vendor=<vendor>[,...]
According to UEFI and PXE specifications, DHCP packets between PXE clients and
@@ -2394,48 +2425,67 @@ the CNAME. To work around this, add the CNAME to /etc/hosts so that
the CNAME is shadowed too.
.PP
The tag system works as follows: For each DHCP request, dnsmasq
collects a set of valid tags from active configuration lines which
include set:<tag>, including one from the
.B --dhcp-range
used to allocate the address, one from any matching
.B --dhcp-host
(and "known" or "known-othernet" if a \fB--dhcp-host\fP matches)
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
name of the interface on which the request arrived is also set.
The tag system works as follows: dnsmasq tags each DHCP request
with tags from applicable configuration lines containing \fBset:<tag>\fP i.e.
Any configuration lines which include one or more tag:<tag> constructs
will only be valid if all that tags are matched in the set derived
above. Typically this is \fB--dhcp-option\fP.
.B --dhcp-option
which has tags will be used in preference to an untagged
.B --dhcp-option,
provided that _all_ the tags match somewhere in the
set collected as described above. The prefix '!' on a tag means 'not'
so \fB--dhcp-option=tag:!purple,3,1.2.3.4\fP sends the option when the
tag purple is not in the set of valid tags. (If using this in a
command line rather than a configuration file, be sure to escape !,
which is a shell metacharacter)
\fBset:<tag>\fP from the \fB--dhcp-range\fP used to allocate the address;
\fBset:<tag>\fP from any matching \fB--dhcp-host\fP (plus the tag \fBknown\fP or
\fBknown-othernet\fP).
BOOTP requests are tagged \fBbootp\fP. Each request is also tagged with the name of
the interface on which the request arrived.
Each configuration line containing one or more \fBtag:<tag>\fP constructs
applies when all its tags exist on the request. That is:
Configuration tag:A applies to a request set:tagged A.
Configuration tag:B applies to a request set:tagged B.
Configuration tag:A+B doesn't apply to a request set:tagged A.
Configuration tag:A+B doesn't apply to a request set:tagged B.
Configurations tag:A+B, tag:A, tag:B apply to a request set:tagged A+B.
\fBset:<tag>\fP constructs in \fB--dhcp-range\fP and \fB--dhcp-host\fP tag requests.
Use \fBtag:<tag>\fPs in \fB--dhcp-option\fPs to match \fBset:<tag>\fP and apply configurations.
A \fB--dhcp-option\fP with \fBtag:<tag>\fP is preferred over an untagged
\fB--dhcp-option\fP, provided that \fBall\fP its tags match somewhere in the
set gathered above.
The tag prefix '!' means 'not'.
\fB--dhcp-option=tag:!purple,3,1.2.3.4\fP sends the option when the request
is not tagged with purple. (The shell metacharacter '!' must be escaped on the
command line but not in a configuration file).
When selecting \fB--dhcp-option\fPs, a \fB--dhcp-range\fP tag is second class
to other tags, to make it easy to override options for
individual hosts, so:
When selecting \fB--dhcp-options\fP, a tag from \fB--dhcp-range\fP is second class
relative to other tags, to make it easy to override options for
individual hosts, so
.B --dhcp-range=set:interface1,......
.B --dhcp-host=set:myhost,.....
.B --dhcp-option=tag:interface1,option:nis-domain,"domain1"
.B --dhcp-option=tag:myhost,option:nis-domain,"domain2"
will set the NIS-domain to domain1 for hosts in the range, but
override that to domain2 for a particular host.
sets the NIS-domain to domain1 for hosts in the range, but
to domain2 for a particular host that may or may not fall in the range.
.PP
Note that for
.B --dhcp-range
both tag:<tag> and set:<tag> are allowed, to both select the range in
Note that for \fB--dhcp-range\fP both
\fBtag:<tag>\fP and
\fBset:<tag>\fP are possible, in order to both select the range in
use based on (eg) \fB--dhcp-host\fP, and to affect the options sent, based on
the range selected.
This system evolved from an earlier, more limited one and for backward
compatibility "net:" may be used instead of "tag:" and "set:" may be
The tag system evolved from an earlier, more limited system. For backward
compatibility, "net:" may be used instead of "tag:" and "set:" may be
omitted. (Except in
.B --dhcp-host,
where "net:" may be used instead of "set:".) For the same reason, '#'
@@ -2453,7 +2503,7 @@ configuration option is present to activate the DHCP server
on a particular network. (Setting \fB--bootp-dynamic\fP removes the need for
static address mappings.) The filename
parameter in a BOOTP request is used as a tag,
as is the tag "bootp", allowing some control over the options returned to
as is the tag \fBbootp\fP, allowing some control over the options returned to
different classes of hosts.
.SH AUTHORITATIVE CONFIGURATION

137
po/de.po
View File

@@ -2,7 +2,7 @@
#
# This revised version is (C) Copyright by
# Matthias Andree <matthias.andree@gmx.de>, 2010 - 2021.
# Conrad Kostecki <conrad@kostecki.com>, 2014 - 2022.
# Conrad Kostecki <conrad@kostecki.com>, 2014 - 2024.
# It is subject to the GNU General Public License v2,
# or at your option, any later version.
#
@@ -10,10 +10,10 @@
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
msgid ""
msgstr ""
"Project-Id-Version: dnsmasq 2.88\n"
"Project-Id-Version: dnsmasq 2.91\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-03-20 00:00+0000\n"
"PO-Revision-Date: 2022-11-17 20:08+0100\n"
"PO-Revision-Date: 2024-12-23 22:36+0100\n"
"Last-Translator: Conrad Kostecki <conrad@kostecki.com>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
@@ -21,7 +21,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2\n"
"X-Generator: Poedit 3.5\n"
#: cache.c:652
msgid "Internal error in cache."
@@ -43,9 +43,9 @@ msgid "bad name at %s line %d"
msgstr "Fehlerhafter Name in %s Zeile %d"
#: cache.c:1265
#, fuzzy, c-format
#, c-format
msgid "read %s - %d names"
msgstr "%s gelesen - %d Adressen"
msgstr "%s gelesen - %d Namen"
#: cache.c:1381
msgid "cleared cache"
@@ -84,7 +84,7 @@ msgstr "weitergeleitete Anfragen %u, lokal beantwortete Anfragen %u"
#: cache.c:1766
#, c-format
msgid "queries answered from stale cache %u"
msgstr ""
msgstr "Anfragen beantwortet vom veralteten Cache %u"
#: cache.c:1768
#, c-format
@@ -92,9 +92,9 @@ msgid "queries for authoritative zones %u"
msgstr "Anfragen nach autoritativen Zonen %u"
#: cache.c:1796
#, fuzzy, c-format
#, c-format
msgid "server %s#%d: queries sent %u, retried %u, failed %u, nxdomain replies %u, avg. latency %ums"
msgstr "Server %s#%d: Anfragen gesendet %u, erneut versucht oder fehlgeschlagen %u"
msgstr "Server %s#%d: Anfragen gesendet %u, erneut versucht %u, fehlgeschlagen %u, nxdomain-Antworten %u, durchschnittliche Latenz %ums"
#: util.c:51
#, c-format
@@ -120,14 +120,14 @@ msgid "failed to allocate %d bytes"
msgstr "Konnte %d Bytes nicht belegen"
#: util.c:344
#, fuzzy, c-format
#, c-format
msgid "failed to reallocate %d bytes"
msgstr "Konnte %d Bytes nicht belegen"
msgstr "Konnte %d Bytes nicht allozieren"
#: util.c:465
#, fuzzy, c-format
#, c-format
msgid "cannot read monotonic clock: %s"
msgstr "kann Netlink-Socket nicht erzeugen: %s"
msgstr "monotone Uhr kann nicht gelesen werden: %s"
# @Simon: not perfect but I cannot get nearer right now.
#: util.c:579
@@ -188,11 +188,11 @@ msgstr "Unberechtigte DNS-Anfragen von Windows-Rechnern nicht weiterleiten."
#: option.c:404
msgid "Don't include IPv4 addresses in DNS answers."
msgstr ""
msgstr "Keine IPv4-Adressen in DNS-Antworten inkludieren."
#: option.c:405
msgid "Don't include IPv6 addresses in DNS answers."
msgstr ""
msgstr "Keine IPv6-Adressen in DNS-Antworten inkludieren."
#: option.c:406
msgid "Enable DHCP in the range given with lease duration."
@@ -313,7 +313,7 @@ msgstr "Fehlerhafte Suchergebnisse NICHT zwischenspeichern."
#: option.c:434
msgid "Use expired cache data for faster reply."
msgstr ""
msgstr "Verwende abgelaufene Cachedaten für schnellere Antwort."
#: option.c:435
#, c-format
@@ -347,7 +347,7 @@ msgstr "Ausgehenden Port für DNS-Anfragen an vorgelagerte Server erzwingen."
#: option.c:442
msgid "Set maximum number of random originating ports for a query."
msgstr ""
msgstr "Setze die maximale Anzahl zufälliger Ursprungsports für eine Abfrage."
#: option.c:443
msgid "Do NOT read resolv.conf."
@@ -404,7 +404,7 @@ msgstr "Spezifiziere untere Gültigkeitsdauergrenze für Zwischenspeicher."
#: option.c:456
msgid "Retry DNS queries after this many milliseconds."
msgstr ""
msgstr "DNS-Abfragen nach so vielen Millisekunden wiederholen."
#: option.c:457
#, c-format
@@ -520,7 +520,7 @@ msgstr "Konfiguration aus allen Dateien in diesem Verzeichnis lesen."
#: option.c:484
msgid "Execute file and read configuration from stdin."
msgstr ""
msgstr "Führe Datei aus und lese die Konfiguration aus stdin."
#: option.c:485
msgid "Log to this syslog facility or file. (defaults to DAEMON)"
@@ -680,7 +680,7 @@ msgstr "Anfragende MAC-Adresse in die weiterleitende DNS-Anfrage einfügen."
#: option.c:523
msgid "Strip MAC information from queries."
msgstr ""
msgstr "Entferne die MAC-Information von Abfragen."
#: option.c:524
msgid "Add specified IP subnet to forwarded DNS queries."
@@ -688,7 +688,7 @@ msgstr "Füge spezifiziertes IP-Subnetz an weitergeleiteten DNS-Anfragen hinzu."
#: option.c:525
msgid "Strip ECS information from queries."
msgstr ""
msgstr "Entferne die ECS-Information von Abfragen."
#: option.c:526
msgid "Add client identification to forwarded DNS queries."
@@ -773,9 +773,8 @@ msgid "Specify ipsets to which matching domains should be added"
msgstr "Spezifiziere IPSets, zu denen passende Domains hinzugefügt werden sollen"
#: option.c:546
#, fuzzy
msgid "Specify nftables sets to which matching domains should be added"
msgstr "Spezifiziere IPSets, zu denen passende Domains hinzugefügt werden sollen"
msgstr "Geben Sie nftables sets an, zu denen passende Domänen hinzugefügt werden sollen"
#: option.c:547
msgid "Enable filtering of DNS queries with connection-track marks."
@@ -880,7 +879,7 @@ msgstr "Protokolliere kein Routine-TFTP."
#: option.c:572
msgid "Suppress round-robin ordering of DNS records."
msgstr ""
msgstr "Unterdrückt die Round-Robin-Sortierung von DNS-Einträgen."
#: option.c:802
#, c-format
@@ -915,11 +914,11 @@ msgstr "Schnittstellenbindung nicht unterstützt"
#: option.c:955
msgid "Cannot resolve server name"
msgstr ""
msgstr "Servername kann nicht aufgelöst werden"
#: option.c:991
msgid "cannot use IPv4 server address with IPv6 source address"
msgstr ""
msgstr "IPv4-Serveradresse kann nicht mit IPv6-Quelladresse verwendet werden"
#: option.c:997 option.c:1043
msgid "interface can only be specified once"
@@ -931,21 +930,19 @@ msgstr "Fehlerhafter Schnittestellenname"
#: option.c:1037
msgid "cannot use IPv6 server address with IPv4 source address"
msgstr ""
msgstr "IPv6-Serveradresse kann nicht mit IPv4-Quelladresse verwendet werden"
#: option.c:1124
#, fuzzy
msgid "bad IPv4 prefix length"
msgstr "fehlerhafte Präfixlänge"
msgstr "ungültige IPv4-Präfixlänge"
#: option.c:1155 option.c:1165 option.c:1240 option.c:1250 option.c:5360
msgid "error"
msgstr "Fehler"
#: option.c:1207
#, fuzzy
msgid "bad IPv6 prefix length"
msgstr "fehlerhafte Präfixlänge"
msgstr "ungültige IPv6-Präfixlänge"
#: option.c:1467
msgid "inappropriate vendor:"
@@ -1034,7 +1031,6 @@ msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
msgstr "Neuübersetzung mit HAVE_LUASCRIPT nötig, um benutzerdefinierte Lua-Skripte auszuführen"
#: option.c:2447
#, fuzzy
msgid "invalid auth-zone"
msgstr "unzulässiger Alias-Bereich"
@@ -1059,9 +1055,8 @@ msgid "recompile with HAVE_IPSET defined to enable ipset directives"
msgstr "Neuübersetzung mit HAVE_IPSET nötig, um IPSet-Direktiven zu aktivieren"
#: option.c:3117
#, fuzzy
msgid "recompile with HAVE_NFTSET defined to enable nftset directives"
msgstr "Neuübersetzung mit HAVE_IPSET nötig, um IPSet-Direktiven zu aktivieren"
msgstr "Neukompilieren mit definiertem HAVE_NFTSET, um NFTSET-Direktiven zu aktivieren"
#: option.c:3192 option.c:3210
msgid "recompile with HAVE_CONNTRACK defined to enable connmark-allowlist directives"
@@ -1259,7 +1254,7 @@ msgstr "unzulässige Option"
#: option.c:5363
#, c-format
msgid " in output from %s"
msgstr ""
msgstr " in der Ausgabe von %s"
#: option.c:5365
#, c-format
@@ -1272,9 +1267,9 @@ msgid "read %s"
msgstr "%s gelesen"
#: option.c:5446
#, fuzzy, c-format
#, c-format
msgid "cannot execute %s: %s"
msgstr "kann %s nicht erstellen: %s"
msgstr "kann %s nicht ausführen: %s"
#: option.c:5454 option.c:5615 tftp.c:790
#, c-format
@@ -1282,14 +1277,14 @@ msgid "cannot read %s: %s"
msgstr "kann %s nicht lesen: %s"
#: option.c:5473
#, fuzzy, c-format
#, c-format
msgid "error executing %s: %s"
msgstr "konnte %s nicht ausführen: %s"
msgstr "Fehler bei der Ausführung von %s: %s"
#: option.c:5476
#, c-format
msgid "%s returns non-zero error code"
msgstr ""
msgstr "%s gibt einen Fehlercode ungleich Null zurück"
#: option.c:5775
msgid "junk found in command line"
@@ -1399,14 +1394,14 @@ msgid "reducing DNS packet size for nameserver %s to %d"
msgstr "Reduziere die DNS-Paketgröße für Nameserver %s auf %d"
#: forward.c:1565
#, fuzzy, c-format
#, c-format
msgid "ignoring query from non-local network %s (logged only once)"
msgstr "Ignoriere Anfrage von auswärtigem Netzwerk"
msgstr "Ignoriere Abfrage von nicht-lokalen Netzwerk %s (Nur einmal protokolliert)"
#: forward.c:2139
#, fuzzy, c-format
#, c-format
msgid "ignoring query from non-local network %s"
msgstr "Ignoriere Anfrage von auswärtigem Netzwerk"
msgstr "Ignoriere Abfrage von nicht-lokalen Netzwerk %s"
#: forward.c:2501
#, c-format
@@ -1488,7 +1483,7 @@ msgstr "ignoriere Namensserver %s - kann Socket nicht erzeugen/binden: %s"
#: network.c:1643
msgid "more servers are defined but not logged"
msgstr ""
msgstr "mehr Server sind definiert aber nicht protokolliert"
#: network.c:1654
msgid "(no DNSSEC)"
@@ -1605,7 +1600,7 @@ msgstr "max_port darf nicht kleiner als min_port sein"
#: dnsmasq.c:271
msgid "port_limit must not be larger than available port range"
msgstr ""
msgstr "port_limit darf nicht größer als der verfügbare Portbereich sein"
#: dnsmasq.c:278
msgid "--auth-server required when an auth zone is defined."
@@ -1810,9 +1805,9 @@ msgid "restricting maximum simultaneous TFTP transfers to %d"
msgstr "Begrenze gleichzeitige TFTP-Übertragungen auf maximal %d"
#: dnsmasq.c:1095
#, fuzzy, c-format
#, c-format
msgid "error binding DHCP socket to device %s"
msgstr "Fehler beim Senden des DHCP-Pakets an %s: %s"
msgstr "Fehler beim Binden des DHCP-Sockets an Gerät %s"
#: dnsmasq.c:1229
msgid "connected to system DBus"
@@ -1981,19 +1976,19 @@ msgid "read %s - %d addresses"
msgstr "%s gelesen - %d Adressen"
#: dhcp.c:1136
#, fuzzy, c-format
#, c-format
msgid "Cannot broadcast DHCP relay via interface %s"
msgstr "Kann nicht zum DHCPv6 Server multicasten ohne korrekte Schnittstelle"
msgstr "DHCP-Relay kann nicht über die Schnittstelle %s gesendet werden"
#: dhcp.c:1160
#, c-format
msgid "broadcast via %s"
msgstr ""
msgstr "broadcast via %s"
#: dhcp.c:1163 rfc3315.c:2219
#, fuzzy, c-format
#, c-format
msgid "DHCP relay at %s -> %s"
msgstr "DHCP Relais %s -> %s"
msgstr "DHCP-Relay bei %s -> %s"
#: lease.c:64
#, c-format
@@ -2405,14 +2400,14 @@ msgid "release received"
msgstr "Freigabe empfangen"
#: rfc3315.c:2200
#, fuzzy, c-format
#, c-format
msgid "Cannot multicast DHCP relay via interface %s"
msgstr "Kann nicht zum DHCPv6 Server multicasten ohne korrekte Schnittstelle"
msgstr "Multicast-DHCP-Relay über Schnittstelle %s nicht möglich"
#: rfc3315.c:2216
#, c-format
msgid "multicast via %s"
msgstr ""
msgstr "multicast via %s"
#: dhcp-common.c:187
#, c-format
@@ -2484,9 +2479,9 @@ msgid "router advertisement on %s%s"
msgstr "Router-Advertisment auf %s%s"
#: dhcp-common.c:1043
#, fuzzy, c-format
#, c-format
msgid "DHCP relay from %s via %s"
msgstr "DHCP Weiterleitung von %s nach %s"
msgstr "DHCP-Relay von %s über %s"
#: dhcp-common.c:1045
#, c-format
@@ -2621,9 +2616,9 @@ msgid "Insecure DS reply received for %s, check domain configuration and upstrea
msgstr "Unsichere DS-Antwort für %s, bitte Domainkonfiguration und Upstream DNS-Server für DNSSEC-Unterstützung überprüfen"
#: blockdata.c:55
#, fuzzy, c-format
#, c-format
msgid "pool memory in use %zu, max %zu, allocated %zu"
msgstr "Speicherpool in Benutzung %u, Max %u, zugewiesen %u"
msgstr "Speicherpool in Benutzung %zu, Max %zu, zugewiesen %zu"
#: tables.c:61
#, c-format
@@ -2695,24 +2690,23 @@ msgid "bad dynamic directory %s: %s"
msgstr "fehlerhaftes dynamisches Verzeichnis %s: %s"
#: inotify.c:186
#, fuzzy
msgid "not a directory"
msgstr "Kann auf Verzeichnis %s nicht zugreifen: %s"
msgstr "ist kein Verzeichnis"
#: inotify.c:299
#, c-format
msgid "inotify: %s removed"
msgstr ""
msgstr "inotify: %s entfernt"
#: inotify.c:301
#, fuzzy, c-format
#, c-format
msgid "inotify: %s new or modified"
msgstr "inotify, neue oder geänderte Datei %s"
msgstr "inotify: %s neu oder modifiziert"
#: inotify.c:309
#, c-format
msgid "inotify: flushed %u names read from %s"
msgstr ""
msgstr "inotify: %u Namen gelöscht, aus %s gelesen"
#: dump.c:68
#, c-format
@@ -2729,14 +2723,14 @@ msgid "failed to write packet dump"
msgstr "schreiben des Paketmitschnitts fehlgeschlagen"
#: dump.c:289
#, fuzzy, c-format
#, c-format
msgid "%u dumping packet %u mask 0x%04x"
msgstr "Lade UDP Paket %u Maske 0x%04x ab"
msgstr "%u dumpe Paket %u Maske 0x%04x"
#: dump.c:291
#, fuzzy, c-format
#, c-format
msgid "dumping packet %u mask 0x%04x"
msgstr "Lade UDP Paket %u Maske 0x%04x ab"
msgstr "Dumpe Packet %u Make 0x%04x"
#: ubus.c:79
#, c-format
@@ -2770,9 +2764,8 @@ msgid "Failed to create SHA-256 hash object"
msgstr "Kann SHA-256-Hash-Objekt nicht erstellen"
#: nftset.c:35
#, fuzzy
msgid "failed to create nftset context"
msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s"
msgstr "Fehler beim Erstellen des NFTSET-Kontexts"
#~ msgid "bad IPv4 prefix"
#~ msgstr "fehlerhaftes IPv4-Präfix"

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -35,7 +35,7 @@ struct arp_record {
static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
static time_t last = 0;
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
static int filter_mac(int family, void *addrp, char *mac, size_t maclen, void *parmv)
{
struct arp_record *arp;
@@ -152,7 +152,7 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
if (arp->status != ARP_EMPTY)
arp->status = ARP_MARK;
iface_enumerate(AF_UNSPEC, NULL, filter_mac);
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)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -96,8 +96,8 @@ 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, int do_bit, int have_pseudoheader)
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;
@@ -137,7 +137,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
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);
@@ -513,7 +513,7 @@ 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))))
{
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
log_query(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))
@@ -868,7 +868,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
/* 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(F_AUTH, "reply", NULL, "truncated", 0);
}
if ((auth || local_query) && nxdomain)
SET_RCODE(header, NXDOMAIN);
@@ -890,10 +896,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
return resize_packet(header, ansp - (unsigned char *)header, NULL, 0);
}
/* Advertise our packet size limit in our reply */
if (have_pseudoheader)
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
return ansp - (unsigned char *)header;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -101,7 +101,7 @@ static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
memcpy(block->key, data, blen);
data += blen;
}
else if (!read_write(fd, block->key, blen, 1))
else if (!read_write(fd, block->key, blen, RW_READ))
{
/* failed read free partial chain */
blockdata_free(ret);
@@ -193,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;
@@ -228,7 +228,7 @@ 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, 0);
read_write(fd, block->key, blen, RW_WRITE);
len -= blen;
}
}

186
src/bpf.c
View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -47,7 +47,7 @@ static union all_addr del_addr;
#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,7 +100,7 @@ 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 errsave, fd = -1, ret = 0;
@@ -126,112 +126,110 @@ int iface_enumerate(int family, void *parm, int (*callback)())
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.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;
}
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.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));
safe_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;
}
#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:
errsave = errno;
freeifaddrs(head);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -101,6 +101,7 @@ static const struct {
{ 63, "ZONEMD" }, /* Message Digest Over Zone Data [RFC8976] ZONEMD/zonemd-completed-template 2018-12-12*/
{ 64, "SVCB" }, /* Service Binding [draft-ietf-dnsop-svcb-https-00] SVCB/svcb-completed-template 2020-06-30*/
{ 65, "HTTPS" }, /* HTTPS Binding [draft-ietf-dnsop-svcb-https-00] HTTPS/https-completed-template 2020-06-30*/
{ 66, "DSYNC" }, /* Endpoint discovery for delegation synchronization [draft-ietf-dnsop-generalized-notify-03] DSYNC/dsync-completed-template 2024-12-10 */
{ 99, "SPF" }, /* [RFC7208] */
{ 100, "UINFO" }, /* [IANA-Reserved] */
{ 101, "UID" }, /* [IANA-Reserved] */
@@ -112,6 +113,7 @@ static const struct {
{ 107, "LP" }, /* [RFC6742] ILNP/lp-completed-template */
{ 108, "EUI48" }, /* an EUI-48 address [RFC7043] EUI48/eui48-completed-template 2013-03-27*/
{ 109, "EUI64" }, /* an EUI-64 address [RFC7043] EUI64/eui64-completed-template 2013-03-27*/
{ 128, "NXNAME" }, /* NXDOMAIN indicator for Compact Denial of Existence https://www.iana.org/go/draft-ietf-dnsop-compact-denial-of-existence-04 */
{ 249, "TKEY" }, /* Transaction Key [RFC2930] */
{ 250, "TSIG" }, /* Transaction Signature [RFC8945] */
{ 251, "IXFR" }, /* incremental transfer [RFC1995] */
@@ -125,6 +127,9 @@ static const struct {
{ 259, "DOA" }, /* Digital Object Architecture [draft-durand-doa-over-dns] DOA/doa-completed-template 2017-08-30*/
{ 260, "AMTRELAY" }, /* Automatic Multicast Tunneling Relay [RFC8777] AMTRELAY/amtrelay-completed-template 2019-02-06*/
{ 261, "RESINFO" }, /* Resolver Information as Key/Value Pairs https://datatracker.ietf.org/doc/draft-ietf-add-resolver-info/06/ */
{ 262, "WALLET" }, /* Public wallet address https://www.iana.org/assignments/dns-parameters/WALLET/wallet-completed-template */
{ 263, "CLA" }, /* BP Convergence Layer Adapter https://www.iana.org/go/draft-johnson-dns-ipn-cla-07 */
{ 264, "IPN" }, /* BP Node Number https://www.iana.org/go/draft-johnson-dns-ipn-cla-07 */
{ 32768, "TA" }, /* DNSSEC Trust Authorities [Sam_Weiler][http://cameo.library.cmu.edu/][ Deploying DNSSEC Without a Signed Root. Technical Report 1999-19, Information Networking Institute, Carnegie Mellon University, April 2004.] 2005-12-13*/
{ 32769, "DLV" }, /* DNSSEC Lookaside Validation (OBSOLETE) [RFC8749][RFC4431] */
};
@@ -474,7 +479,7 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
{
int rrmatch = 0;
if (crecp->flags & flags & F_RR)
if (addr && (crecp->flags & flags & F_RR))
{
unsigned short rrc = (crecp->flags & F_KEYTAG) ? crecp->addr.rrblock.rrtype : crecp->addr.rrdata.rrtype;
unsigned short rra = (flags & F_KEYTAG) ? addr->rrblock.rrtype : addr->rrdata.rrtype;
@@ -798,36 +803,32 @@ void cache_end_insert(void)
u16 class = new_chain->uid;
#endif
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)name, m, 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)name, m, RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), RW_WRITE);
if (flags & F_RR)
{
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
if (flags & F_RR)
{
/* A negative RR entry is possible and has no data, obviously. */
if (!(flags & F_NEG) && (flags & F_KEYTAG))
blockdata_write(new_chain->addr.rrblock.rrdata, new_chain->addr.rrblock.datalen, daemon->pipe_to_parent);
}
#ifdef HAVE_DNSSEC
if (flags & F_DNSKEY)
{
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
}
else if (flags & F_DS)
{
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), 0);
/* A negative DS entry is possible and has no data, obviously. */
if (!(flags & F_NEG))
blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
}
#endif
/* A negative RR entry is possible and has no data, obviously. */
if (!(flags & F_NEG) && (flags & F_KEYTAG))
blockdata_write(new_chain->addr.rrblock.rrdata, new_chain->addr.rrblock.datalen, daemon->pipe_to_parent);
}
#ifdef HAVE_DNSSEC
if (flags & F_DNSKEY)
{
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), RW_WRITE);
blockdata_write(new_chain->addr.key.keydata, new_chain->addr.key.keylen, daemon->pipe_to_parent);
}
else if (flags & F_DS)
{
read_write(daemon->pipe_to_parent, (unsigned char *)&class, sizeof(class), RW_WRITE);
/* A negative DS entry is possible and has no data, obviously. */
if (!(flags & F_NEG))
blockdata_write(new_chain->addr.ds.keydata, new_chain->addr.ds.keylen, daemon->pipe_to_parent);
}
#endif
}
}
@@ -838,7 +839,21 @@ void cache_end_insert(void)
if (daemon->pipe_to_parent != -1)
{
ssize_t m = -1;
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), 0);
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), RW_WRITE);
#ifdef HAVE_DNSSEC
/* Sneak out possibly updated crypto HWM values. */
read_write(daemon->pipe_to_parent,
(unsigned char *)&daemon->metrics[METRIC_CRYPTO_HWM],
sizeof(daemon->metrics[METRIC_CRYPTO_HWM]), RW_WRITE);
read_write(daemon->pipe_to_parent,
(unsigned char *)&daemon->metrics[METRIC_SIG_FAIL_HWM],
sizeof(daemon->metrics[METRIC_SIG_FAIL_HWM]), RW_WRITE);
read_write(daemon->pipe_to_parent,
(unsigned char *)&daemon->metrics[METRIC_WORK_HWM],
sizeof(daemon->metrics[METRIC_WORK_HWM]), RW_WRITE);
#endif
}
new_chain = NULL;
@@ -857,21 +872,88 @@ int cache_recv_insert(time_t now, int fd)
cache_start_insert();
while(1)
while (1)
{
if (!read_write(fd, (unsigned char *)&m, sizeof(m), 1))
if (!read_write(fd, (unsigned char *)&m, sizeof(m), RW_READ))
return 0;
if (m == -1)
{
#ifdef HAVE_DNSSEC
/* Sneak in possibly updated crypto HWM. */
unsigned int val;
if (!read_write(fd, (unsigned char *)&val, sizeof(val), RW_READ))
return 0;
if (val > daemon->metrics[METRIC_CRYPTO_HWM])
daemon->metrics[METRIC_CRYPTO_HWM] = val;
if (!read_write(fd, (unsigned char *)&val, sizeof(val), RW_READ))
return 0;
if (val > daemon->metrics[METRIC_SIG_FAIL_HWM])
daemon->metrics[METRIC_SIG_FAIL_HWM] = val;
if (!read_write(fd, (unsigned char *)&val, sizeof(val), RW_READ))
return 0;
if (val > daemon->metrics[METRIC_WORK_HWM])
daemon->metrics[METRIC_WORK_HWM] = val;
#endif
cache_end_insert();
return 1;
}
if (!read_write(fd, (unsigned char *)daemon->namebuff, m, 1) ||
!read_write(fd, (unsigned char *)&ttd, sizeof(ttd), 1) ||
!read_write(fd, (unsigned char *)&flags, sizeof(flags), 1))
#ifdef HAVE_DNSSEC
/* UDP validation moved to TCP to avoid truncation.
Restart UDP validation process with the returned result. */
if (m == -2)
{
int status, uid, keycount, validatecount;
int *keycountp, *validatecountp;
size_t ret_len;
struct frec *forward;
if (!read_write(fd, (unsigned char *)&status, sizeof(status), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&ret_len, sizeof(ret_len), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)daemon->packet, ret_len, RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&forward, sizeof(forward), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&uid, sizeof(uid), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&keycount, sizeof(keycount), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&keycountp, sizeof(keycountp), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&validatecount, sizeof(validatecount), RW_READ))
return 0;
if (!read_write(fd, (unsigned char *)&validatecountp, sizeof(validatecountp), RW_READ))
return 0;
/* There's a tiny chance that the frec may have been freed
and reused before the TCP process returns. Detect that with
the uid field which is unique modulo 2^32 for each use. */
if (uid == forward->uid)
{
/* repatriate the work counters from the child process. */
*keycountp = keycount;
*validatecountp = validatecount;
if (!forward->dependent)
return_reply(now, forward, (struct dns_header *)daemon->packet, ret_len, status);
else
pop_and_retry_query(forward, status, now);
}
return 1;
}
#endif
if (!read_write(fd, (unsigned char *)daemon->namebuff, m, RW_READ) ||
!read_write(fd, (unsigned char *)&ttd, sizeof(ttd), RW_READ) ||
!read_write(fd, (unsigned char *)&flags, sizeof(flags), RW_READ) ||
!read_write(fd, (unsigned char *)&addr, sizeof(addr), RW_READ))
return 0;
daemon->namebuff[m] = 0;
@@ -902,30 +984,23 @@ int cache_recv_insert(time_t now, int fd)
{
unsigned short class = C_IN;
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_RR))
{
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
return 0;
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
return 0;
if ((flags & F_RR) && !(flags & F_NEG) && (flags & F_KEYTAG)
&& !(addr.rrblock.rrdata = blockdata_read(fd, addr.rrblock.datalen)))
return 0;
#ifdef HAVE_DNSSEC
if (flags & F_DNSKEY)
{
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
return 0;
}
else if (flags & F_DS)
{
if (!read_write(fd, (unsigned char *)&class, sizeof(class), 1) ||
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
return 0;
}
#endif
if (flags & F_DNSKEY)
{
if (!read_write(fd, (unsigned char *)&class, sizeof(class), RW_READ) ||
!(addr.key.keydata = blockdata_read(fd, addr.key.keylen)))
return 0;
}
else if (flags & F_DS)
{
if (!read_write(fd, (unsigned char *)&class, sizeof(class), RW_READ) ||
(!(flags & F_NEG) && !(addr.key.keydata = blockdata_read(fd, addr.key.keylen))))
return 0;
}
#endif
crecp = really_insert(daemon->namebuff, &addr, class, now, ttl, flags);
}
}
@@ -1378,11 +1453,17 @@ void cache_reload(void)
cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
cache->ttd = daemon->local_ttl;
cache->name.namep = ds->name;
cache->addr.ds.keylen = ds->digestlen;
cache->addr.ds.algo = ds->algo;
cache->addr.ds.keytag = ds->keytag;
cache->addr.ds.digest = ds->digest_type;
cache->uid = ds->class;
if (ds->digestlen != 0)
{
cache->addr.ds.keylen = ds->digestlen;
cache->addr.ds.algo = ds->algo;
cache->addr.ds.keytag = ds->keytag;
cache->addr.ds.digest = ds->digest_type;
}
else
cache->flags |= F_NEG | F_DNSSECOK | F_NO_RR;
cache_hash(cache);
make_non_terminals(cache);
}
@@ -1782,15 +1863,31 @@ int cache_make_stat(struct txt_record *t)
#endif
/* There can be names in the cache containing control chars, don't
mess up logging or open security holes. */
mess up logging or open security holes. Also convert to all-LC
so that 0x20-encoding doesn't make logs look like ransom notes
made out of letters cut from a newspaper.
Overwrites daemon->workspacename */
static char *sanitise(char *name)
{
unsigned char *r;
unsigned char *r = (unsigned char *)name;
if (name)
for (r = (unsigned char *)name; *r; r++)
if (!isprint((int)*r))
return "<name unprintable>";
{
char *d = name = daemon->workspacename;
for (; *r; r++, d++)
if (!isprint((int)*r))
return "<name unprintable>";
else
{
unsigned char c = *r;
*d = (char)((c >= 'A' && c <= 'Z') ? c + 'a' - 'A' : c);
}
*d = 0;
}
return name;
}
@@ -1809,8 +1906,18 @@ static void dump_cache_entry(struct crec *cache, time_t now)
p = buff;
*a = 0;
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
n = "<Root>";
if (cache->flags & F_REVERSE)
{
if ((cache->flags & F_NEG))
n = "";
}
else
{
if (strlen(n) == 0)
n = "<Root>";
}
p += sprintf(p, "%-30.30s ", sanitise(n));
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
a = sanitise(cache_get_cname_target(cache));
@@ -1893,6 +2000,11 @@ void dump_cache(time_t now)
#ifdef HAVE_AUTH
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
#endif
#ifdef HAVE_DNSSEC
my_syslog(LOG_INFO, _("DNSSEC per-query subqueries HWM %u"), daemon->metrics[METRIC_WORK_HWM]);
my_syslog(LOG_INFO, _("DNSSEC per-query crypto work HWM %u"), daemon->metrics[METRIC_CRYPTO_HWM]);
my_syslog(LOG_INFO, _("DNSSEC per-RRSet signature fails HWM %u"), daemon->metrics[METRIC_SIG_FAIL_HWM]);
#endif
blockdata_report();
my_syslog(LOG_INFO, _("child processes for TCP requests: in use %zu, highest since last SIGUSR1 %zu, max allowed %zu."),
@@ -2052,6 +2164,11 @@ static char *edestr(int ede)
case EDE_NO_AUTH: return "no reachable authority";
case EDE_NETERR: return "network error";
case EDE_INVALID_DATA: return "invalid data";
case EDE_SIG_E_B_V: return "signature expired before valid";
case EDE_TOO_EARLY: return "too early";
case EDE_UNS_NS3_ITER: return "unsupported NSEC3 iterations value";
case EDE_UNABLE_POLICY: return "uanble to conform to policy";
case EDE_SYNTHESIZED: return "synthesized";
default: return "unknown";
}
}
@@ -2171,12 +2288,12 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
}
else if (flags & F_AUTH)
source = "auth";
else if (flags & F_DNSSEC)
else if (flags & F_DNSSEC)
{
source = arg;
verb = "to";
}
else if (flags & F_SERVER)
else if (flags & F_SERVER)
{
source = "forwarded";
verb = "to";
@@ -2205,12 +2322,21 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
if (option_bool(OPT_EXTRALOG))
{
if (flags & F_NOEXTRA)
my_syslog(LOG_INFO, "%u %s %s%s%s %s%s", daemon->log_display_id, source, name, gap, verb, dest, extra);
int display_id = daemon->log_display_id;
char *proto = "";
if (option_bool(OPT_LOG_PROTO))
proto = (display_id < 0) ? "TCP " : "UDP ";
if (display_id < 0)
display_id = -display_id;
if (flags & F_NOEXTRA || !daemon->log_source_addr)
my_syslog(LOG_INFO, "%s%u %s %s%s%s %s%s", proto, display_id, source, name, gap, verb, dest, extra);
else
{
int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
my_syslog(LOG_INFO, "%u %s/%u %s %s%s%s %s%s", daemon->log_display_id, daemon->addrbuff2, port, source, name, gap, verb, dest, extra);
my_syslog(LOG_INFO, "%s%u %s/%u %s %s%s%s %s%s", proto, display_id, daemon->addrbuff2, port, source, name, gap, verb, dest, extra);
}
}
else

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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,11 +18,15 @@
#define MAX_PROCS 20 /* default max no children for TCP requests */
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
#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 SAFE_PKTSZ 1232 /* "go anywhere" UDP packet size, see https://dnsflagday.net/2020/ */
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
#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 */
@@ -126,9 +130,6 @@ HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
HAVE_CRYPTOHASH
include just hash function from crypto library, but no DNSSEC.
HAVE_DNSSEC
include DNSSEC validator.
@@ -197,7 +198,6 @@ RESOLVFILE
/* #define HAVE_IDN */
/* #define HAVE_LIBIDN2 */
/* #define HAVE_CONNTRACK */
/* #define HAVE_CRYPTOHASH */
/* #define HAVE_DNSSEC */
/* #define HAVE_NFTSET */
@@ -363,6 +363,11 @@ HAVE_SOCKADDR_SA_LEN
#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.
DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
@@ -435,10 +440,6 @@ static char *compile_opts =
"no-"
#endif
"auth "
#if !defined(HAVE_CRYPTOHASH) && !defined(HAVE_DNSSEC)
"no-"
#endif
"cryptohash "
#ifndef HAVE_DNSSEC
"no-"
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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,7 +16,7 @@
#include "dnsmasq.h"
#if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
#if defined(HAVE_DNSSEC)
/* Minimal version of nettle */
@@ -30,9 +30,6 @@
#define MIN_VERSION(major, minor) ((NETTLE_VERSION_MAJOR == (major) && NETTLE_VERSION_MINOR >= (minor)) || \
(NETTLE_VERSION_MAJOR > (major)))
#endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
#if defined(HAVE_DNSSEC)
#include <nettle/rsa.h>
#include <nettle/ecdsa.h>
#include <nettle/ecc-curve.h>
@@ -476,9 +473,6 @@ char *nsec3_digest_name(int digest)
}
}
#endif /* defined(HAVE_DNSSEC) */
#if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
/* Find pointer to correct hash function in nettle library */
const struct nettle_hash *hash_find(char *name)
{
@@ -509,4 +503,4 @@ const struct nettle_hash *hash_find(char *name)
#endif
}
#endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
#endif /* defined(HAVE_DNSSEC) */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -485,28 +485,37 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
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 NULL;
return reply;
}
#ifdef HAVE_DHCP
@@ -829,23 +838,37 @@ DBusHandlerResult message_handler(DBusConnection *connection,
else if (strcmp(method, "SetFilterA") == 0)
{
static int done = 0;
static struct rrlist list = { T_A, NULL };
static struct rrlist list = { 0, NULL };
dbus_bool_t enabled;
if (!done)
if (!(reply = dbus_get_bool(message, &enabled, "filter-A")))
{
list.next = daemon->filter_rr;
daemon->filter_rr = &list;
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 = { T_AAAA, NULL };
if (!done)
static struct rrlist list = { 0, NULL };
dbus_bool_t enabled;
if (!(reply = dbus_get_bool(message, &enabled, "filter-AAAA")))
{
list.next = daemon->filter_rr;
daemon->filter_rr = &list;
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)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -128,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)
@@ -163,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)
@@ -176,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))
@@ -186,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)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -32,7 +32,7 @@ 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(int iface_index, struct dhcp_packet *mess, size_t sz);
static void relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz);
static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface);
static int make_fd(int port)
@@ -317,7 +317,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;
@@ -327,17 +327,10 @@ void dhcp_packet(time_t now, int pxe_fd)
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
}
if (relay_upstream4(iface_index, mess, (size_t)sz))
return;
if (!iface_enumerate(AF_INET, &parm, complete_context))
if (!iface_enumerate(AF_INET, &parm, (callback_t){.af_inet=complete_context}))
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 (relay_upstream4(iface_index, mess, (size_t)sz))
return;
relay_upstream4(iface_index, mess, (size_t)sz);
/* May have configured relay, but not DHCP server */
if (!daemon->dhcp)
@@ -398,6 +391,10 @@ void dhcp_packet(time_t now, int pxe_fd)
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 = rcvd_iface_index;
@@ -1073,14 +1070,14 @@ char *host_from_dns(struct in_addr addr)
return NULL;
}
static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
static void relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
{
struct in_addr giaddr = mess->giaddr;
u8 hops = mess->hops;
struct dhcp_relay *relay;
if (mess->op != BOOTREQUEST)
return 0;
return;
for (relay = daemon->relay4; relay; relay = relay->next)
if (relay->iface_index != 0 && relay->iface_index == iface_index)
@@ -1088,7 +1085,7 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
/* No relay config. */
if (!relay)
return 0;
return;
for (; relay; relay = relay->next)
if (relay->iface_index != 0 && relay->iface_index == iface_index)
@@ -1121,6 +1118,9 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
to.sa.sa_family = AF_INET;
to.in.sin_addr = relay->server.addr4;
to.in.sin_port = htons(relay->port);
#ifdef HAVE_SOCKADDR_SA_LEN
to.in.sin_len = sizeof(struct sockaddr_in);
#endif
/* Broadcasting to server. */
if (relay->server.addr4.s_addr == 0)
@@ -1164,7 +1164,8 @@ static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
}
}
return 1;
/* restore in case of a local reply. */
mess->giaddr = giaddr;
}

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -239,7 +239,7 @@ void dhcp6_packet(time_t now)
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
return;
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
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
@@ -617,7 +617,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);
@@ -667,7 +667,7 @@ 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;
@@ -801,7 +801,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)
{
@@ -812,7 +812,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 */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -112,8 +112,11 @@
#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 {
@@ -139,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) \
@@ -155,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; \
@@ -173,7 +176,7 @@ 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))

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -32,6 +32,7 @@ static volatile int pipewrite;
static void set_dns_listeners(void);
static void set_tftp_listeners(void);
static void check_dns_listeners(time_t now);
static void do_tcp_connection(struct listener *listener, time_t now, int slot);
static void sig_handler(int sig);
static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev, char *msg);
@@ -61,6 +62,7 @@ int main (int argc, char **argv)
int need_cap_net_admin = 0;
int need_cap_net_raw = 0;
int need_cap_net_bind_service = 0;
int have_cap_chown = 0;
char *bound_device = NULL;
int did_bind = 0;
struct server *serv;
@@ -131,19 +133,12 @@ int main (int argc, char **argv)
'.' or NAME_ESCAPE then all would have to be escaped, so the
presentation format would be twice as long as the spec. */
daemon->keyname = safe_malloc((MAXDNAME * 2) + 1);
daemon->workspacename = safe_malloc((MAXDNAME * 2) + 1);
daemon->cname = safe_malloc((MAXDNAME * 2) + 1);
/* one char flag per possible RR in answer section (may get extended). */
daemon->rr_status_sz = 64;
daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
}
#endif
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
/* CONNTRACK UBUS code uses this buffer, so if not allocated above,
we need to allocate it here. */
if (option_bool(OPT_CMARK_ALST_EN) && !daemon->workspacename)
daemon->workspacename = safe_malloc((MAXDNAME * 2) + 1);
#endif
#ifdef HAVE_DHCP
if (!daemon->lease_file)
@@ -321,9 +316,12 @@ int main (int argc, char **argv)
{
dhcp_init();
# ifdef HAVE_LINUX_NETWORK
/* Need NET_RAW to send ping. */
if (!option_bool(OPT_NO_PING))
need_cap_net_raw = 1;
need_cap_net_admin = 1;
/* Need NET_ADMIN to change ARP cache if not always broadcasting. */
if (daemon->force_broadcast == NULL || daemon->force_broadcast->list != NULL)
need_cap_net_admin = 1;
# endif
}
@@ -415,7 +413,6 @@ int main (int argc, char **argv)
{
cache_init();
blockdata_init();
hash_questions_init();
/* Scale random socket pool by ftabsize, but
limit it based on available fds. */
@@ -429,8 +426,8 @@ int main (int argc, char **argv)
}
#ifdef HAVE_INOTIFY
if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
&& (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
if ((daemon->port != 0 && !option_bool(OPT_NO_RESOLV)) ||
daemon->dynamic_dirs)
inotify_dnsmasq_init();
else
daemon->inotifyfd = -1;
@@ -562,6 +559,8 @@ int main (int argc, char **argv)
data = safe_malloc(sizeof(*data) * capsize);
capget(hdr, data); /* Get current values, for verification */
have_cap_chown = data->permitted & (1 << CAP_CHOWN);
if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
fail = "NET_ADMIN";
else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
@@ -689,7 +688,7 @@ int main (int argc, char **argv)
if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
chown_warn = errno;
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), RW_WRITE))
err = 1;
else
{
@@ -875,7 +874,14 @@ int main (int argc, char **argv)
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
if (chown_warn != 0)
my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
{
#if defined(HAVE_LINUX_NETWORK)
if (chown_warn == EPERM && !have_cap_chown)
my_syslog(LOG_INFO, "chown of PID file %s failed: please add capability CAP_CHOWN", daemon->runfile);
else
#endif
my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
}
#ifdef HAVE_DBUS
if (option_bool(OPT_DBUS))
@@ -925,7 +931,8 @@ int main (int argc, char **argv)
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
for (ds = daemon->ds; ds; ds = ds->next)
my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
my_syslog(LOG_INFO,
ds->digestlen == 0 ? _("configured with negative trust anchor for %s") : _("configured with trust anchor for %s keytag %u"),
ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
}
#endif
@@ -957,7 +964,14 @@ int main (int argc, char **argv)
my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
daemon->resolv_files = NULL;
if (!daemon->servers)
my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
{
#ifdef HAVE_DBUS
if (option_bool(OPT_DBUS))
my_syslog(LOG_INFO, _("no upstream servers configured - please set them from DBus"));
else
#endif
my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
}
}
if (daemon->max_logs != 0)
@@ -1402,14 +1416,14 @@ static int read_event(int fd, struct event_desc *evp, char **msg)
{
char *buf;
if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), RW_READ))
return 0;
*msg = NULL;
if (evp->msg_sz != 0 &&
(buf = malloc(evp->msg_sz + 1)) &&
read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
read_write(fd, (unsigned char *)buf, evp->msg_sz, RW_READ))
{
buf[evp->msg_sz] = 0;
*msg = buf;
@@ -1472,7 +1486,7 @@ static void async_event(int pipe, time_t now)
{
pid_t p;
struct event_desc ev;
int i, check = 0;
int wstatus, i, check = 0;
char *msg;
/* NOTE: the memory used to return msg is leaked: use msgs in events only
@@ -1523,6 +1537,7 @@ static void async_event(int pipe, time_t now)
{
lease_prune(NULL, now);
lease_update_file(now);
lease_update_dns(0);
}
#ifdef HAVE_DHCP6
else if (daemon->doing_ra)
@@ -1534,7 +1549,7 @@ static void async_event(int pipe, time_t now)
case EVENT_CHILD:
/* See Stevens 5.10 */
while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
while ((p = waitpid(-1, &wstatus, WNOHANG)) != 0)
if (p == -1)
{
if (errno != EINTR)
@@ -1545,6 +1560,20 @@ static void async_event(int pipe, time_t now)
if (daemon->tcp_pids[i] == p)
{
daemon->tcp_pids[i] = 0;
if (!WIFEXITED(wstatus))
{
/* If a helper process dies, (eg with SIGSEV)
log that and attempt to patch things up so that the
parent can continue to function. */
my_syslog(LOG_WARNING, _("TCP helper process %u died unexpectedly"), (unsigned int)p);
if (daemon->tcp_pipes[i] != -1)
{
close(daemon->tcp_pipes[i]);
daemon->tcp_pipes[i] = -1;
}
}
/* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
if (daemon->tcp_pipes[i] == -1)
daemon->metrics[METRIC_TCP_CONNECTIONS]--;
@@ -1827,244 +1856,403 @@ static void check_dns_listeners(time_t now)
struct listener *listener;
struct randfd_list *rfl;
int i;
int pipefd[2];
/* Note that handling events here can create or destroy fds and
render the result of the last poll() call invalid. Once
we find an fd that needs service, do it, then return to go around the
poll() loop again. This avoid really, really, wierd bugs. */
if (!option_bool(OPT_DEBUG))
for (i = 0; i < daemon->max_procs; i++)
if (daemon->tcp_pipes[i] != -1 &&
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP))
{
/* Races. The child process can die before we read all of the data from the
pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
process, and tcp_pipes to -1 and close the FD when we read the last
of the data - indicated by cache_recv_insert returning zero.
The order of these events is indeterminate, and both are needed
to free the process slot. Once the child process has gone, poll()
returns POLLHUP, not POLLIN, so have to check for both here. */
if (!cache_recv_insert(now, daemon->tcp_pipes[i]))
{
close(daemon->tcp_pipes[i]);
daemon->tcp_pipes[i] = -1;
/* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
if (daemon->tcp_pids[i] == 0)
daemon->metrics[METRIC_TCP_CONNECTIONS]--;
}
return;
}
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (poll_check(serverfdp->fd, POLLIN))
reply_query(serverfdp->fd, now);
{
reply_query(serverfdp->fd, now);
return;
}
for (i = 0; i < daemon->numrrand; i++)
if (daemon->randomsocks[i].refcount != 0 &&
poll_check(daemon->randomsocks[i].fd, POLLIN))
reply_query(daemon->randomsocks[i].fd, now);
{
reply_query(daemon->randomsocks[i].fd, now);
return;
}
/* Check overflow random sockets too. */
for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
if (poll_check(rfl->rfd->fd, POLLIN))
reply_query(rfl->rfd->fd, now);
/* Races. The child process can die before we read all of the data from the
pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
process, and tcp_pipes to -1 and close the FD when we read the last
of the data - indicated by cache_recv_insert returning zero.
The order of these events is indeterminate, and both are needed
to free the process slot. Once the child process has gone, poll()
returns POLLHUP, not POLLIN, so have to check for both here. */
if (!option_bool(OPT_DEBUG))
for (i = 0; i < daemon->max_procs; i++)
if (daemon->tcp_pipes[i] != -1 &&
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
!cache_recv_insert(now, daemon->tcp_pipes[i]))
{
close(daemon->tcp_pipes[i]);
daemon->tcp_pipes[i] = -1;
/* tcp_pipes == -1 && tcp_pids == 0 required to free slot */
if (daemon->tcp_pids[i] == 0)
daemon->metrics[METRIC_TCP_CONNECTIONS]--;
}
{
reply_query(rfl->rfd->fd, now);
return;
}
for (listener = daemon->listeners; listener; listener = listener->next)
{
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
{
receive_query(listener, now);
return;
}
/* check to see if we have a free tcp process slot.
Note that we can't assume that because we had
at least one a poll() time, that we still do.
There may be more waiting connections after
poll() returns then free process slots. */
for (i = daemon->max_procs - 1; i >= 0; i--)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break;
if (i >= 0)
for (listener = daemon->listeners; listener; listener = listener->next)
if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
{
do_tcp_connection(listener, now, i);
return;
}
}
static void do_tcp_connection(struct listener *listener, time_t now, int slot)
{
int confd, client_ok = 1;
struct irec *iface = NULL;
pid_t p;
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
unsigned char a = 0, *buff;
struct server *s;
int flags, auth_dns;
struct in_addr netmask;
int pipefd[2];
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
return;
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
{
closeconandreturn:
shutdown(confd, SHUT_RDWR);
close(confd);
return;
}
/* Make sure that the interface list is up-to-date.
We do this here as we may need the results below, and
the DNS code needs them for --interface-name stuff.
Multiple calls to enumerate_interfaces() per select loop are
inhibited, so calls to it in the child process (which doesn't select())
have no effect. This avoids two processes reading from the same
netlink fd and screwing the pooch entirely.
*/
enumerate_interfaces(0);
if (option_bool(OPT_NOWILD))
iface = listener->iface; /* May be NULL */
else
{
int if_index;
char intr_name[IF_NAMESIZE];
/* check to see if we have a free tcp process slot.
Note that we can't assume that because we had
at least one a poll() time, that we still do.
There may be more waiting connections after
poll() returns then free process slots. */
/* if we can find the arrival interface, check it's one that's allowed */
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
indextoname(listener->tcpfd, if_index, intr_name))
{
union all_addr addr;
if (tcp_addr.sa.sa_family == AF_INET6)
addr.addr6 = tcp_addr.in6.sin6_addr;
else
addr.addr4 = tcp_addr.in.sin_addr;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index &&
iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
client_ok = 0;
}
if (option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
{
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
if (!iface)
client_ok = 0;
}
}
if (!client_ok)
goto closeconandreturn;
if (!option_bool(OPT_DEBUG))
{
if (pipe(pipefd) == -1)
goto closeconandreturn; /* pipe failed */
if ((p = fork()) == -1)
{
/* fork failed */
close(pipefd[0]);
close(pipefd[1]);
goto closeconandreturn;
}
if (p != 0)
{
/* fork() done: parent side */
close(pipefd[1]); /* parent needs read pipe end. */
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
read_write(pipefd[0], &a, 1, RW_READ);
#endif
daemon->tcp_pids[slot] = p;
daemon->tcp_pipes[slot] = pipefd[0];
daemon->metrics[METRIC_TCP_CONNECTIONS]++;
if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
close(confd);
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
daemon->log_id += TCP_MAX_QUERIES;
#ifdef HAVE_DNSSEC
/* It can do more if making DNSSEC queries too. */
if (option_bool(OPT_DNSSEC_VALID))
daemon->log_id += daemon->limit[LIMIT_WORK];
#endif
return;
}
}
if (iface)
{
netmask = iface->netmask;
auth_dns = iface->dns_auth;
}
else
{
netmask.s_addr = 0;
auth_dns = 0;
}
/* Arrange for SIGALRM after CHILD_LIFETIME seconds to
terminate the process. */
if (!option_bool(OPT_DEBUG))
{
#ifdef HAVE_LINUX_NETWORK
/* See comment above re: netlink socket. */
close(daemon->netlinkfd);
read_write(pipefd[1], &a, 1, RW_WRITE);
#endif
alarm(CHILD_LIFETIME);
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
}
/* The connected socket inherits non-blocking
attribute from the listening socket.
Reset that here. */
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK)));
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
if (buff)
free(buff);
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
s->tcpfd = -1;
}
if (!option_bool(OPT_DEBUG))
{
close(daemon->pipe_to_parent);
flush_log();
_exit(0);
}
}
#ifdef HAVE_DNSSEC
/* If a DNSSEC query over UDP returns a truncated answer,
we swap to the TCP path. This routine is responsible for forking
the required process, the child then calls tcp_key_recurse() and
returns the result of the validation through the pipe to the parent
(which has also primed the cache with the relevant DS and DNSKEY records).
If we're in debug mode, don't fork and return the result directly, otherwise
return STAT_ASYNC. The UDP validation process will restart when
cache_recv_insert() calls pop_and_retry_query() after the result
arrives via the pipe to the parent. */
int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header *header,
ssize_t *plen, char *name, int class, struct server *server, int *keycount, int *validatecount)
{
struct server *s;
if (!option_bool(OPT_DEBUG))
{
pid_t p;
int i, pipefd[2];
#ifdef HAVE_LINUX_NETWORK
unsigned char a = 0;
#endif
/* check to see if we have a free tcp process slot. */
for (i = daemon->max_procs - 1; i >= 0; i--)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
break;
if (listener->tcpfd != -1 && i >= 0 && poll_check(listener->tcpfd, POLLIN))
/* No slots or no pipe */
if (i < 0 || pipe(pipefd) != 0)
return STAT_ABANDONED;
if ((p = fork()) != 0)
{
int confd, client_ok = 1;
struct irec *iface = NULL;
pid_t p;
union mysockaddr tcp_addr;
socklen_t tcp_len = sizeof(union mysockaddr);
while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
if (confd == -1)
continue;
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
close(pipefd[1]); /* parent needs read pipe end. */
if (p == -1)
{
close(confd);
continue;
/* fork() failed */
close(pipefd[0]);
return STAT_ABANDONED;
}
/* Make sure that the interface list is up-to-date.
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
We do this here as we may need the results below, and
the DNS code needs them for --interface-name stuff.
Multiple calls to enumerate_interfaces() per select loop are
inhibited, so calls to it in the child process (which doesn't select())
have no effect. This avoids two processes reading from the same
netlink fd and screwing the pooch entirely.
*/
enumerate_interfaces(0);
if (option_bool(OPT_NOWILD))
iface = listener->iface; /* May be NULL */
else
{
int if_index;
char intr_name[IF_NAMESIZE];
/* if we can find the arrival interface, check it's one that's allowed */
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
indextoname(listener->tcpfd, if_index, intr_name))
{
union all_addr addr;
if (tcp_addr.sa.sa_family == AF_INET6)
addr.addr6 = tcp_addr.in6.sin6_addr;
else
addr.addr4 = tcp_addr.in.sin_addr;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index &&
iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
client_ok = 0;
}
if (option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */
else
{
/* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr))
break;
if (!iface)
client_ok = 0;
}
}
if (!client_ok)
{
shutdown(confd, SHUT_RDWR);
close(confd);
}
else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
{
close(pipefd[1]); /* parent needs read pipe end. */
if (p == -1)
close(pipefd[0]);
else
{
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
unsigned char a;
read_write(pipefd[0], &a, 1, 1);
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
read_write(pipefd[0], &a, 1, RW_READ);
#endif
/* i holds index of free slot */
daemon->tcp_pids[i] = p;
daemon->tcp_pipes[i] = pipefd[0];
daemon->metrics[METRIC_TCP_CONNECTIONS]++;
if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
/* i holds index of free slot */
daemon->tcp_pids[i] = p;
daemon->tcp_pipes[i] = pipefd[0];
daemon->metrics[METRIC_TCP_CONNECTIONS]++;
if (daemon->metrics[METRIC_TCP_CONNECTIONS] > daemon->max_procs_used)
daemon->max_procs_used = daemon->metrics[METRIC_TCP_CONNECTIONS];
}
close(confd);
/* child can use a maximum of this many log serials. */
daemon->log_id += daemon->limit[LIMIT_WORK];
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
daemon->log_id += TCP_MAX_QUERIES;
}
else
{
unsigned char *buff;
struct server *s;
int flags;
struct in_addr netmask;
int auth_dns;
if (iface)
{
netmask = iface->netmask;
auth_dns = iface->dns_auth;
}
else
{
netmask.s_addr = 0;
auth_dns = 0;
}
/* Arrange for SIGALRM after CHILD_LIFETIME seconds to
terminate the process. */
if (!option_bool(OPT_DEBUG))
{
/* tell the caller we've forked. */
return STAT_ASYNC;
}
else
{
/* child starts here. */
#ifdef HAVE_LINUX_NETWORK
/* See comment above re: netlink socket. */
unsigned char a = 0;
close(daemon->netlinkfd);
read_write(pipefd[1], &a, 1, 0);
/* See comment above re: netlink socket. */
close(daemon->netlinkfd);
read_write(pipefd[1], &a, 1, RW_WRITE);
#endif
alarm(CHILD_LIFETIME);
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
}
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1;
/* The connected socket inherits non-blocking
attribute from the listening socket.
Reset that here. */
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK)));
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
if (buff)
free(buff);
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
if (!option_bool(OPT_DEBUG))
{
close(daemon->pipe_to_parent);
flush_log();
_exit(0);
}
}
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
}
}
status = tcp_from_udp(now, status, header, plen, class, name, server, keycount, validatecount);
/* close upstream connections. */
for (s = daemon->servers; s; s = s->next)
if (s->tcpfd != -1)
{
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
s->tcpfd = -1;
}
if (!option_bool(OPT_DEBUG))
{
ssize_t m = -2;
/* tell our parent we're done, and what the result was then exit. */
read_write(daemon->pipe_to_parent, (unsigned char *)&m, sizeof(m), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&status, sizeof(status), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)plen, sizeof(*plen), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)header, *plen, RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&forward, sizeof(forward), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&forward->uid, sizeof(forward->uid), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)keycount, sizeof(*keycount), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&keycount, sizeof(keycount), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)validatecount, sizeof(*validatecount), RW_WRITE);
read_write(daemon->pipe_to_parent, (unsigned char *)&validatecount, sizeof(validatecount), RW_WRITE);
close(daemon->pipe_to_parent);
flush_log();
_exit(0);
}
/* path for debug mode. */
return status;
}
#endif
#ifdef HAVE_DHCP
int make_icmp_sock(void)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -14,7 +14,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define COPYRIGHT "Copyright (c) 2000-2024 Simon Kelley"
#define COPYRIGHT "Copyright (c) 2000-2025 Simon Kelley"
/* We do defines that influence behavior of stdio.h, so complain
if included too early. */
@@ -155,11 +155,7 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
#include <priv.h>
#endif
/* Backwards compat with 2.83 */
#if defined(HAVE_NETTLEHASH)
# define HAVE_CRYPTOHASH
#endif
#if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
#if defined(HAVE_DNSSEC)
# include <nettle/nettle-meta.h>
#endif
@@ -282,7 +278,10 @@ struct event_desc {
#define OPT_NO_IDENT 70
#define OPT_CACHE_RR 71
#define OPT_LOCALHOST_SERVICE 72
#define OPT_LAST 73
#define OPT_LOG_PROTO 73
#define OPT_NO_0x20 74
#define OPT_DO_0x20 75
#define OPT_LAST 76
#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
@@ -341,8 +340,8 @@ union all_addr {
in the cache flags. */
struct datablock {
unsigned short rrtype;
unsigned char datalen;
char data[];
unsigned char datalen; /* also length of SOA in negative records. */
char data[1];
} rrdata;
};
@@ -456,6 +455,11 @@ struct host_record {
#define INP4 4
#define INP6 8
#define RW_WRITE 0
#define RW_READ 1
#define RW_WRITE_ONCE 2
#define RW_READ_ONCE 3
struct interface_name {
char *name; /* domain name */
char *intr; /* interface name */
@@ -597,8 +601,7 @@ struct server {
char interface[IF_NAMESIZE+1];
unsigned int ifindex; /* corresponding to interface, above */
struct serverfd *sfd;
int tcpfd, edns_pktsz;
time_t pktsz_reduced;
int tcpfd;
unsigned int queries, failed_queries, nxdomain_replies, retrys;
unsigned int query_latency, mma_latency;
time_t forwardtime;
@@ -747,6 +750,7 @@ struct dyndir {
#define STAT_SECURE_WILDCARD 0x70000
#define STAT_OK 0x80000
#define STAT_ABANDONED 0x90000
#define STAT_ASYNC 0xa0000
#define DNSSEC_FAIL_NYV 0x0001 /* key not yet valid */
#define DNSSEC_FAIL_EXP 0x0002 /* key expired */
@@ -757,6 +761,9 @@ struct dyndir {
#define DNSSEC_FAIL_NONSEC 0x0040 /* No NSEC */
#define DNSSEC_FAIL_NODSSUP 0x0080 /* no supported DS algo. */
#define DNSSEC_FAIL_NOKEY 0x0100 /* no DNSKEY */
#define DNSSEC_FAIL_NSEC3_ITERS 0x0200 /* too many iterations in NSEC3 */
#define DNSSEC_FAIL_BADPACKET 0x0400 /* bad packet */
#define DNSSEC_FAIL_WORK 0x0800 /* too much crypto */
#define STAT_ISEQUAL(a, b) (((a) & 0xffff0000) == (b))
@@ -767,20 +774,17 @@ struct dyndir {
#define FREC_DS_QUERY 16
#define FREC_AD_QUESTION 32
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_TEST_PKTSZ 256
#define FREC_HAS_EXTRADATA 512
#define FREC_HAS_PHEADER 1024
#define HASH_SIZE 32 /* SHA-256 digest size */
#define FREC_HAS_PHEADER 128
#define FREC_GONE_TO_TCP 256
#define FREC_ANSWER 512
struct frec {
struct frec_src {
union mysockaddr source;
union all_addr dest;
unsigned int iface, log_id;
unsigned int iface, log_id, encode_bitmap, *encode_bigmap;
int fd;
unsigned short orig_id;
unsigned short orig_id, udp_pkt_size;
struct frec_src *next;
} frec_src;
struct server *sentto; /* NULL means free */
@@ -790,11 +794,10 @@ struct frec {
time_t time;
u32 forward_timestamp;
int forward_delay;
unsigned char *hash[HASH_SIZE];
struct blockdata *stash; /* Saved reply, whilst we validate */
struct blockdata *stash; /* saved query or saved reply, whilst we validate */
size_t stash_len;
#ifdef HAVE_DNSSEC
int class, work_counter;
int uid, class, work_counter, validate_counter;
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
struct frec *next_dependent; /* list of above. */
struct frec *blocking_query; /* Query which is blocking us. */
@@ -831,6 +834,12 @@ struct frec {
#define LEASE_HAVE_HWADDR 128 /* Have set hwaddress */
#define LEASE_EXP_CHANGED 256 /* Lease expiry time changed */
#define LIMIT_SIG_FAIL 0
#define LIMIT_CRYPTO 1
#define LIMIT_WORK 2
#define LIMIT_NSEC3_ITERS 3
#define LIMIT_MAX 4
struct dhcp_lease {
int clid_len; /* length of client identifier */
unsigned char *clid; /* clientid */
@@ -951,6 +960,7 @@ struct dhcp_opt {
#define DHOPT_TAGOK 4096
#define DHOPT_ADDR6 8192
#define DHOPT_VENDOR_PXE 16384
#define DHOPT_PXE_OPT 32768
struct dhcp_boot {
char *file, *sname, *tftp_sname;
@@ -1117,7 +1127,10 @@ struct tftp_prefix {
};
struct dhcp_relay {
union all_addr local, server;
union {
struct in_addr addr4;
struct in6_addr addr6;
} local, server;
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
int iface_index; /* working - interface in which requests arrived, for return */
int port; /* Port of relay we forward to. */
@@ -1233,16 +1246,14 @@ extern struct daemon {
char *packet; /* packet buffer */
int packet_buff_sz; /* size of above */
char *namebuff; /* MAXDNAME size buffer */
#if (defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)) || defined(HAVE_DNSSEC)
/* CONNTRACK UBUS code uses this buffer, as well as DNSSEC code. */
char *workspacename;
#endif
#ifdef HAVE_DNSSEC
char *keyname; /* MAXDNAME size buffer */
char *keyname, *cname; /* MAXDNAME size buffer */
unsigned long *rr_status; /* ceiling in TTL from DNSSEC or zero for insecure */
int rr_status_sz;
int dnssec_no_time_check;
int back_to_the_future;
int limit[LIMIT_MAX];
#endif
struct frec *frec_list;
struct frec_src *free_frec_src;
@@ -1376,24 +1387,24 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr);
int is_rev_synth(int flag, union all_addr *addr, char *name);
/* rfc1035.c */
int do_doctor(struct dns_header *header, size_t qlen, char *namebuff);
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes);
char *name, int func, unsigned int parm);
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
unsigned char *skip_questions(struct dns_header *header, size_t plen);
unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen);
unsigned int extract_request(struct dns_header *header, size_t qlen,
char *name, unsigned short *typep);
unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
unsigned short *typep, unsigned short *classp);
void setup_reply(struct dns_header *header, unsigned int flags, int ede);
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
time_t now, struct ipsets *ipsets, struct ipsets *nftsets, int is_sign,
int check_rebind, int no_cache_dnssec, int secure, int *doctored);
int check_rebind, int no_cache_dnssec, int secure);
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
void report_addresses(struct dns_header *header, size_t len, u32 mark);
#endif
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
struct in_addr local_addr, struct in_addr local_netmask,
time_t now, int ad_reqd, int do_bit, int have_pseudoheader,
int *stale, int *filtered);
time_t now, int ad_reqd, int do_bit, int no_cache, int *stale, int *filtered);
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
time_t now);
int check_for_ignored_address(struct dns_header *header, size_t qlen);
@@ -1405,32 +1416,34 @@ int add_resource_record(struct dns_header *header, char *limit, int *truncp,
int *offset, unsigned short type, unsigned short class, char *format, ...);
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
int private_net(struct in_addr addr, int ban_localhost);
/* extract_name ops */
#define EXTR_NAME_EXTRACT 1
#define EXTR_NAME_COMPARE 2
#define EXTR_NAME_NOCASE 3
#define EXTR_NAME_FLIP 4
/* auth.c */
#ifdef HAVE_AUTH
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen,
time_t now, union mysockaddr *peer_addr, int local_query,
int do_bit, int have_pseudoheader);
time_t now, union mysockaddr *peer_addr, int local_query);
int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
#ifdef HAVE_DNSSEC
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, int edns_pktsz);
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int id, int type);
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name,
char *keyname, int class, int *validate_count);
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name,
char *keyname, int class, int *validate_count);
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
int check_unsigned, int *neganswer, int *nons, int *nsec_ttl);
int check_unsigned, int *neganswer, int *nons, int *nsec_ttl, int *validate_count);
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
int setup_timestamp(void);
int errflags_to_ede(int status);
#endif
/* hash_questions.c */
void hash_questions_init(void);
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name);
/* crypto.c */
const struct nettle_hash *hash_find(char *name);
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
@@ -1513,6 +1526,13 @@ int option_read_dynfile(char *file, int flags);
/* forward.c */
void reply_query(int fd, time_t now);
void receive_query(struct listener *listen, time_t now);
void return_reply(time_t now, struct frec *forward, struct dns_header *header, ssize_t n, int status);
#ifdef HAVE_DNSSEC
void pop_and_retry_query(struct frec *forward, int status, time_t now);
int tcp_from_udp(time_t now, int status, struct dns_header *header, ssize_t *n,
int class, char *name, struct server *server,
int *keycount, int *validatecount);
#endif
unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
void server_gone(struct server *server);
@@ -1632,6 +1652,10 @@ void queue_event(int event);
void send_alarm(time_t event, time_t now);
void send_event(int fd, int event, int data, char *msg);
void clear_cache_and_reload(time_t now);
#ifdef HAVE_DNSSEC
int swap_to_tcp(struct frec *forward, time_t now, int status, struct dns_header *header,
ssize_t *plen, char *name, int class, struct server *server, int *keycount, int *validatecount);
#endif
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
@@ -1649,7 +1673,13 @@ void route_sock(void);
#endif
/* bpf.c or netlink.c */
int iface_enumerate(int family, void *parm, int (callback)());
typedef union {
int (*af_unspec)(int family, void *addrp, char *mac, size_t maclen, void *parmv);
int (*af_inet)(struct in_addr local, int if_index, char *label, struct in_addr netmask, struct in_addr broadcast, void *vparam);
int (*af_inet6)(struct in6_addr *local, int prefix, int scope, int if_index, int flags, unsigned int preferred, unsigned int valid, void *vparam);
int (*af_local)(int index, unsigned int type, char *mac, size_t maclen, void *parm);
} callback_t;
int iface_enumerate(int family, void *parm, callback_t callback);
/* dbus.c */
#ifdef HAVE_DBUS
@@ -1763,8 +1793,9 @@ int do_snoop_script_run(void);
void dhcp_common_init(void);
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags);
int pxe_ok(struct dhcp_opt *opt, int pxemode);
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
struct dhcp_opt *opts);
struct dhcp_opt *opts, int pxemode);
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded);
char *strip_hostname(char *hostname);
void log_tags(struct dhcp_netid *netid, u32 xid);
@@ -1854,7 +1885,7 @@ void from_wire(char *name);
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
size_t *len, unsigned char **p, int *is_sign, int *is_last);
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, time_t now, int *cacheable);

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -94,8 +94,7 @@ void build_server_array(void)
server=/.example.com/ works.
A flag of F_SERVER returns an upstream server only.
A flag of F_DNSSECOK returns a DNSSEC capable server only and
also disables NODOTS servers from consideration.
A flag of F_DNSSECOK disables NODOTS servers from consideration.
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.
@@ -338,12 +337,8 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
if (i != nlow)
{
/* If we want a server that can do DNSSEC, and this one can't,
return nothing, similarly if were looking only for a server
for a particular domain. */
if ((flags & F_DNSSECOK) && !(daemon->serverarray[nlow]->flags & SERV_DO_DNSSEC))
nlow = nhigh;
else if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0)
/* If we want a server for a particular domain, and this one isn't, return nothing. */
if ((flags & F_DOMAINSRV) && daemon->serverarray[nlow]->domain_len == 0)
nlow = nhigh;
else
nhigh = i;
@@ -351,7 +346,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
else
{
/* --local=/domain/, only return if we don't need a server. */
if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER))
if (flags & (F_DOMAINSRV | F_SERVER))
nhigh = i;
}
}
@@ -405,11 +400,19 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
int start;
union all_addr addr;
setup_reply(header, flags, ede);
if (flags & (F_NXDOMAIN | F_NOERR))
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL, 0);
setup_reply(header, flags, ede);
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;
@@ -444,7 +447,13 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
}
if (trunc)
header->hb3 |= HB3_TC;
{
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;
@@ -458,7 +467,7 @@ int dnssec_server(struct server *server, char *keyname, int *firstp, int *lastp)
/* 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_DNSSECOK, &first, &last))
if (!lookup_domain(keyname, F_SERVER | F_DNSSECOK, &first, &last))
return -1;
for (index = first; index != last; index++)
@@ -541,9 +550,9 @@ static int order_qsort(const void *a, const void *b)
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
if (rc == 0)
if (!(s1->flags & SERV_LITERAL_ADDRESS))
if (!(s1->flags & SERV_IS_LOCAL) && !(s2->flags & SERV_IS_LOCAL))
rc = s1->serial - s2->serial;
return rc;
}
@@ -739,12 +748,14 @@ int add_update_server(int flags,
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-2024 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
@@ -115,26 +115,15 @@ int is_name_synthetic(int flags, char *name, union all_addr *addrp)
*p = 0;
if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
{
/* special hack for v4-mapped. */
memcpy(tail, "::ffff:", 7);
for (p = tail + 7; *p; p++)
if (*p == '-')
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
}
else
{
/* swap . or : for - */
for (p = tail; *p; p++)
if (*p == '-')
{
if (prot == AF_INET)
*p = '.';
else
*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);
@@ -194,9 +183,8 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains)))
{
char *p;
*name = 0;
if (c->indexed)
{
u64 index = addr6part(&addr->addr6) - addr6part(&c->start6);
@@ -204,24 +192,17 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
}
else
{
if (c->prefix)
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
inet_ntop(AF_INET6, &addr->addr6, name + strlen(name), ADDRSTRLEN);
int i;
char frag[6];
/* 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->prefix)
strncpy(name, c->prefix, MAXDNAME);
for (i = 0; i < 16; i += 2)
{
*name = '0';
inet_ntop(AF_INET6, &addr->addr6, name+1, ADDRSTRLEN);
sprintf(frag, "%s%02x%02x", i == 0 ? "" : "-", addr->addr6.s6_addr[i], addr->addr6.s6_addr[i+1]);
strncat(name, frag, MAXDNAME);
}
/* V4-mapped have periods.... */
for (p = name; *p; p++)
if (*p == ':' || *p == '.')
*p = '-';
}
strncat(name, ".", MAXDNAME);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -51,31 +51,39 @@ void dump_init(void)
packet_count = 0;
header.magic_number = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone = 0;
header.sigfigs = 0;
header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
if (stat(daemon->dump_file, &buf) == -1)
{
/* doesn't exist, create and add header */
header.magic_number = 0xa1b2c3d4;
header.version_major = 2;
header.version_minor = 4;
header.thiszone = 0;
header.sigfigs = 0;
header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
if (errno != ENOENT ||
(daemon->dumpfd = creat(daemon->dump_file, S_IRUSR | S_IWUSR)) == -1 ||
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 0))
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), RW_WRITE))
die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
}
else if (S_ISFIFO(buf.st_mode))
{
/* File is named pipe (with wireshark on the other end, probably.)
Send header. */
if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), RW_WRITE))
die(_("cannot open pipe %s: %s"), daemon->dump_file, EC_FILE);
}
else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1))
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), RW_READ))
die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
else if (header.magic_number != 0xa1b2c3d4)
die(_("bad header in %s"), daemon->dump_file, EC_FILE);
else
{
/* count existing records */
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 1))
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), RW_READ))
{
lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
packet_count++;
@@ -280,12 +288,12 @@ static void do_dump_packet(int mask, void *packet, size_t len,
pcap_header.ts_usec = time.tv_usec;
if (rc == -1 ||
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
(proto == IPPROTO_UDP && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0)) ||
!read_write(daemon->dumpfd, (void *)packet, len, 0))
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), RW_WRITE) ||
!read_write(daemon->dumpfd, iphdr, ipsz, RW_WRITE) ||
(proto == IPPROTO_UDP && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), RW_WRITE)) ||
!read_write(daemon->dumpfd, (void *)packet, len, RW_WRITE))
my_syslog(LOG_ERR, _("failed to write packet dump"));
else if (option_bool(OPT_EXTRALOG))
else if (option_bool(OPT_EXTRALOG) && (mask & 0x00ff))
my_syslog(LOG_INFO, _("%u dumping packet %u mask 0x%04x"), daemon->log_display_id, ++packet_count, mask);
else
my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask);

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -96,9 +96,12 @@ unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t
}
/* replace == 2 ->delete existing option only. */
/* replace == 0 ->don't replace existing option
replace == 1 ->replace existing or add option
replace == 2 ->relpace existing option only.
*/
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
{
unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
int rdlen = 0, is_sign, is_last;
@@ -114,9 +117,10 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
/* Existing header */
int i;
unsigned short code, len;
p = udp_len;
GETSHORT(udp_sz, p);
PUTSHORT(daemon->edns_pktsz, p);
GETSHORT(rcode, p);
GETSHORT(flags, p);
@@ -197,12 +201,12 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
free(buff);
return plen; /* bad packet */
}
*p++ = 0; /* empty name */
PUTSHORT(T_OPT, p);
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
PUTSHORT(rcode, p); /* extended RCODE and version */
PUTSHORT(flags, p); /* DO flag */
PUTSHORT(daemon->edns_pktsz, p); /* max packet length, 512 if not given in EDNS0 header */
PUTSHORT(rcode, p); /* extended RCODE and version */
PUTSHORT(flags, p); /* DO flag */
lenp = p;
PUTSHORT(rdlen, p); /* RDLEN */
datap = p;
@@ -245,7 +249,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit)
{
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1, 0);
return add_pseudoheader(header, plen, (unsigned char *)limit, 0, NULL, 0, 1, 0);
}
static unsigned char char64(unsigned char c)
@@ -290,7 +294,7 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
replace = 2;
if (replace != 0 || maclen == 6)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
plen = add_pseudoheader(header, plen, limit, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
return plen;
}
@@ -315,7 +319,7 @@ static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *lim
replace = 2;
if (replace != 0 || maclen != 0)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
plen = add_pseudoheader(header, plen, limit, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
return plen;
}
@@ -413,21 +417,34 @@ static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned c
else if (option_bool(OPT_STRIP_ECS))
replace = 2;
else
return plen;
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
{
unsigned char *pheader;
/* If we still think the data is cacheable, and we're not
messing with EDNS client subnet ourselves, see if the client
sent a client subnet. If so, mark the data as uncacheable */
if (*cacheable &&
(pheader = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL)) &&
!check_source(header, plen, pheader, NULL))
*cacheable = 0;
return plen;
}
return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
}
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
{
/* Section 9.2, Check that subnet option in reply matches. */
/* Section 9.2, Check that subnet option (if any) in reply matches.
if peer == NULL, this degrades to a check for the existence of and EDNS0 client-subnet option. */
int len, calc_len;
struct subnet_opt opt;
unsigned char *p;
int code, i, rdlen;
calc_len = calc_subnet_opt(&opt, peer, NULL);
if (peer)
calc_len = calc_subnet_opt(&opt, peer, NULL);
if (!(p = skip_name(pseudoheader, header, plen, 10)))
return 1;
@@ -439,21 +456,26 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
return 1; /* bad packet */
/* check if option there */
for (i = 0; i + 4 < rdlen; i += len + 4)
for (i = 0; i + 4 < rdlen; i += len + 4)
{
GETSHORT(code, p);
GETSHORT(len, p);
if (code == EDNS0_OPTION_CLIENT_SUBNET)
{
/* make sure this doesn't mismatch. */
opt.scope_netmask = p[3];
if (len != calc_len || memcmp(p, &opt, len) != 0)
if (peer)
{
/* make sure this doesn't mismatch. */
opt.scope_netmask = p[3];
if (len != calc_len || memcmp(p, &opt, len) != 0)
return 0;
}
else if (((struct subnet_opt *)p)->source_netmask != 0)
return 0;
}
p += len;
}
return 1;
return 1;
}
/* See https://docs.umbrella.com/umbrella-api/docs/identifying-dns-traffic for
@@ -487,7 +509,7 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
{
*cacheable = 0;
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {0}};
u8 *u = &opt.fields[0];
int family = source->sa.sa_family;
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
@@ -515,7 +537,7 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
PUTLONG(daemon->umbrella_asset, u);
}
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
return add_pseudoheader(header, plen, (unsigned char *)limit, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
}
/* Set *check_subnet if we add a client subnet option, which needs to checked
@@ -530,13 +552,13 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l
plen = add_dns_client(header, plen, limit, source, now, cacheable);
if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
plen = add_pseudoheader(header, plen, limit, EDNS0_OPTION_NOMCPEID,
(unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
if (option_bool(OPT_UMBRELLA))
plen = add_umbrella_opt(header, plen, limit, source, cacheable);
plen = add_source_addr(header, plen, limit, source, cacheable);
return plen;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,284 +0,0 @@
/* Copyright (c) 2012-2023 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/>.
*/
/* Hash the question section. This is used to safely detect query
retransmission and to detect answers to questions we didn't ask, which
might be poisoning attacks. Note that we decode the name rather
than CRC the raw bytes, since replies might be compressed differently.
We ignore case in the names for the same reason.
The hash used is SHA-256. If we're building with DNSSEC support,
we use the Nettle cypto library. If not, we prefer not to
add a dependency on Nettle, and use a stand-alone implementation.
*/
#include "dnsmasq.h"
#if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
static const struct nettle_hash *hash;
static void *ctx;
static unsigned char *digest;
void hash_questions_init(void)
{
if (!(hash = hash_find("sha256")))
die(_("Failed to create SHA-256 hash object"), NULL, EC_MISC);
ctx = safe_malloc(hash->context_size);
digest = safe_malloc(hash->digest_size);
}
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned char *p = (unsigned char *)(header+1);
hash->init(ctx);
for (q = ntohs(header->qdcount); q != 0; q--)
{
char *cp, c;
if (!extract_name(header, plen, &p, name, 1, 4))
return NULL; /* bad packet */
for (cp = name; (c = *cp); cp++)
if (c >= 'A' && c <= 'Z')
*cp += 'a' - 'A';
hash->update(ctx, cp - name, (unsigned char *)name);
/* CRC the class and type as well */
hash->update(ctx, 4, p);
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
return NULL; /* bad packet */
}
hash->digest(ctx, hash->digest_size, digest);
return digest;
}
#else /* HAVE_DNSSEC || HAVE_CRYPTOHASH */
#define SHA256_BLOCK_SIZE 32 /* SHA256 outputs a 32 byte digest */
typedef unsigned char BYTE; /* 8-bit byte */
typedef unsigned int WORD; /* 32-bit word, change to "long" for 16-bit machines */
typedef struct {
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
static void sha256_init(SHA256_CTX *ctx);
static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
static void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
void hash_questions_init(void)
{
}
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned char *p = (unsigned char *)(header+1);
SHA256_CTX ctx;
static BYTE digest[SHA256_BLOCK_SIZE];
sha256_init(&ctx);
for (q = ntohs(header->qdcount); q != 0; q--)
{
char *cp, c;
if (!extract_name(header, plen, &p, name, 1, 4))
return NULL; /* bad packet */
for (cp = name; (c = *cp); cp++)
if (c >= 'A' && c <= 'Z')
*cp += 'a' - 'A';
sha256_update(&ctx, (BYTE *)name, cp - name);
/* CRC the class and type as well */
sha256_update(&ctx, (BYTE *)p, 4);
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
return NULL; /* bad packet */
}
sha256_final(&ctx, digest);
return (unsigned char *)digest;
}
/* Code from here onwards comes from https://github.com/B-Con/crypto-algorithms
and was written by Brad Conte (brad@bradconte.com), to whom all credit is given.
This code is in the public domain, and the copyright notice at the head of this
file does not apply to it.
*/
/****************************** MACROS ******************************/
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
/**************************** VARIABLES *****************************/
static const WORD k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
/*********************** FUNCTION DEFINITIONS ***********************/
static void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (((WORD)data[j]) << 24) | (((WORD)data[j + 1]) << 16) | (((WORD)data[j + 2]) << 8) | (((WORD)data[j + 3]));
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i)
{
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
static void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
for (i = 0; i < len; ++i)
{
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
/* Pad whatever data is left in the buffer. */
if (ctx->datalen < 56)
{
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else
{
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
/* Append to the padding the total message's length in bits and transform. */
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
/* Since this implementation uses little endian byte ordering and SHA uses big endian,
reverse all the bytes when copying the final state to the output hash. */
for (i = 0; i < 4; ++i)
{
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
#endif

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -196,7 +196,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
}
/* we read zero bytes when pipe closed: this is our signal to exit */
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), RW_READ))
{
#ifdef HAVE_LUASCRIPT
if (daemon->luascript)
@@ -258,7 +258,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
continue;
if (!read_write(pipefd[0], buf,
data.hostname_len + data.ed_len + data.clid_len, 1))
data.hostname_len + data.ed_len + data.clid_len, RW_READ))
continue;
/* CLID into packet */

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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
@@ -94,7 +94,7 @@ void inotify_dnsmasq_init()
if (daemon->inotifyfd == -1)
die(_("failed to create inotify: %s"), NULL, EC_MISC);
if (option_bool(OPT_NO_RESOLV))
if (daemon->port == 0 || option_bool(OPT_NO_RESOLV))
return;
for (res = daemon->resolv_files; res; res = res->next)

View File

@@ -1,4 +1,4 @@
/* dnsmasq is Copyright (c) 2000-2024 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

View File

@@ -75,11 +75,11 @@ static char *buffer;
static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, const void *data)
{
struct my_nlattr *attr = (void *)nlh + NL_ALIGN(nlh->nlmsg_len);
struct my_nlattr *attr = (struct my_nlattr *)((u8 *)nlh + NL_ALIGN(nlh->nlmsg_len));
uint16_t payload_len = NL_ALIGN(sizeof(struct my_nlattr)) + len;
attr->nla_type = type;
attr->nla_len = payload_len;
memcpy((void *)attr + NL_ALIGN(sizeof(struct my_nlattr)), data, len);
memcpy((u8 *)attr + NL_ALIGN(sizeof(struct my_nlattr)), data, len);
nlh->nlmsg_len += NL_ALIGN(payload_len);
}
@@ -138,8 +138,8 @@ static int new_add_to_ipset(const char *setname, const union all_addr *ipaddr, i
add_attr(nlh,
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
addrsz, ipaddr);
nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
nested[1]->nla_len = (u8 *)buffer + NL_ALIGN(nlh->nlmsg_len) - (u8 *)nested[1];
nested[0]->nla_len = (u8 *)buffer + NL_ALIGN(nlh->nlmsg_len) - (u8 *)nested[0];
while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
(struct sockaddr *)&snl, sizeof(snl))));

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