Compare commits
419 Commits
v2.86
...
v2.91test8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b72ecb3a59 | ||
|
|
c221030f89 | ||
|
|
5bbea085d0 | ||
|
|
622cf03ab9 | ||
|
|
8ce27433f8 | ||
|
|
5d894620b4 | ||
|
|
71766c0c35 | ||
|
|
da58455508 | ||
|
|
b915c9a661 | ||
|
|
424aaa0f9d | ||
|
|
c72c895869 | ||
|
|
b7156116c2 | ||
|
|
7d915a0bb9 | ||
|
|
509afcd1d2 | ||
|
|
51343bd9a2 | ||
|
|
b58276a73c | ||
|
|
f162d344c0 | ||
|
|
0003db15cb | ||
|
|
275f4a4475 | ||
|
|
12e4565fef | ||
|
|
7af26eed32 | ||
|
|
63dc6eb316 | ||
|
|
6656790f24 | ||
|
|
c8de423038 | ||
|
|
c52653f97c | ||
|
|
e24c341068 | ||
|
|
5ef6c8c24f | ||
|
|
7c348a0b73 | ||
|
|
d578da0665 | ||
|
|
8949ef44b4 | ||
|
|
3ac11cdd98 | ||
|
|
5d49fa112d | ||
|
|
d29d19e654 | ||
|
|
49ea7db74e | ||
|
|
fcb40ee73d | ||
|
|
0f437b3b5e | ||
|
|
8a5fe8ce6b | ||
|
|
2a664c03db | ||
|
|
4902807879 | ||
|
|
742af6e4b9 | ||
|
|
3eb008c36d | ||
|
|
32248ebd5b | ||
|
|
5d32f35bdc | ||
|
|
d6379cd923 | ||
|
|
9f7e9ba46f | ||
|
|
80498fab01 | ||
|
|
ea84abe3e9 | ||
|
|
0526792ebb | ||
|
|
ab177cb153 | ||
|
|
3b74df4f55 | ||
|
|
5483fead6a | ||
|
|
7199531ff1 | ||
|
|
5a1f2c577d | ||
|
|
6c9bc0156a | ||
|
|
da2cc84854 | ||
|
|
a8088e331a | ||
|
|
41d2ae3203 | ||
|
|
c6bc22adc7 | ||
|
|
9c057566d5 | ||
|
|
32a8f3e009 | ||
|
|
481ff0ed10 | ||
|
|
f04cf8506a | ||
|
|
04d7693d86 | ||
|
|
4ea23f7ea1 | ||
|
|
163c05c61d | ||
|
|
d2790914df | ||
|
|
334e144c36 | ||
|
|
8bd54efceb | ||
|
|
e5e8c14d87 | ||
|
|
e778a28eee | ||
|
|
4cf2f757ec | ||
|
|
ae85ea3858 | ||
|
|
b087cf4a6c | ||
|
|
0adaf13438 | ||
|
|
b5ac983bf6 | ||
|
|
498794ad85 | ||
|
|
467fbd1086 | ||
|
|
7b7aef903e | ||
|
|
09a1839272 | ||
|
|
1b76e1c8ec | ||
|
|
959d991d10 | ||
|
|
ed6d29a784 | ||
|
|
5d6399b71c | ||
|
|
3b6df06fb8 | ||
|
|
a9d46d42cb | ||
|
|
0338aa4586 | ||
|
|
d15d371051 | ||
|
|
1c26ec2876 | ||
|
|
e9a7cd0a50 | ||
|
|
f5cdb007d8 | ||
|
|
46288c7e90 | ||
|
|
d7d682637d | ||
|
|
f006be7842 | ||
|
|
550c368ade | ||
|
|
b8ff4bb762 | ||
|
|
9adbf009a6 | ||
|
|
ccff85ad72 | ||
|
|
4c590320ec | ||
|
|
89aad01468 | ||
|
|
de6f914654 | ||
|
|
1ed783b8d7 | ||
|
|
3705ec5592 | ||
|
|
b6769234bc | ||
|
|
214a046f47 | ||
|
|
b38da6b191 | ||
|
|
9621c16a78 | ||
|
|
3ae7f1ab0d | ||
|
|
39de57499e | ||
|
|
3c91bca943 | ||
|
|
76bceb06c4 | ||
|
|
6f23a0a75e | ||
|
|
06945c4b77 | ||
|
|
c5aa221e44 | ||
|
|
bfefd6e38c | ||
|
|
59d30390c9 | ||
|
|
51471cafa5 | ||
|
|
be73efc020 | ||
|
|
40595f80d9 | ||
|
|
8c8e5385fd | ||
|
|
3de7289bd6 | ||
|
|
febeea9d01 | ||
|
|
762a3f2430 | ||
|
|
6d35601da4 | ||
|
|
a827127c77 | ||
|
|
d4a6f3a93e | ||
|
|
86c15032ba | ||
|
|
12ddb2a4b9 | ||
|
|
db07664f2a | ||
|
|
1205fc3541 | ||
|
|
3a8ebcac77 | ||
|
|
729e54b386 | ||
|
|
a61dbc84bf | ||
|
|
3cbd4b0fc0 | ||
|
|
75965b19bd | ||
|
|
830459d3a1 | ||
|
|
aa9e9651a1 | ||
|
|
9142942483 | ||
|
|
68fe0d78bb | ||
|
|
c9d7b983c4 | ||
|
|
7c07dc3526 | ||
|
|
cd93d15ab1 | ||
|
|
34bbb7a1b8 | ||
|
|
b5820d1fd8 | ||
|
|
2748d4e901 | ||
|
|
63ba726e1f | ||
|
|
f1beb79429 | ||
|
|
cd4db8246e | ||
|
|
69877f565a | ||
|
|
744231d995 | ||
|
|
65c2d6afd6 | ||
|
|
b27b94cfdc | ||
|
|
b8b5b734b4 | ||
|
|
568fb02449 | ||
|
|
77ef9b2603 | ||
|
|
416390f996 | ||
|
|
24804b7431 | ||
|
|
1fe9d2ba45 | ||
|
|
3868066085 | ||
|
|
a889c554a7 | ||
|
|
ca8d04a8ff | ||
|
|
8b606543a3 | ||
|
|
d16b995756 | ||
|
|
768b45a023 | ||
|
|
3b5ddf37d9 | ||
|
|
9bbf098a97 | ||
|
|
6536187b62 | ||
|
|
50adf82199 | ||
|
|
1419de285f | ||
|
|
31c91b40bd | ||
|
|
1d6fe0ea84 | ||
|
|
d774add784 | ||
|
|
7500157cff | ||
|
|
52e6ad2761 | ||
|
|
bcb46809dc | ||
|
|
33635d8564 | ||
|
|
bd188e306a | ||
|
|
aaba66efbd | ||
|
|
597378cdf5 | ||
|
|
15dcdc824a | ||
|
|
86ee779e22 | ||
|
|
df242de5c6 | ||
|
|
b14aa762ff | ||
|
|
a78487a4df | ||
|
|
3a601d06bd | ||
|
|
047256a6d8 | ||
|
|
c244d92d8a | ||
|
|
138e1e2a2d | ||
|
|
153eeb070b | ||
|
|
a3c8b75972 | ||
|
|
042c64273d | ||
|
|
638c7c4d20 | ||
|
|
88fc6c8023 | ||
|
|
3fb10cd0d8 | ||
|
|
ff28a485cf | ||
|
|
1f0f86a0d0 | ||
|
|
2842972035 | ||
|
|
5a9eae429a | ||
|
|
9461807011 | ||
|
|
00be8b39e2 | ||
|
|
ef5aac95d4 | ||
|
|
ef8e930e42 | ||
|
|
eb92fb32b7 | ||
|
|
9a698434dd | ||
|
|
f5ef0f064c | ||
|
|
997982f78b | ||
|
|
7d6b68c5d7 | ||
|
|
137ae2e9cf | ||
|
|
5dc14b6e05 | ||
|
|
0427e37116 | ||
|
|
e5e8cae1ca | ||
|
|
7f42ca8af8 | ||
|
|
e4251eb13b | ||
|
|
5083876910 | ||
|
|
f172fdbb77 | ||
|
|
3822825e54 | ||
|
|
1da54210fc | ||
|
|
43a2a66531 | ||
|
|
e6841ea2e0 | ||
|
|
e939b45c9f | ||
|
|
e3068ed111 | ||
|
|
efbf80be58 | ||
|
|
022ad63f0c | ||
|
|
02f8754339 | ||
|
|
142456cfd0 | ||
|
|
207ce40db2 | ||
|
|
881eaa4dbc | ||
|
|
d6d7527c95 | ||
|
|
11b4be2036 | ||
|
|
3e306c1202 | ||
|
|
7f227a83f2 | ||
|
|
9ed3ee67ec | ||
|
|
1f9215f5f9 | ||
|
|
f52cfdd8c3 | ||
|
|
2fc904111d | ||
|
|
262dadf50e | ||
|
|
6c596f1cc1 | ||
|
|
dafa16c400 | ||
|
|
1db9943c68 | ||
|
|
5b868c213b | ||
|
|
2d8905dafd | ||
|
|
9002108551 | ||
|
|
d3c21c596e | ||
|
|
34fac952b6 | ||
|
|
92c32e0bac | ||
|
|
1bcad67806 | ||
|
|
fe9a134baf | ||
|
|
930428fb97 | ||
|
|
936be022d9 | ||
|
|
0017dd74d5 | ||
|
|
0ba25a0512 | ||
|
|
a176cf1bc3 | ||
|
|
fdd9a96a8c | ||
|
|
b87d7aa041 | ||
|
|
f753e7eba6 | ||
|
|
78a5a21655 | ||
|
|
a5cbe6d112 | ||
|
|
9403664616 | ||
|
|
f32498465d | ||
|
|
fa45e06431 | ||
|
|
6722ec6c78 | ||
|
|
d882dfdae9 | ||
|
|
a2ee2426bf | ||
|
|
84bd46ddd7 | ||
|
|
271790685a | ||
|
|
7a74037267 | ||
|
|
9a9f6e147c | ||
|
|
8f2d432799 | ||
|
|
92eab03b12 | ||
|
|
1ba4ae2830 | ||
|
|
0076481dfd | ||
|
|
c0e731d545 | ||
|
|
3f56bb8ba1 | ||
|
|
e518e87533 | ||
|
|
c4b9bc63e0 | ||
|
|
1d53d958bb | ||
|
|
d334e7c34f | ||
|
|
d21438a7df | ||
|
|
24c3b5b3d4 | ||
|
|
4447d48bb9 | ||
|
|
04cc2ae1a6 | ||
|
|
32588c755a | ||
|
|
84a6d07cdd | ||
|
|
d6c69f6bdb | ||
|
|
ce372917fe | ||
|
|
09d741f58a | ||
|
|
0666ae3d27 | ||
|
|
ba4c7d906b | ||
|
|
f4b2813818 | ||
|
|
5586934da0 | ||
|
|
6134b94c02 | ||
|
|
05e6728e98 | ||
|
|
6578acd668 | ||
|
|
b5581ed173 | ||
|
|
508d6b4885 | ||
|
|
ef6efd69ed | ||
|
|
151d7dc5ea | ||
|
|
20b4a4ea5b | ||
|
|
770bce967c | ||
|
|
a267a9e489 | ||
|
|
f65d210012 | ||
|
|
858bfcf261 | ||
|
|
9b801c4e72 | ||
|
|
1a98d1a94f | ||
|
|
03345ecefe | ||
|
|
191924576c | ||
|
|
756a1dcc19 | ||
|
|
3ab6dd1c37 | ||
|
|
4458d87289 | ||
|
|
b7f62475d0 | ||
|
|
4732aa663b | ||
|
|
c27cfeaa7b | ||
|
|
bb6f6bae0b | ||
|
|
f4c87b504b | ||
|
|
e426c2d3bc | ||
|
|
6279d9eaf3 | ||
|
|
12949aa0c0 | ||
|
|
84f3357dd9 | ||
|
|
4333d5d93a | ||
|
|
fa580ad3eb | ||
|
|
292dfa653e | ||
|
|
7fbf1cce7b | ||
|
|
dbceeb4178 | ||
|
|
ed200fa001 | ||
|
|
b5dafc0b7e | ||
|
|
fc664d114d | ||
|
|
c6d4c33d61 | ||
|
|
bf1fc6c6fd | ||
|
|
b18e9c8c61 | ||
|
|
a3293bb242 | ||
|
|
4e2a4b8788 | ||
|
|
2362784bc0 | ||
|
|
b2cec1b881 | ||
|
|
a946857133 | ||
|
|
10cd342f5c | ||
|
|
27ce754b3d | ||
|
|
3ab0ad8748 | ||
|
|
4308236262 | ||
|
|
ebd8350300 | ||
|
|
8285d335f4 | ||
|
|
9db275ebea | ||
|
|
1f8f78a49b | ||
|
|
c2f129ba3d | ||
|
|
07c47416a9 | ||
|
|
8f2a62b386 | ||
|
|
a6c0edd4f4 | ||
|
|
ff43d35aee | ||
|
|
70fca205be | ||
|
|
1033130b6c | ||
|
|
8cfcd9ff63 | ||
|
|
80a6c16dcc | ||
|
|
553c4c99cc | ||
|
|
4165c1331b | ||
|
|
b2690415bf | ||
|
|
011f8cf1d0 | ||
|
|
2748fb81e2 | ||
|
|
46312909d9 | ||
|
|
41adecad14 | ||
|
|
ea5d8c56a0 | ||
|
|
d242cbffa4 | ||
|
|
1c8855ed10 | ||
|
|
ea33a01303 | ||
|
|
18b1d1424e | ||
|
|
1176cd58c9 | ||
|
|
44a4643b62 | ||
|
|
ed96efd865 | ||
|
|
e3093b532c | ||
|
|
9560658c5b | ||
|
|
37a70d39e0 | ||
|
|
72fac0810c | ||
|
|
c166c07a93 | ||
|
|
39a625ff72 | ||
|
|
ad32ca18a7 | ||
|
|
efea282396 | ||
|
|
33d6a01cd3 | ||
|
|
d290630d31 | ||
|
|
d2ad5dc073 | ||
|
|
68ab5127af | ||
|
|
089a11f340 | ||
|
|
de1d04eb66 | ||
|
|
ed4e7defd7 | ||
|
|
267ab619c4 | ||
|
|
0140454ba2 | ||
|
|
2c60441239 | ||
|
|
cbbd56c965 | ||
|
|
2561f9fe0e | ||
|
|
47aefca5e4 | ||
|
|
981fb03710 | ||
|
|
ef2f8d70d2 | ||
|
|
d9995a1add | ||
|
|
ea7a05ad43 | ||
|
|
26bbf5a314 | ||
|
|
c147329823 | ||
|
|
eb88eed1fc | ||
|
|
8312a3ba4f | ||
|
|
35f93081dc | ||
|
|
de372d6914 | ||
|
|
4ac517e4ac | ||
|
|
e3651367b3 | ||
|
|
02ea41ddd1 | ||
|
|
51ffae4eab | ||
|
|
afe84f37f8 | ||
|
|
0afeef0e00 | ||
|
|
94a17fd97f | ||
|
|
5b5ec55445 | ||
|
|
1e6565c1a5 | ||
|
|
fc522515b9 | ||
|
|
9881b0736d | ||
|
|
e52b4b1466 | ||
|
|
2f45670951 | ||
|
|
50d75ae514 | ||
|
|
dea69a12aa | ||
|
|
e0ce3c12f2 | ||
|
|
93cf516bf1 | ||
|
|
6f4de018af | ||
|
|
6e91cf3172 | ||
|
|
9cb7f8a655 | ||
|
|
5d8d1ad14b | ||
|
|
c4523639d5 | ||
|
|
1ce1c6beae |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -7,8 +7,4 @@ src/.copts_*
|
||||
contrib/lease-tools/dhcp_lease_time
|
||||
contrib/lease-tools/dhcp_release
|
||||
contrib/lease-tools/dhcp_release6
|
||||
debian/files
|
||||
debian/substvars
|
||||
debian/utils-substvars
|
||||
debian/trees/
|
||||
debian/build/
|
||||
|
||||
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "debian"]
|
||||
path = debian
|
||||
url = git://thekelleys.org.uk/dnsmasq-debian.git
|
||||
349
CHANGELOG
349
CHANGELOG
@@ -1,3 +1,349 @@
|
||||
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, 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.
|
||||
|
||||
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 wuth 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 pseudoheader, 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 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.
|
||||
|
||||
|
||||
version 2.90
|
||||
Fix reversion in --rev-server introduced in 2.88 which
|
||||
caused breakage if the prefix length is not exactly divisible
|
||||
by 8 (IPv4) or 4 (IPv6).
|
||||
|
||||
Fix possible SEGV when there server(s) for a particular
|
||||
domain are configured, but no server which is not qualified
|
||||
for a particular domain. Thanks to Daniel Danzberger for
|
||||
spotting this bug.
|
||||
|
||||
Set the default maximum DNS UDP packet sice 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
|
||||
for IPv6. It's still possible to override this with
|
||||
--edns-packet-max for special circumstances.
|
||||
|
||||
Add --no-dhcpv4-interface and --no-dhcpv6-interface for
|
||||
better control over which inetrfaces 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
|
||||
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 the is a security vulnerablity 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
|
||||
in corruption of the DNS cache internal data structures and
|
||||
logging of "cache internal error". This has only been seen
|
||||
in one place in the wild, and it took considerable effort
|
||||
to even generate a test case to reproduce it, but there's
|
||||
no way to be sure it won't strike, and the effect is to break
|
||||
the cache badly. Installations with DNSSEC enabled are more
|
||||
likely to see the problem, but not running DNSSEC does not
|
||||
guarantee that it won't happen. Thanks to Timo van Roermund
|
||||
for reporting the bug and for his great efforts in chasing
|
||||
it down.
|
||||
|
||||
|
||||
version 2.88
|
||||
Fix bug in --dynamic-host when an interface has /16 IPv4
|
||||
address. Thanks to Mark Dietzer for spotting this.
|
||||
|
||||
Add --fast-dns-retry option. This gives dnsmasq the ability
|
||||
to originate retries for upstream DNS queries itself, rather
|
||||
than relying on the downstream client. This is most useful
|
||||
when doing DNSSEC over unreliable upstream networks. It comes
|
||||
with some cost in memory usage and network bandwidth.
|
||||
|
||||
Add --use-stale-cache option. 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 of sometimes returning out-of-date data and
|
||||
less efficient cache utilisation, since old data cannot be
|
||||
flushed when its TTL expires, so the cache becomes
|
||||
strictly least-recently-used.
|
||||
|
||||
Add --port-limit option which allows tuning for robustness in
|
||||
the face of some upstream network errors. Thanks to
|
||||
Prashant Kumar Singh, Ravi Nagayach and Mike Danilov,
|
||||
all of Amazon Web Services, for their efforts in developing this
|
||||
and the stale-cache and fast-retry options.
|
||||
|
||||
Make --hostsdir (but NOT --dhcp-hostsdir and --dhcp-optsdir)
|
||||
handle removal of whole files or entries within files.
|
||||
Thanks to Dominik Derigs for the initial patches for this.
|
||||
|
||||
Fix bug, introduced in 2.87, which could result in DNS
|
||||
servers being removed from the configuration when reloading
|
||||
server configuration from DBus, or re-reading /etc/resolv.conf
|
||||
Only servers from the same source should be replaced, but some
|
||||
servers from other sources (i.e., hard coded or another dynamic source)
|
||||
could mysteriously disappear. Thanks to all reporting this,
|
||||
but especially Christopher J. Madsen who reduced the problem
|
||||
to an easily reproducible case which saved much labour in
|
||||
finding it.
|
||||
|
||||
Add --no-round-robin option.
|
||||
|
||||
Allow domain names as well as IP addresses when specifying
|
||||
upstream DNS servers. There are some gotchas associated with this
|
||||
(it will mysteriously fail to work if the dnsmasq instance
|
||||
being started is in the path from the system resolver to the DNS),
|
||||
and a seemingly sensible configuration like
|
||||
--server=domain.name@1.2.3.4 is unactionable if domain.name
|
||||
only resolves to an IPv6 address). There are, however,
|
||||
cases where is can be useful. Thanks to Dominik Derigs for
|
||||
the patch.
|
||||
|
||||
Handle DS records for unsupported crypto algorithms correctly.
|
||||
Such a DS, as long as it is validated, should allow answers
|
||||
in the domain it attests to be returned as unvalidated, and not
|
||||
as a validation error.
|
||||
|
||||
Optimise reading large numbers of --server options. When re-reading
|
||||
upstream servers from /etc/resolv.conf or other sources that
|
||||
can change dnsmasq tries to avoid memory fragmentation by re-using
|
||||
existing records that are being re-read unchanged. This involves
|
||||
seaching all the server records for each new one installed.
|
||||
During startup this search is pointless, and can cause long
|
||||
start times with thousands of --server options because the work
|
||||
needed is O(n^2). Handle this case more intelligently.
|
||||
Thanks to Ye Zhou for spotting the problem and an initial patch.
|
||||
|
||||
If we detect that a DNS reply from upstream is malformed don't
|
||||
return it to the requestor; send a SEVFAIL rcode instead.
|
||||
|
||||
|
||||
version 2.87
|
||||
Allow arbitrary prefix lengths in --rev-server and
|
||||
--domain=....,local
|
||||
|
||||
Replace --address=/#/..... functionality which got
|
||||
missed in the 2.86 domain search rewrite.
|
||||
|
||||
Add --nftset option, like --ipset but for the newer nftables.
|
||||
Thanks to Chen Zhenge for the patch.
|
||||
|
||||
Add --filter-A and --filter-AAAA options, to remove IPv4 or IPv6
|
||||
addresses from DNS answers.
|
||||
|
||||
Fix crash doing netbooting when --port is set to zero
|
||||
to disable the DNS server. Thanks to Drexl Johannes
|
||||
for the bug report.
|
||||
|
||||
Generalise --dhcp-relay. Sending via broadcast/multicast is
|
||||
now supported for both IPv4 and IPv6 and the configuration
|
||||
syntax made easier (but backwards compatible).
|
||||
|
||||
Add snooping of IPv6 prefix-delegations to the DHCP-relay system.
|
||||
|
||||
Finesse parsing of --dhcp-remoteid and --dhcp-subscrid. To be treated
|
||||
as hex, the pattern must consist of only hex digits AND contain
|
||||
at least one ':'. Thanks to Bengt-Erik Sandstrom who tripped
|
||||
over a pattern consisting of a decimal number which was interpreted
|
||||
surprisingly.
|
||||
|
||||
Include client address in TFTP file-not-found error reports.
|
||||
Thanks to Stefan Rink for the initial patch, which has been
|
||||
re-worked by me (srk). All bugs mine.
|
||||
|
||||
Note in manpage the change in behaviour of -address. This behaviour
|
||||
actually changed in v2.86, but was undocumented there. From 2.86 on,
|
||||
(eg) --address=/example.com/1.2.3.4 ONLY applies to A queries. All other
|
||||
types of query will be sent upstream. Pre 2.86, that would catch the
|
||||
whole example.com domain and queries for other types would get
|
||||
a local NODATA answer. The pre-2.86 behaviour is still available,
|
||||
by configuring --address=/example.com/1.2.3.4 --local=/example.com/
|
||||
|
||||
Fix problem with binding DHCP sockets to an individual interface.
|
||||
Despite the fact that the system call tales the interface _name_ as
|
||||
a parameter, it actually, binds the socket to interface _index_.
|
||||
Deleting the interface and creating a new one with the same name
|
||||
leaves the socket bound to the old index. (Creating new sockets
|
||||
always allocates a fresh index, they are not reused). We now
|
||||
take this behaviour into account and keep up with changing indexes.
|
||||
|
||||
Add --conf-script configuration option.
|
||||
|
||||
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
|
||||
doesn't require hard-coding addresses. Thanks to Sten Spans for
|
||||
the idea.
|
||||
|
||||
Fix write-after-free error in DHCPv6 server code.
|
||||
CVE-2022-0934 refers.
|
||||
|
||||
Add the ability to specify destination port in
|
||||
DHCP-relay mode. This change also removes a previous bug
|
||||
where --dhcp-alternate-port would affect the port used
|
||||
to relay _to_ as well as the port being listened on.
|
||||
The new feature allows configuration to provide bug-for-bug
|
||||
compatibility, if required. Thanks to Damian Kaczkowski
|
||||
for the feature suggestion.
|
||||
|
||||
Bound the value of UDP packet size in the EDNS0 header of
|
||||
forwarded queries to the configured or default value of
|
||||
edns-packet-max. There's no point letting a client set a larger
|
||||
value if we're unable to return the answer. Thanks to Bertie
|
||||
Taylor for pointing out the problem and supplying the patch.
|
||||
|
||||
Fix problem with the configuration
|
||||
|
||||
--server=/some.domain/# --address=/#/<ip> --server=<server_ip>
|
||||
|
||||
This would return <ip> for queries in some.domain, rather than
|
||||
forwarding the query via the default server.
|
||||
|
||||
Tweak DHCPv6 relay code so that packets relayed towards a server
|
||||
have source address on the server-facing network, not the
|
||||
client facing network. Thanks to Luis Thomas for spotting this
|
||||
and initial patch.
|
||||
|
||||
|
||||
version 2.86
|
||||
Handle DHCPREBIND requests in the DHCPv6 server code.
|
||||
Thanks to Aichun Li for spotting this omission, and the initial
|
||||
@@ -92,6 +438,9 @@ version 2.86
|
||||
of filename). Thanks to Ed Wildgoose for the initial patch
|
||||
and motivation for this.
|
||||
|
||||
Allow adding IP address to nftables set in addition to
|
||||
ipset.
|
||||
|
||||
|
||||
version 2.85
|
||||
Fix problem with DNS retries in 2.83/2.84.
|
||||
|
||||
43
COPYING
43
COPYING
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -225,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
||||
43
Makefile
43
Makefile
@@ -1,4 +1,4 @@
|
||||
# dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
# dnsmasq is Copyright (c) 2000-2024 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,20 +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.2`
|
||||
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2`
|
||||
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`
|
||||
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
||||
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 \
|
||||
@@ -82,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
|
||||
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
|
||||
@@ -90,8 +89,8 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
all : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
|
||||
mostly_clean :
|
||||
@@ -103,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
|
||||
@@ -115,14 +112,18 @@ all-i18n : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
for f in `cd $(PO); echo *.po`; do \
|
||||
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
||||
done
|
||||
|
||||
install-i18n : all-i18n install-common
|
||||
install-i18n : all-i18n
|
||||
$(INSTALL) -d $(DESTDIR)$(BINDIR)
|
||||
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
|
||||
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
|
||||
cd $(BUILDDIR); $(top)/bld/install-mo $(DESTDIR)$(LOCALEDIR) $(INSTALL)
|
||||
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
|
||||
|
||||
|
||||
@@ -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,6 +0,0 @@
|
||||
This packaging is now unmaintained in the dnsmasq source: dnsmasq is
|
||||
included in Suse proper, and up-to-date packages are now available
|
||||
from
|
||||
|
||||
ftp://ftp.suse.com/pub/people/ug/
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
|
||||
It fixes the dependency from the dns daemon name 'named'
|
||||
After appending the patch, the SuSEfirewall is again able to autodetect
|
||||
the dnsmasq named service.
|
||||
This is a very old bug in the SuSEfirewall script.
|
||||
The SuSE people think the name of the dns server will always 'named'
|
||||
|
||||
|
||||
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
|
||||
+++ /sbin/SuSEfirewall2 2004-01-23 13:31:56.000000000 +0100
|
||||
@@ -764,7 +764,7 @@
|
||||
echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
|
||||
|
||||
test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
|
||||
- test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
|
||||
+ test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
|
||||
echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
|
||||
You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
|
||||
FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
|
||||
@@ -878,7 +878,7 @@
|
||||
test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
|
||||
# Get ports/IP bindings of NAMED/SQUID
|
||||
test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
|
||||
- $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
||||
+ $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
||||
test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
|
||||
$AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`
|
||||
@@ -1,23 +0,0 @@
|
||||
--- man/dnsmasq.8 2004-08-08 20:57:56.000000000 +0200
|
||||
+++ man/dnsmasq.8 2004-08-12 00:40:01.000000000 +0200
|
||||
@@ -69,7 +69,7 @@
|
||||
.TP
|
||||
.B \-g, --group=<groupname>
|
||||
Specify the group which dnsmasq will run
|
||||
-as. The defaults to "dip", if available, to facilitate access to
|
||||
+as. The defaults to "dialout", if available, to facilitate access to
|
||||
/etc/ppp/resolv.conf which is not normally world readable.
|
||||
.TP
|
||||
.B \-v, --version
|
||||
--- src/config.h 2004-08-11 11:39:18.000000000 +0200
|
||||
+++ src/config.h 2004-08-12 00:40:01.000000000 +0200
|
||||
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
-#define CHGRP "dip"
|
||||
+#define CHGRP "dialout"
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# General
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.33
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Productivity/Networking/DNS/Servers
|
||||
Vendor: Simon Kelley
|
||||
Packager: Simon Kelley
|
||||
URL: http://www.thekelleys.org.uk/dnsmasq
|
||||
Provides: dns_daemon
|
||||
Conflicts: bind bind8 bind9
|
||||
PreReq: %fillup_prereq %insserv_prereq
|
||||
Autoreqprov: on
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
BuildRoot: /var/tmp/%{name}-%{version}
|
||||
Summary: A lightweight caching nameserver
|
||||
|
||||
%description
|
||||
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
|
||||
is designed to provide DNS and, optionally, DHCP, to a small network. It can
|
||||
serve the names of local machines which are not in the global DNS. The DHCP
|
||||
server integrates with the DNS server and allows machines with DHCP-allocated
|
||||
addresses to appear in the DNS with names configured either in each host or
|
||||
in a central configuration file. Dnsmasq supports static and dynamic DHCP
|
||||
leases and BOOTP for network booting of diskless machines.
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Build
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
patch -p0 <rpm/%{name}-SuSE.patch
|
||||
|
||||
%build
|
||||
%{?suse_update_config:%{suse_update_config -f}}
|
||||
make all-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Install
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
|
||||
make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
||||
install -o root -g root -m 755 rpm/rc.dnsmasq-suse $RPM_BUILD_ROOT/etc/init.d/dnsmasq
|
||||
install -o root -g root -m 644 dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
||||
strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
|
||||
ln -sf ../../etc/init.d/dnsmasq $RPM_BUILD_ROOT/usr/sbin/rcdnsmasq
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Post-install scriptlet
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%post
|
||||
%{fillup_and_insserv dnsmasq}
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Post-uninstall scriptlet
|
||||
#
|
||||
# The %postun script executes after the package has been removed. It is the
|
||||
# last chance for a package to clean up after itself.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%postun
|
||||
%{insserv_cleanup}
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# File list
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
|
||||
%doc contrib
|
||||
%config /etc/init.d/dnsmasq
|
||||
%config /etc/dnsmasq.conf
|
||||
/usr/sbin/rcdnsmasq
|
||||
/usr/sbin/dnsmasq
|
||||
/usr/share/locale/*/LC_MESSAGES/*
|
||||
%doc %{_mandir}/man8/dnsmasq.8.gz
|
||||
%doc %{_mandir}/*/man8/dnsmasq.8.gz
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# init.d/dnsmasq
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dnsmasq
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop:
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop:
|
||||
# Description: Starts internet name service masq caching server (DNS)
|
||||
### END INIT INFO
|
||||
|
||||
NAMED_BIN=/usr/sbin/dnsmasq
|
||||
NAMED_PID=/var/run/dnsmasq.pid
|
||||
NAMED_CONF=/etc/dnsmasq.conf
|
||||
|
||||
if [ ! -x $NAMED_BIN ] ; then
|
||||
echo -n "dnsmasq not installed ! "
|
||||
exit 5
|
||||
fi
|
||||
|
||||
. /etc/rc.status
|
||||
rc_reset
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
if [ $? -eq 0 ] ; then
|
||||
echo -n "- Warning: dnsmasq already running ! "
|
||||
else
|
||||
[ -e $NAMED_PID ] && echo -n "- Warning: $NAMED_PID exists ! "
|
||||
fi
|
||||
startproc -p $NAMED_PID $NAMED_BIN -u nobody
|
||||
rc_status -v
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
||||
killproc -p $NAMED_PID -TERM $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
try-restart)
|
||||
$0 stop && $0 start
|
||||
rc_status
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
rc_status
|
||||
;;
|
||||
force-reload)
|
||||
$0 reload
|
||||
rc_status
|
||||
;;
|
||||
reload)
|
||||
echo -n "Reloading name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
||||
killproc -p $NAMED_PID -HUP $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
status)
|
||||
echo -n "Checking for name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
probe)
|
||||
test $NAMED_CONF -nt $NAMED_PID && echo reload
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
rc_exit
|
||||
|
||||
@@ -280,6 +280,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
||||
a DHCP server */
|
||||
memset(&ifr, 0, sizeof(ifr));
|
||||
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||
|
||||
@@ -318,6 +318,12 @@ void usage(const char* arg, FILE* stream)
|
||||
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
||||
}
|
||||
|
||||
static void fail_fatal(const char *errstr, int exitcode)
|
||||
{
|
||||
perror(errstr);
|
||||
exit(exitcode);
|
||||
}
|
||||
|
||||
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||
{
|
||||
struct sockaddr_in6 server_addr, client_addr;
|
||||
@@ -343,18 +349,19 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
|
||||
client_addr.sin6_flowinfo = 0;
|
||||
client_addr.sin6_scope_id =0;
|
||||
inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
|
||||
bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
|
||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
||||
if (inet_pton(AF_INET6, "::", &client_addr.sin6_addr) <= 0)
|
||||
fail_fatal("inet_pton", 5);
|
||||
if (bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)) != 0)
|
||||
perror("bind"); /* continue on bind error */
|
||||
if (inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr) <= 0)
|
||||
fail_fatal("inet_pton", 5);
|
||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||
int16_t recv_size = 0;
|
||||
ssize_t recv_size = 0;
|
||||
int result;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
||||
{
|
||||
perror("sendto failed");
|
||||
exit(4);
|
||||
}
|
||||
fail_fatal("sendto failed", 4);
|
||||
|
||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||
if (recv_size == -1)
|
||||
@@ -367,16 +374,18 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||
else
|
||||
{
|
||||
perror("recvfrom");
|
||||
result = UNSPEC_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t result = parse_packet(response, recv_size);
|
||||
if (result == NOT_REPLY_CODE)
|
||||
else
|
||||
{
|
||||
sleep(1);
|
||||
continue;
|
||||
result = parse_packet(response, recv_size);
|
||||
if (result == NOT_REPLY_CODE)
|
||||
{
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -44,10 +44,22 @@ SetFilterWin2KOption
|
||||
--------------------
|
||||
Takes boolean, sets or resets the --filterwin2k option.
|
||||
|
||||
SetFilterA
|
||||
------------------------
|
||||
Takes boolean, sets or resets the --filter-A option.
|
||||
|
||||
SetFilterAAAA
|
||||
------------------------
|
||||
Takes boolean, sets or resets the --filter-AAAA option.
|
||||
|
||||
SetBogusPrivOption
|
||||
------------------
|
||||
Takes boolean, sets or resets the --bogus-priv option.
|
||||
|
||||
SetLocaliseQueriesOption
|
||||
------------------------
|
||||
Takes boolean, sets or resets the --localise-queries option.
|
||||
|
||||
SetServers
|
||||
----------
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
@@ -248,6 +260,15 @@ GetMetrics
|
||||
|
||||
Returns an array with various metrics for DNS and DHCP.
|
||||
|
||||
GetServerMetrics
|
||||
----------------
|
||||
|
||||
Returns per-DNS-server metrics.
|
||||
|
||||
ClearMetrics
|
||||
------------
|
||||
|
||||
Clear call metric counters, global and per-server.
|
||||
|
||||
2. SIGNALS
|
||||
----------
|
||||
|
||||
1
debian
Submodule
1
debian
Submodule
Submodule debian added at 83e05da879
1440
debian/changelog
vendored
1440
debian/changelog
vendored
File diff suppressed because it is too large
Load Diff
5
debian/conffiles
vendored
5
debian/conffiles
vendored
@@ -1,5 +0,0 @@
|
||||
/etc/init.d/dnsmasq
|
||||
/etc/default/dnsmasq
|
||||
/etc/dnsmasq.conf
|
||||
/etc/resolvconf/update.d/dnsmasq
|
||||
/etc/insserv.conf.d/dnsmasq
|
||||
66
debian/control
vendored
66
debian/control
vendored
@@ -1,66 +0,0 @@
|
||||
Source: dnsmasq
|
||||
Section: net
|
||||
Priority: optional
|
||||
Build-depends: 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.2-dev, dh-runit, debhelper-compat (= 10),
|
||||
pkg-config
|
||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
||||
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
|
||||
Vcs-Browser: http://thekelleys.org.uk/gitweb/?p=dnsmasq.git
|
||||
Standards-Version: 3.9.8
|
||||
|
||||
Package: dnsmasq
|
||||
Architecture: all
|
||||
Depends: netbase, dnsmasq-base,
|
||||
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6), ${misc:Depends}
|
||||
Suggests: resolvconf
|
||||
Breaks: ${runit:Breaks}
|
||||
Conflicts: resolvconf (<<1.15), ${runit:Conflicts}
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP
|
||||
server. It is designed to provide DNS and optionally, DHCP, to a
|
||||
small network. It can serve the names of local machines which are
|
||||
not in the global DNS. The DHCP server integrates with the DNS
|
||||
server and allows machines with DHCP-allocated addresses
|
||||
to appear in the DNS with names configured either in each host or
|
||||
in a central configuration file. Dnsmasq supports static and dynamic
|
||||
DHCP leases and BOOTP/TFTP for network booting of diskless machines.
|
||||
|
||||
Package: dnsmasq-base
|
||||
Architecture: any
|
||||
Depends: adduser, ${shlibs:Depends}
|
||||
Breaks: dnsmasq (<< 2.63-1~)
|
||||
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||
Recommends: dns-root-data
|
||||
Provides: dnsmasq-base
|
||||
Conflicts: dnsmasq-base-lua
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
This package contains the dnsmasq executable and documentation, but
|
||||
not the infrastructure required to run it as a system daemon. For
|
||||
that, install the dnsmasq package.
|
||||
|
||||
Package: dnsmasq-base-lua
|
||||
Architecture: any
|
||||
Depends: adduser, ${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
|
||||
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: ${shlibs:Depends}
|
||||
Conflicts: dnsmasq (<<2.40)
|
||||
Description: Utilities for manipulating DHCP leases
|
||||
Small utilities to query a DHCP server's lease database and
|
||||
remove leases from it. These programs are distributed with dnsmasq
|
||||
and may not work correctly with other DHCP servers.
|
||||
21
debian/copyright
vendored
21
debian/copyright
vendored
@@ -1,21 +0,0 @@
|
||||
dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
|
||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
On Debian GNU/Linux systems, the text of the GNU general public license is
|
||||
available in the file /usr/share/common-licenses/GPL-2 or
|
||||
/usr/share/common-licenses/GPL-3
|
||||
|
||||
The Debian package of dnsmasq was created by Simon Kelley with assistance
|
||||
from Lars Bahner.
|
||||
|
||||
18
debian/dbus.conf
vendored
18
debian/dbus.conf
vendored
@@ -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>
|
||||
|
||||
42
debian/default
vendored
42
debian/default
vendored
@@ -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"
|
||||
|
||||
# Whether or not to run the dnsmasq daemon; set to 0 to disable.
|
||||
# Note that this is only valid when using SYSV init. For systemd,
|
||||
# use "systemctl disable dnsmasq"
|
||||
ENABLED=1
|
||||
|
||||
# By default search this drop directory for configuration options.
|
||||
# Libvirt leaves a file here to make the system dnsmasq play nice.
|
||||
# Comment out this line if you don't want this. The dpkg-* are file
|
||||
# endings which cause dnsmasq to skip that file. This avoids pulling
|
||||
# in backups made by dpkg.
|
||||
CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
|
||||
|
||||
# If the resolvconf package is installed, dnsmasq will use its output
|
||||
# rather than the contents of /etc/resolv.conf to find upstream
|
||||
# nameservers. Uncommenting this line inhibits this behaviour.
|
||||
# Note that including a "resolv-file=<filename>" line in
|
||||
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
|
||||
# installed: the line below must be uncommented.
|
||||
#IGNORE_RESOLVCONF=yes
|
||||
|
||||
# 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"
|
||||
1
debian/dnsmasq-base.conffiles
vendored
1
debian/dnsmasq-base.conffiles
vendored
@@ -1 +0,0 @@
|
||||
/etc/dbus-1/system.d/dnsmasq.conf
|
||||
24
debian/dnsmasq-base.postinst
vendored
24
debian/dnsmasq-base.postinst
vendored
@@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# Create the dnsmasq user in dnsmasq-base, so that Dbus doesn't complain.
|
||||
|
||||
# create a user to run as (code stolen from dovecot-common)
|
||||
if [ "$1" = "configure" ]; then
|
||||
if [ -z "`id -u dnsmasq 2> /dev/null`" ]; then
|
||||
adduser --system --home /var/lib/misc --gecos "dnsmasq" \
|
||||
--no-create-home --disabled-password \
|
||||
--quiet dnsmasq || true
|
||||
fi
|
||||
|
||||
# Make the directory where we keep the pid file - this
|
||||
# has to be owned by "dnsmasq" so that the file can be unlinked.
|
||||
# This is only actually used by the dnsmasq binary package, not
|
||||
# dnsmasq-base, but it's much easier to create it here so that
|
||||
# we don't have synchronisation issues with the creation of the
|
||||
# dnsmasq user.
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq
|
||||
chown dnsmasq:nogroup /run/dnsmasq
|
||||
fi
|
||||
fi
|
||||
11
debian/dnsmasq-base.postrm
vendored
11
debian/dnsmasq-base.postrm
vendored
@@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ purge = "$1" ]; then
|
||||
if [ -x "$(command -v deluser)" ]; then
|
||||
deluser --quiet --system dnsmasq > /dev/null || true
|
||||
else
|
||||
echo >&2 "not removing dnsmasq system account because deluser command was not found"
|
||||
fi
|
||||
rm -rf /run/dnsmasq
|
||||
fi
|
||||
1
debian/dnsmasq.runit
vendored
1
debian/dnsmasq.runit
vendored
@@ -1 +0,0 @@
|
||||
debian/dnsmasq.runscript name=dnsmasq,logscript,presubj
|
||||
5
debian/dnsmasq.runscript/finish
vendored
5
debian/dnsmasq.runscript/finish
vendored
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh -eu
|
||||
if [ -x /sbin/resolvconf ] ; then
|
||||
/sbin/resolvconf -d lo.dnsmasq
|
||||
fi
|
||||
|
||||
43
debian/dnsmasq.runscript/run
vendored
43
debian/dnsmasq.runscript/run
vendored
@@ -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
|
||||
325
debian/init
vendored
325
debian/init
vendored
@@ -1,325 +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
|
||||
|
||||
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.
|
||||
ENABLED=1
|
||||
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
|
||||
|
||||
# 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.
|
||||
test -e /usr/share/dnsmasq/installed-marker || exit 0
|
||||
|
||||
test -x ${DAEMON} || exit 0
|
||||
|
||||
# Provide skeleton LSB log functions for backports which don't have LSB functions.
|
||||
if [ -f /lib/lsb/init-functions ]; then
|
||||
. /lib/lsb/init-functions
|
||||
else
|
||||
log_warning_msg () {
|
||||
echo "${@}."
|
||||
}
|
||||
|
||||
log_success_msg () {
|
||||
echo "${@}."
|
||||
}
|
||||
|
||||
log_daemon_msg () {
|
||||
echo -n "${1}: ${2}"
|
||||
}
|
||||
|
||||
log_end_msg () {
|
||||
if [ "${1}" -eq 0 ]; then
|
||||
echo "."
|
||||
elif [ "${1}" -eq 255 ]; then
|
||||
/bin/echo -e " (warning)."
|
||||
else
|
||||
/bin/echo -e " failed!"
|
||||
fi
|
||||
}
|
||||
fi
|
||||
|
||||
# RESOLV_CONF:
|
||||
# If the resolvconf package is installed then use the resolv conf file
|
||||
# that it provides as the default. Otherwise use /etc/resolv.conf as
|
||||
# the default.
|
||||
#
|
||||
# If IGNORE_RESOLVCONF is set in /etc/default/dnsmasq or an explicit
|
||||
# filename is set there then this inhibits the use of the resolvconf-provided
|
||||
# information.
|
||||
#
|
||||
# Note that if the resolvconf package is installed it is not possible to
|
||||
# override it just by configuration in /etc/dnsmasq.conf, it is necessary
|
||||
# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
|
||||
|
||||
if [ ! "${RESOLV_CONF}" ] &&
|
||||
[ "${IGNORE_RESOLVCONF}" != "yes" ] &&
|
||||
[ -x /sbin/resolvconf ]
|
||||
then
|
||||
RESOLV_CONF=/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
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
# 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}
|
||||
}
|
||||
|
||||
stop_resolvconf()
|
||||
{
|
||||
if [ -x /sbin/resolvconf ] ; then
|
||||
/sbin/resolvconf -d lo.${NAME}${INSTANCE:+.${INSTANCE}}
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
status()
|
||||
{
|
||||
# Return
|
||||
# 0 if daemon is running
|
||||
# 1 if daemon is dead and pid file exists
|
||||
# 3 if daemon is not running
|
||||
# 4 if daemon status is unknown
|
||||
start-stop-daemon --start --quiet --pidfile /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)
|
||||
test "${ENABLED}" != "0" || exit 0
|
||||
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
|
||||
if [ "${ENABLED}" != "0" ]; then
|
||||
log_daemon_msg "Stopping ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
|
||||
fi
|
||||
stop
|
||||
RETVAL="${?}"
|
||||
if [ "${ENABLED}" = "0" ]; then
|
||||
case "${RETVAL}" in
|
||||
0) log_daemon_msg "Stopping ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"; log_end_msg 0 ;;
|
||||
esac
|
||||
exit 0
|
||||
fi
|
||||
case "${RETVAL}" in
|
||||
0) log_end_msg 0 ; exit 0 ;;
|
||||
1) log_warning_msg "(not running)" ; exit 0 ;;
|
||||
*) log_end_msg 1; exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
checkconfig)
|
||||
${DAEMON} --test ${CONFIG_DIR:+ -7 ${CONFIG_DIR}} ${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} >/dev/null 2>&1
|
||||
RETVAL="${?}"
|
||||
exit ${RETVAL}
|
||||
;;
|
||||
restart|force-reload)
|
||||
test "${ENABLED}" != "0" || exit 1
|
||||
${DAEMON} --test ${CONFIG_DIR:+ -7 ${CONFIG_DIR}} ${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} >/dev/null 2>&1
|
||||
if [ ${?} -ne 0 ]; then
|
||||
NAME="configuration syntax check"
|
||||
RETVAL="2"
|
||||
else
|
||||
stop_resolvconf
|
||||
stop
|
||||
RETVAL="${?}"
|
||||
fi
|
||||
log_daemon_msg "Restarting ${DESC}" "${NAME}${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`
|
||||
;;
|
||||
systemd-start-resolvconf)
|
||||
start_resolvconf
|
||||
;;
|
||||
systemd-stop-resolvconf)
|
||||
stop_resolvconf
|
||||
;;
|
||||
systemd-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 ] || return 2 ; }
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 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}}
|
||||
;;
|
||||
*)
|
||||
echo "Usage: /etc/init.d/${NAME} {start|stop|restart|force-reload|dump-stats|status}" >&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
1
debian/insserv
vendored
1
debian/insserv
vendored
@@ -1 +0,0 @@
|
||||
$named dnsmasq
|
||||
2
debian/installed-marker
vendored
2
debian/installed-marker
vendored
@@ -1,2 +0,0 @@
|
||||
# This file indicates dnsmasq (and not just dnsmasq-base) is installed.
|
||||
# It is an implementation detail of the dnsmasq init script.
|
||||
3
debian/lintian-override
vendored
3
debian/lintian-override
vendored
@@ -1,3 +0,0 @@
|
||||
# dnsmasq-base and dnsmasq-base-lua are mutually exclusive and both
|
||||
# provide /usr/share/doc/dnsmasq-base
|
||||
dnsmasq-base-lua binary: usr-share-doc-symlink-without-dependency dnsmasq-base
|
||||
41
debian/postinst
vendored
41
debian/postinst
vendored
@@ -1,41 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# /usr/share/doc/dnsmasq was a symlink in versions < 2.81-1 (see #985282)
|
||||
dpkg-maintscript-helper symlink_to_dir /usr/share/doc/dnsmasq dnsmasq-base 2.84-1.2~ dnsmasq -- "$@"
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
# This will only remove masks created by d-s-h on package removal.
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
|
||||
|
||||
# was-enabled defaults to true, so new installations run enable.
|
||||
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
|
||||
# Enables the unit on first installation, creates new
|
||||
# symlinks on upgrades if the unit file has changed.
|
||||
deb-systemd-helper enable dnsmasq.service >/dev/null || true
|
||||
else
|
||||
# Update the statefile to add new symlinks (if any), which need to be
|
||||
# cleaned up on purge. Also remove old symlinks.
|
||||
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
if [ -x /etc/init.d/dnsmasq ]; then
|
||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||
|
||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
|
||||
if [ -e /run/dnsmasq/dnsmasq.pid ]; then
|
||||
ACTION=restart
|
||||
else
|
||||
ACTION=start
|
||||
fi
|
||||
|
||||
if [ -x /usr/sbin/invoke-rc.d ] ; then
|
||||
invoke-rc.d dnsmasq $ACTION || true
|
||||
else
|
||||
/etc/init.d/dnsmasq $ACTION || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
25
debian/postrm
vendored
25
debian/postrm
vendored
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# /usr/share/doc/dnsmasq was a symlink in versions < 2.81-1 (see #985282)
|
||||
dpkg-maintscript-helper symlink_to_dir /usr/share/doc/dnsmasq dnsmasq-base 2.84-1.2~ dnsmasq -- "$@"
|
||||
|
||||
if [ purge = "$1" ]; then
|
||||
update-rc.d dnsmasq remove >/dev/null
|
||||
fi
|
||||
|
||||
# Code copied from dh_systemd_enable ----------------------
|
||||
if [ "$1" = "remove" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper mask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$1" = "purge" ]; then
|
||||
if [ -x "/usr/bin/deb-systemd-helper" ]; then
|
||||
deb-systemd-helper purge dnsmasq.service >/dev/null
|
||||
deb-systemd-helper unmask dnsmasq.service >/dev/null
|
||||
fi
|
||||
fi
|
||||
# End code copied from dh_systemd_enable ------------------
|
||||
|
||||
5
debian/preinst
vendored
5
debian/preinst
vendored
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# /usr/share/doc/dnsmasq was a symlink in versions < 2.81-1 (see #985282)
|
||||
dpkg-maintscript-helper symlink_to_dir /usr/share/doc/dnsmasq dnsmasq-base 2.84-1.2~ dnsmasq -- "$@"
|
||||
14
debian/prerm
vendored
14
debian/prerm
vendored
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
if [ "$1" = "remove" ]; then
|
||||
if [ -x /usr/sbin/invoke-rc.d ] ; then
|
||||
invoke-rc.d dnsmasq stop || true
|
||||
else
|
||||
/etc/init.d/dnsmasq stop || true
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
|
||||
79
debian/readme
vendored
79
debian/readme
vendored
@@ -1,79 +0,0 @@
|
||||
Notes on configuring dnsmasq as packaged for Debian.
|
||||
|
||||
(1) To configure dnsmasq edit /etc/dnsmasq.conf. The file is well
|
||||
commented; see also the dnsmasq.8 man page for explanation of
|
||||
the options. The file /etc/default/dnsmasq also exists but it
|
||||
shouldn't need to be touched in most cases. To set up DHCP
|
||||
options you might need to refer to a copy of RFC 2132. This is
|
||||
available on Debian systems in the package doc-rfc-std as the file
|
||||
/usr/share/doc/RFC/draft-standard/rfc2132.txt.gz .
|
||||
|
||||
(2) Installing the dnsmasq package also creates the directory
|
||||
/etc/dnsmasq.d which is searched by dnsmasq for configuration file
|
||||
fragments. This behaviour can be disabled by editing
|
||||
/etc/default/dnsmasq.
|
||||
|
||||
(3) If the Debian resolvconf package is installed then, regardless
|
||||
of what interface configuration daemons are employed, the list of
|
||||
nameservers to which dnsmasq should forward queries can be found
|
||||
in /var/run/dnsmasq/resolv.conf; also, 127.0.0.1 is listed as the
|
||||
first nameserver address in /etc/resolv.conf. This works using the
|
||||
default configurations of resolvconf and dnsmasq.
|
||||
|
||||
(4) In the absence of resolvconf, if you are using dhcpcd then
|
||||
dnsmasq should read the list of nameservers from the automatically
|
||||
generated file /etc/dhcpc/resolv.conf. You should list 127.0.0.1
|
||||
as the first nameserver address in /etc/resolv.conf.
|
||||
|
||||
(5) In the absence of resolvconf, if you are using pppd then
|
||||
dnsmasq should read the list of nameservers from the automatically
|
||||
generated file /etc/ppp/resolv.conf. You should list 127.0.0.1
|
||||
as the first nameserver address in /etc/resolv.conf.
|
||||
|
||||
(6) In the absence of resolvconf, dns-nameservers lines in
|
||||
/etc/network/interfaces are ignored. If you do 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.
|
||||
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.
|
||||
7
debian/readme.dnsmasq.d
vendored
7
debian/readme.dnsmasq.d
vendored
@@ -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
84
debian/resolvconf
vendored
@@ -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"
|
||||
|
||||
13
debian/resolvconf-package
vendored
13
debian/resolvconf-package
vendored
@@ -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
|
||||
305
debian/rules
vendored
305
debian/rules
vendored
@@ -1,305 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# debian/rules file - for dnsmasq.
|
||||
# Copyright 2001-2020 by Simon Kelley
|
||||
# Based on the sample in the debian hello package which carries the following:
|
||||
# Copyright 1994,1995 by Ian Jackson.
|
||||
# I hereby give you perpetual unlimited permission to copy,
|
||||
# modify and relicense this file, provided that you do not remove
|
||||
# my name from the file itself. (I assert my moral right of
|
||||
# paternity under the Copyright, Designs and Patents Act 1988.)
|
||||
# This file may have to be extensively modified
|
||||
|
||||
package=dnsmasq-base
|
||||
|
||||
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all,+pie,+bindnow" dpkg-buildflags
|
||||
|
||||
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
|
||||
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
|
||||
CFLAGS += -Wall -W
|
||||
|
||||
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
|
||||
|
||||
DEB_COPTS = $(COPTS)
|
||||
|
||||
TARGET = install-i18n
|
||||
|
||||
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
|
||||
DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
|
||||
|
||||
ifeq ($(origin CC),default)
|
||||
CC = $(DEB_HOST_GNU_TYPE)-gcc
|
||||
endif
|
||||
|
||||
# Support non-cross-builds on systems without gnu-triplet-binaries for pkg-config.
|
||||
ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
|
||||
PKG_CONFIG=pkg-config
|
||||
else
|
||||
PKG_CONFIG=$(DEB_HOST_GNU_TYPE)-pkg-config
|
||||
endif
|
||||
|
||||
# Force package version based on git tags.
|
||||
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
||||
PACKAGE_VERSION = $(shell bld/get-version `pwd` | sed 's/test/~&/; s/[a-z]/~&/; s/-/./g; s/$$/-1/; s/^/-v/';)
|
||||
endif
|
||||
|
||||
ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_DBUS
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_LIBIDN2
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
DEB_COPTS += -DHAVE_CONNTRACK
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noipset,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_IPSET
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nodhcp6,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_DHCP6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noipv6,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_IPV6
|
||||
endif
|
||||
|
||||
ifneq (,$(filter notftp,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_TFTP
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nodhcp,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_DHCP
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noscript,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DNO_SCRIPT
|
||||
endif
|
||||
|
||||
ifneq (,$(filter nortc,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_BROKEN_RTC
|
||||
endif
|
||||
|
||||
ifneq (,$(filter noi18n,$(DEB_BUILD_OPTIONS)))
|
||||
TARGET = install
|
||||
endif
|
||||
|
||||
ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_LUASCRIPT
|
||||
endif
|
||||
|
||||
ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_DNSSEC
|
||||
endif
|
||||
|
||||
ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
|
||||
# For strlcpy in FreeBSD
|
||||
LIBS += $(shell ${PKG_CONFIG} --libs libbsd-overlay)
|
||||
CFLAGS += $(shell ${PKG_CONFIG} --cflags libbsd-overlay)
|
||||
endif
|
||||
|
||||
define build_tree
|
||||
rm -rf $1
|
||||
install -m 755 \
|
||||
-d $1/DEBIAN \
|
||||
-d $1/etc/dbus-1/system.d \
|
||||
-d $1/usr/share/doc/$(package) \
|
||||
-d $1/usr/share/doc/$(package)/examples \
|
||||
-d $1/usr/share/$(package) \
|
||||
-d $1/var/lib/misc
|
||||
|
||||
endef
|
||||
|
||||
define add_docs
|
||||
# Need to remove paypal links in Debian Package for policy reasons.
|
||||
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >$1/usr/share/doc/$(package)/doc.html
|
||||
echo "</BODY>" >>$1/usr/share/doc/$(package)/doc.html
|
||||
install -m 644 setup.html $1/usr/share/doc/$(package)/.
|
||||
install -m 644 dnsmasq.conf.example $1/usr/share/doc/$(package)/examples/.
|
||||
install -m 644 FAQ $1/usr/share/doc/$(package)/.
|
||||
gzip -9n $1/usr/share/doc/$(package)/FAQ
|
||||
install -m 644 CHANGELOG $1/usr/share/doc/$(package)/changelog
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog
|
||||
install -m 644 CHANGELOG.archive $1/usr/share/doc/$(package)/changelog.archive
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog.archive
|
||||
install -m 644 dbus/DBus-interface $1/usr/share/doc/$(package)/.
|
||||
gzip -9n $1/usr/share/doc/$(package)/DBus-interface
|
||||
install -m 644 debian/systemd_howto $1/usr/share/doc/$(package)/.
|
||||
gzip -9n $1/usr/share/doc/$(package)/systemd_howto
|
||||
gzip -9n $1/usr/share/man/man8/dnsmasq.8
|
||||
for f in $1/usr/share/man/*; do \
|
||||
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||
gzip -9n $$f/man8/dnsmasq.8 ; \
|
||||
fi \
|
||||
done
|
||||
endef
|
||||
|
||||
define add_files
|
||||
install -m 644 trust-anchors.conf $1/usr/share/$(package)/.
|
||||
install -m 644 debian/dnsmasq-base.conffiles $1/DEBIAN/conffiles
|
||||
install -m 755 debian/dnsmasq-base.postinst $1/DEBIAN/postinst
|
||||
install -m 755 debian/dnsmasq-base.postrm $1/DEBIAN/postrm
|
||||
install -m 644 debian/changelog $1/usr/share/doc/$(package)/changelog.Debian
|
||||
gzip -9n $1/usr/share/doc/$(package)/changelog.Debian
|
||||
install -m 644 debian/readme $1/usr/share/doc/$(package)/README.Debian
|
||||
install -m 644 debian/copyright $1/usr/share/doc/$(package)/copyright
|
||||
install -m 644 debian/dbus.conf $1/etc/dbus-1/system.d/dnsmasq.conf
|
||||
endef
|
||||
|
||||
clean:
|
||||
$(checkdir)
|
||||
make BUILDDIR=debian/build/no-lua clean
|
||||
make BUILDDIR=debian/build/lua clean
|
||||
make -C contrib/lease-tools clean
|
||||
rm -rf debian/build debian/trees debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||
|
||||
binary-indep: checkroot
|
||||
$(checkdir)
|
||||
rm -rf debian/trees/daemon
|
||||
install -m 755 \
|
||||
-d debian/trees/daemon/DEBIAN \
|
||||
-d debian/trees/daemon/usr/share/doc/dnsmasq \
|
||||
-d debian/trees/daemon/etc/init.d \
|
||||
-d debian/trees/daemon/etc/dnsmasq.d \
|
||||
-d debian/trees/daemon/etc/resolvconf/update.d \
|
||||
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||
-d debian/trees/daemon/usr/share/dnsmasq \
|
||||
-d debian/trees/daemon/usr/share/doc/dnsmasq \
|
||||
-d debian/trees/daemon/etc/default \
|
||||
-d debian/trees/daemon/lib/systemd/system \
|
||||
-d debian/trees/daemon/usr/lib/tmpfiles.d \
|
||||
-d debian/trees/daemon/etc/insserv.conf.d
|
||||
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
|
||||
install -m 755 debian/postinst debian/postrm debian/preinst debian/prerm debian/trees/daemon/DEBIAN
|
||||
if ! dpkg-vendor --derives-from Ubuntu; then \
|
||||
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper; \
|
||||
dh_runit -pdnsmasq -Pdebian/trees/daemon; \
|
||||
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst; \
|
||||
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm; \
|
||||
cd debian/trees/daemon && find etc/sv -type f -printf '/%p\n' >>DEBIAN/conffiles; \
|
||||
fi
|
||||
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
|
||||
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
|
||||
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
|
||||
install -m 644 debian/installed-marker debian/trees/daemon/usr/share/dnsmasq
|
||||
install -m 644 debian/default debian/trees/daemon/etc/default/dnsmasq
|
||||
install -m 644 dnsmasq.conf.example debian/trees/daemon/etc/dnsmasq.conf
|
||||
install -m 644 debian/readme.dnsmasq.d debian/trees/daemon/etc/dnsmasq.d/README
|
||||
install -m 644 debian/systemd.service debian/trees/daemon/lib/systemd/system/dnsmasq.service
|
||||
install -m 644 debian/systemd@.service debian/trees/daemon/lib/systemd/system/dnsmasq@.service
|
||||
install -m 644 debian/tmpfiles.conf debian/trees/daemon/usr/lib/tmpfiles.d/dnsmasq.conf
|
||||
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
|
||||
install -m 644 debian/copyright debian/trees/daemon/usr/share/doc/dnsmasq/copyright
|
||||
install -m 644 debian/changelog debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
|
||||
gzip -9n debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
|
||||
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/dnsmasq.substvars -pdnsmasq -Pdebian/trees/daemon
|
||||
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/daemon
|
||||
chmod -R g-ws debian/trees/daemon
|
||||
dpkg --build debian/trees/daemon ..
|
||||
|
||||
binary-arch: checkroot
|
||||
$(call build_tree,debian/trees/base)
|
||||
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||
$(call add_docs,debian/trees/base)
|
||||
else
|
||||
rm -rf debian/trees/base/usr/share/man
|
||||
endif
|
||||
$(call add_files,debian/trees/base)
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/base/usr/sbin/dnsmasq
|
||||
endif
|
||||
cd debian/trees/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/trees/base/usr/sbin/dnsmasq
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/trees/base
|
||||
find debian/trees/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/base
|
||||
chmod -R g-ws debian/trees/base
|
||||
dpkg --build debian/trees/base ..
|
||||
|
||||
$(call build_tree,debian/trees/lua-base)
|
||||
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||
$(call add_docs,debian/trees/lua-base)
|
||||
else
|
||||
rm -rf debian/trees/lua-base/usr/share/man
|
||||
endif
|
||||
$(call add_files,debian/trees/lua-base)
|
||||
install -m 755 -d debian/trees/lua-base/usr/share/lintian/overrides
|
||||
install -m 644 debian/lintian-override debian/trees/lua-base/usr/share/lintian/overrides/dnsmasq-base-lua
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/lua-base/usr/sbin/dnsmasq
|
||||
endif
|
||||
ln -s $(package) debian/trees/lua-base/usr/share/doc/dnsmasq-base-lua
|
||||
cd debian/trees/lua-base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/trees/lua-base/usr/sbin/dnsmasq
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base-lua -Pdebian/trees/lua-base
|
||||
find debian/trees/lua-base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/lua-base
|
||||
chmod -R g-ws debian/trees/lua-base
|
||||
dpkg --build debian/trees/lua-base ..
|
||||
|
||||
|
||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
rm -rf debian/trees/utils
|
||||
install -m 755 -d debian/trees/utils/DEBIAN \
|
||||
-d debian/trees/utils/usr/bin \
|
||||
-d debian/trees/utils/usr/share/doc/dnsmasq-utils
|
||||
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||
install -m 755 -d debian/trees/utils/usr/share/man/man1
|
||||
endif
|
||||
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
|
||||
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
|
||||
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||
install -m 644 contrib/lease-tools/dhcp_release.1 debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
endif
|
||||
install -m 644 debian/copyright debian/trees/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||
install -m 644 debian/changelog debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
gzip -9n debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release6
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
endif
|
||||
cd debian/trees/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps -Tdebian/utils-substvars debian/trees/utils/usr/bin/dhcp_release debian/trees/utils/usr/bin/dhcp_release6 debian/trees/utils/usr/bin/dhcp_lease_time
|
||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/trees/utils
|
||||
find debian/trees/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||
chown -R root.root debian/trees/utils
|
||||
chmod -R g-ws debian/trees/utils
|
||||
dpkg --build debian/trees/utils ..
|
||||
endif
|
||||
|
||||
define checkdir
|
||||
test -f Makefile -a -f debian/rules
|
||||
endef
|
||||
|
||||
# Below here is fairly generic really
|
||||
|
||||
binary: binary-arch binary-indep
|
||||
|
||||
build:
|
||||
build-arch:
|
||||
build-indep:
|
||||
|
||||
checkroot:
|
||||
test root = "`whoami`"
|
||||
|
||||
.PHONY: binary binary-arch binary-indep clean checkroot
|
||||
|
||||
|
||||
1
debian/source/format
vendored
1
debian/source/format
vendored
@@ -1 +0,0 @@
|
||||
1.0
|
||||
31
debian/systemd.service
vendored
31
debian/systemd.service
vendored
@@ -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=/etc/init.d/dnsmasq checkconfig
|
||||
|
||||
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
||||
# wrapper picking up extra configuration files and then execs dnsmasq
|
||||
# itself, when called with the "systemd-exec" function.
|
||||
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
||||
|
||||
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||
# resolvconf to work with the dnsmasq DNS server. They're called like
|
||||
# this to get correct error handling (ie don't start-resolvconf if the
|
||||
# dnsmasq daemon fails to start).
|
||||
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
|
||||
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
|
||||
|
||||
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
31
debian/systemd@.service
vendored
31
debian/systemd@.service
vendored
@@ -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=/etc/init.d/dnsmasq checkconfig "%i"
|
||||
|
||||
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
||||
# wrapper picking up extra configuration files and then execs dnsmasq
|
||||
# itself, when called with the "systemd-exec" function.
|
||||
ExecStart=/etc/init.d/dnsmasq systemd-exec "%i"
|
||||
|
||||
# The systemd-*-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=/etc/init.d/dnsmasq systemd-start-resolvconf "%i"
|
||||
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf "%i"
|
||||
|
||||
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
41
debian/systemd_howto
vendored
41
debian/systemd_howto
vendored
@@ -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)
|
||||
1
debian/tmpfiles.conf
vendored
1
debian/tmpfiles.conf
vendored
@@ -1 +0,0 @@
|
||||
d /run/dnsmasq 755 dnsmasq nogroup
|
||||
@@ -85,6 +85,16 @@
|
||||
# subdomains to the vpn and search ipsets:
|
||||
#ipset=/yahoo.com/google.com/vpn,search
|
||||
|
||||
# Add the IPs of all queries to yahoo.com, google.com, and their
|
||||
# subdomains to netfilters sets, which is equivalent to
|
||||
# 'nft add element ip test vpn { ... }; nft add element ip test search { ... }'
|
||||
#nftset=/yahoo.com/google.com/ip#test#vpn,ip#test#search
|
||||
|
||||
# Use netfilters sets for both IPv4 and IPv6:
|
||||
# This adds all addresses in *.yahoo.com to vpn4 and vpn6 for IPv4 and IPv6 addresses.
|
||||
#nftset=/yahoo.com/4#ip#test#vpn4
|
||||
#nftset=/yahoo.com/6#ip#test#vpn6
|
||||
|
||||
# You can control how dnsmasq talks to a server: this forces
|
||||
# queries to 10.1.2.3 to be routed via eth1
|
||||
# server=10.1.2.3@eth1
|
||||
@@ -384,7 +394,7 @@
|
||||
|
||||
# The following DHCP options set up dnsmasq in the same way as is specified
|
||||
# for the ISC dhcpcd in
|
||||
# http://www.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
|
||||
# https://web.archive.org/web/20040313070105/http://us1.samba.org/samba/ftp/docs/textdocs/DHCP-Server-Configuration.txt
|
||||
# adapted for a typical dnsmasq installation where the host running
|
||||
# dnsmasq is also the host running samba.
|
||||
# you may want to uncomment some or all of them if you use
|
||||
@@ -654,7 +664,7 @@
|
||||
# Provide an alias for a "local" DNS name. Note that this _only_ works
|
||||
# for targets which are names from DHCP or /etc/hosts. Give host
|
||||
# "bert" another name, bertrand
|
||||
#cname=bertand,bert
|
||||
#cname=bertrand,bert
|
||||
|
||||
# For debugging purposes, log each DNS query as it passes through
|
||||
# dnsmasq.
|
||||
|
||||
300
man/dnsmasq.8
300
man/dnsmasq.8
@@ -60,7 +60,8 @@ in alphabetical order.
|
||||
.TP
|
||||
.B --hostsdir=<path>
|
||||
Read all the hosts files contained in the directory. New or changed files
|
||||
are read automatically. See \fB--dhcp-hostsdir\fP for details.
|
||||
are read automatically and modified and deleted files have removed records
|
||||
automatically deleted.
|
||||
.TP
|
||||
.B \-E, --expand-hosts
|
||||
Add the domain to simple names (without a period) in /etc/hosts
|
||||
@@ -105,6 +106,17 @@ Dnsmasq limits the value of this option to one hour, unless recompiled.
|
||||
.B --auth-ttl=<time>
|
||||
Set the TTL value returned in answers from the authoritative server.
|
||||
.TP
|
||||
.B --fast-dns-retry=[<initial retry delay in ms>[,<time to continue retries in ms>]]
|
||||
Under normal circumstances, dnsmasq relies on DNS clients to do retries; it
|
||||
does not generate timeouts itself. Setting this option
|
||||
instructs dnsmasq to generate its own retries starting after a delay
|
||||
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. 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
|
||||
normal. This is intended for use when dnsmasq is run under daemontools
|
||||
@@ -122,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
|
||||
@@ -172,7 +184,8 @@ to zero completely disables DNS function, leaving only DHCP and/or TFTP.
|
||||
.TP
|
||||
.B \-P, --edns-packet-max=<size>
|
||||
Specify the largest EDNS.0 UDP packet which is supported by the DNS
|
||||
forwarder. Defaults to 4096, which is the RFC5625-recommended size.
|
||||
forwarder. Defaults to 1232, which is the recommended size following the
|
||||
DNS flag day in 2020. Only increase if you know what you are doing.
|
||||
.TP
|
||||
.B \-Q, --query-port=<query_port>
|
||||
Send outbound DNS queries from, and listen for their replies on, the
|
||||
@@ -180,7 +193,15 @@ specific UDP port <query_port> instead of using random ports. NOTE
|
||||
that using this option will make dnsmasq less secure against DNS
|
||||
spoofing attacks but it may be faster and use less resources. Setting this option
|
||||
to zero makes dnsmasq use a single port allocated to it by the
|
||||
OS: this was the default behaviour in versions prior to 2.43.
|
||||
OS: this was the default behaviour in versions prior to 2.43.
|
||||
.TP
|
||||
.B --port-limit=<#ports>
|
||||
By default, when sending a query via random ports to multiple upstream servers or
|
||||
retrying a query dnsmasq will use a single random port for all the tries/retries.
|
||||
This option allows a larger number of ports to be used, which can increase robustness
|
||||
in certain network configurations. Note that increasing this to more than
|
||||
two or three can have security and resource implications and should only
|
||||
be done with understanding of those.
|
||||
.TP
|
||||
.B --min-port=<port>
|
||||
Do not use ports less than that given as source for outbound DNS
|
||||
@@ -250,16 +271,25 @@ the address dnsmasq is listening on. When an interface is specified,
|
||||
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
||||
addresses associated with the interface. Since any defined authoritative zones are also available as part of the normal recusive DNS service supplied by dnsmasq, it can make sense to have an --auth-server declaration with no interfaces or address, but simply specifying the primary external nameserver.
|
||||
.TP
|
||||
.B --local-service
|
||||
.B --local-service[=net|host]
|
||||
Without parameter or with net parameter, restricts service to connected network.
|
||||
Accept DNS queries only from hosts whose address is on a local subnet,
|
||||
ie a subnet for which an interface exists on the server. This option
|
||||
ie a subnet for which an interface exists on the server. With host parameter, listens
|
||||
only on lo interface and accepts queries from localhost only. This option
|
||||
only has effect if there are no \fB--interface\fP, \fB--except-interface\fP,
|
||||
\fB--listen-address\fP or \fB--auth-server\fP options. It is intended to be set as
|
||||
a default on installation, to allow unconfigured installations to be
|
||||
useful but also safe from being used for DNS amplification attacks.
|
||||
.TP
|
||||
.TP
|
||||
.B \-2, --no-dhcp-interface=<interface name>
|
||||
Do not provide DHCP or TFTP on the specified interface, but do provide DNS service.
|
||||
Do not provide DHCP, TFTP or router advertisement on the specified interface, but do provide DNS service.
|
||||
.TP
|
||||
.B --no-dhcpv4-interface=<interface name>
|
||||
Disable only IPv4 DHCP on the specified interface.
|
||||
.TP
|
||||
.B
|
||||
--no-dhcpv6-interface=<interface name>
|
||||
Disable IPv6 DHCP and router advertisement on the specified interface.
|
||||
.TP
|
||||
.B \-a, --listen-address=<ipaddr>
|
||||
Listen on the given IP address(es). Both
|
||||
@@ -304,7 +334,8 @@ Return answers to DNS queries from /etc/hosts and \fB--interface-name\fP and \fB
|
||||
received. If a name has more than one address associated with
|
||||
it, and at least one of those addresses is on the same subnet as the
|
||||
interface to which the query was sent, then return only the
|
||||
address(es) on that subnet. This allows for a server to have multiple
|
||||
address(es) on that subnet and return all the available addresses otherwise.
|
||||
This allows for a server to have multiple
|
||||
addresses in /etc/hosts corresponding to each of its interfaces, and
|
||||
hosts will get the correct address based on which network they are
|
||||
attached to. Currently this facility is limited to IPv4.
|
||||
@@ -345,8 +376,29 @@ forged answer to a DNS request for certain domain, before the correct answer can
|
||||
.B \-f, --filterwin2k
|
||||
Later versions of windows make periodic DNS requests which don't get sensible answers from
|
||||
the public DNS and can cause problems by triggering dial-on-demand links. This flag turns on an option
|
||||
to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the
|
||||
requested name has underscores, to catch LDAP requests.
|
||||
to filter such requests. The requests blocked are for records of type ANY
|
||||
where the requested name has underscores, to catch LDAP requests, and for
|
||||
\fBall\fP records of types SOA and SRV.
|
||||
.TP
|
||||
.B --filter-A
|
||||
Remove A records from answers. No IPv4 addresses will be returned.
|
||||
.TP
|
||||
.B --filter-AAAA
|
||||
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. 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.
|
||||
This option adds other record types to the cache. The RR-type can be given
|
||||
as a name such as TXT or MX or a decimal number. A single --cache-rr option
|
||||
can take a comma-separated list of RR-types and more than one --cache-rr option
|
||||
is allowed. Use --cache-rr=ANY to enable caching for all RR-types.
|
||||
.TP
|
||||
.B \-r, --resolv-file=<file>
|
||||
Read the IP addresses of the upstream nameservers from <file>, instead of
|
||||
@@ -435,8 +487,8 @@ Tells dnsmasq to never forward A or AAAA queries for plain names, without dots
|
||||
or domain parts, to upstream nameservers. If the name is not known
|
||||
from /etc/hosts or DHCP then a "not found" answer is returned.
|
||||
.TP
|
||||
.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>]][@<interface>][@<source-ip>[#<port>]]
|
||||
Specify IP address of upstream servers directly. Setting this flag does
|
||||
.B \-S, --local, --server=[/[<domain>]/[domain/]][<server>[#<port>]][@<interface>][@<source-ip>[#<port>]]
|
||||
Specify upstream servers directly. Setting this flag does
|
||||
not suppress reading of /etc/resolv.conf, use \fB--no-resolv\fP to do that. If one or more
|
||||
optional domains are given, that server is used only for those domains
|
||||
and they are queried only using the specified server. This is
|
||||
@@ -504,22 +556,27 @@ The query-port flag is ignored for any servers which have a
|
||||
source address specified but the port may be specified directly as
|
||||
part of the source address. Forcing queries to an interface is not
|
||||
implemented on all platforms supported by dnsmasq.
|
||||
|
||||
Upstream servers may be specified with a hostname rather than an IP address.
|
||||
In this case, dnsmasq will try to use the system resolver to get the IP address
|
||||
of a server during startup. If name resolution fails, starting dnsmasq fails, too.
|
||||
If the system's configuration is such that the system resolver sends DNS queries
|
||||
through the dnsmasq instance which is starting up then this will time-out and fail.
|
||||
.TP
|
||||
.B --rev-server=<ip-address>/<prefix-len>[,<ipaddr>][#<port>][@<interface>][@<source-ip>[#<port>]]
|
||||
.B --rev-server=<ip-address>[/<prefix-len>][,<server>][#<port>][@<interface>][@<source-ip>[#<port>]]
|
||||
This is functionally the same as
|
||||
.B --server,
|
||||
but provides some syntactic sugar to make specifying address-to-name queries easier. For example
|
||||
.B --rev-server=1.2.3.0/24,192.168.0.1
|
||||
is exactly equivalent to
|
||||
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
|
||||
Allowed prefix lengths are 1-32 (IPv4) and 1-128 (IPv6). If the prefix length is omitted, dnsmasq substitutes either 32 (IPv4) or 128 (IPv6).
|
||||
.TP
|
||||
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
|
||||
Specify an IP address to return for any host in the given domains.
|
||||
Queries in the domains are never forwarded and always replied to
|
||||
A (or AAAA) queries in the domains are never forwarded and always replied to
|
||||
with the specified IP address which may be IPv4 or IPv6. To give
|
||||
both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
|
||||
To include multiple IP addresses for a single query, use
|
||||
\fB--addn-hosts=<path>\fP instead.
|
||||
multiple addresses or both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
|
||||
Note that /etc/hosts and DHCP leases override this for individual
|
||||
names. A common use of this is to redirect the entire doubleclick.net
|
||||
domain to some friendly local web server to avoid banner ads. The
|
||||
@@ -537,6 +594,11 @@ address of 0.0.0.0 and its IPv6 equivalent of :: so
|
||||
its subdomains. This is partly syntactic sugar for \fB--address=/example.com/0.0.0.0\fP
|
||||
and \fB--address=/example.com/::\fP but is also more efficient than including both
|
||||
as separate configuration lines. Note that NULL addresses normally work in the same way as localhost, so beware that clients looking up these names are likely to end up talking to themselves.
|
||||
|
||||
Note that the behaviour for queries which don't match the specified address literal changed in version 2.86.
|
||||
Previous versions, configured with (eg) --address=/example.com/1.2.3.4 and then queried for a RR type other than
|
||||
A would return a NoData answer. From 2.86, the query is sent upstream. To restore the pre-2.86 behaviour,
|
||||
use the configuration --address=/example.com/1.2.3.4 --local=/example.com/
|
||||
.TP
|
||||
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
|
||||
Places the resolved IP addresses of queries for one or more domains in
|
||||
@@ -549,6 +611,15 @@ These IP sets must already exist. See
|
||||
.BR ipset (8)
|
||||
for more details.
|
||||
.TP
|
||||
.B --nftset=/<domain>[/<domain>...]/[(6|4)#[<family>#]<table>#<set>[,[(6|4)#[<family>#]<table>#<set>]...]
|
||||
Similar to the \fB--ipset\fP option, but accepts one or more nftables
|
||||
sets to add IP addresses into.
|
||||
These sets must already exist. See
|
||||
.BR nft (8)
|
||||
for more details. The family, table and set are passed directly to the nft. If the spec starts with 4# or 6# then
|
||||
only A or AAAA records respectively are added to the set. Since an nftset can hold only IPv4 or IPv6 addresses, this
|
||||
avoids errors being logged for addresses of the wrong type.
|
||||
.TP
|
||||
.B --connmark-allowlist-enable[=<mask>]
|
||||
Enables filtering of incoming DNS queries with associated Linux connection track marks
|
||||
according to individual allowlists configured via a series of \fB--connmark-allowlist\fP
|
||||
@@ -698,23 +769,22 @@ 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
|
||||
representing its type. The current types are: 0x0001 - DNS queries from clients 0x0002 DNS replies to clients 0x0004 - DNS queries to upstream 0x0008 - DNS replies from upstream 0x0010 - queries send upstream for DNSSEC validation 0x0020 - replies to queries for DNSSEC validation 0x0040 - replies to client queries which fail DNSSEC validation 0x0080 replies to queries for DNSSEC validation which fail validation.
|
||||
representing its type. The current types are: 0x0001 - DNS queries from clients, 0x0002 DNS replies to clients, 0x0004 - DNS queries to upstream, 0x0008 - DNS replies from upstream, 0x0010 - queries send upstream for DNSSEC validation, 0x0020 - replies to queries for DNSSEC validation, 0x0040 - replies to client queries which fail DNSSEC validation, 0x0080 replies to queries for DNSSEC validation which fail validation, 0x1000 - DHCPv4, 0x2000 - DHCPv6, 0x4000 - Router advertisement, 0x8000 - TFTP.
|
||||
.TP
|
||||
.B --add-mac[=base64|text]
|
||||
Add the MAC address of the requestor to DNS queries which are
|
||||
@@ -727,6 +797,9 @@ have security and privacy implications. The warning about caching
|
||||
given for \fB--add-subnet\fP applies to \fB--add-mac\fP too. An alternative encoding of the
|
||||
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
|
||||
.TP
|
||||
.B --strip-mac
|
||||
Remove any MAC address information already in downstream queries before forwarding upstream.
|
||||
.TP
|
||||
.B --add-cpe-id=<string>
|
||||
Add an arbitrary identifying string to DNS queries which are
|
||||
forwarded upstream.
|
||||
@@ -752,12 +825,18 @@ will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
|
||||
.B --add-subnet=1.2.3.4/24,1.2.3.4/24
|
||||
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
|
||||
.TP
|
||||
.B --umbrella[=deviceid:<deviceid>[,orgid:<orgid>]]
|
||||
.B --strip-subnet
|
||||
Remove any subnet address already present in a downstream query before forwarding it upstream. If --add-subnet is set this also
|
||||
ensures that any downstream-provided subnet is replaced by the one added by dnsmasq. Otherwise, dnsmasq will NOT replace an
|
||||
existing subnet in the query.
|
||||
.TP
|
||||
.B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]]
|
||||
Embeds the requestor's IP address in DNS queries forwarded upstream.
|
||||
If device id or organization id are specified, the information is
|
||||
If device id or, asset id or organization id are specified, the information is
|
||||
included in the forwarded queries and may be able to be used in
|
||||
filtering policies and reporting. The order of the deviceid and orgid
|
||||
attributes is irrelevant, but must be separated by a comma.
|
||||
filtering policies and reporting. The order of the id
|
||||
attributes is irrelevant, but they must be separated by a comma. Deviceid is
|
||||
a sixteen digit hexadecimal number, org and asset ids are decimal numbers.
|
||||
.TP
|
||||
.B \-c, --cache-size=<cachesize>
|
||||
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. Note: huge cache size impacts performance.
|
||||
@@ -767,6 +846,19 @@ Disable negative caching. Negative caching allows dnsmasq to remember
|
||||
"no such domain" answers from upstream nameservers and answer
|
||||
identical queries without forwarding them again.
|
||||
.TP
|
||||
.B --no-round-robin
|
||||
Dnsmasq normally permutes the order of A or AAAA records for the same
|
||||
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 --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
|
||||
of sometimes returning out-of-date data and less efficient cache utilisation, since old data cannot be flushed when its TTL expires, so the cache becomes
|
||||
mostly least-recently-used. To mitigate issues caused by massively outdated DNS replies, the maximum overaging of cached records can be specified in seconds
|
||||
(defaulting to not serve anything older than one day). Setting the TTL excess time to zero will serve stale cache data regardless how long it has expired.
|
||||
.TP
|
||||
.B \-0, --dns-forward-max=<queries>
|
||||
Set the maximum number of concurrent DNS queries. The default value is
|
||||
150, which should be fine for most setups. The only known situation
|
||||
@@ -839,6 +931,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
|
||||
@@ -1036,7 +1137,7 @@ is also included, as described in RFC-3775 section 7.3.
|
||||
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
|
||||
|
||||
.TP
|
||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][tag:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,tag:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||
Specify per host parameters for the DHCP server. This allows a machine
|
||||
with a particular hardware address to be always allocated the same
|
||||
hostname, IP address and lease time. A hostname specified like this
|
||||
@@ -1099,7 +1200,8 @@ given in a
|
||||
.B --dhcp-host
|
||||
option, but aliases are possible by using CNAMEs. (See
|
||||
.B --cname
|
||||
).
|
||||
). Note that /etc/hosts is NOT used when the DNS server side of dnsmasq
|
||||
is disabled by setting the DNS server port to zero.
|
||||
|
||||
More than one
|
||||
.B --dhcp-host
|
||||
@@ -1135,7 +1237,10 @@ ignore requests from unknown machines using
|
||||
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.
|
||||
|
||||
The tag:<tag> construct filters which dhcp-host directives are used. Tagged directives are used in preference to untagged ones.
|
||||
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
|
||||
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).
|
||||
|
||||
Ethernet addresses (but not client-ids) may have
|
||||
wildcard bytes, so for example
|
||||
@@ -1225,7 +1330,15 @@ and to set the time-server address to 192.168.0.4, do
|
||||
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".
|
||||
machine 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
|
||||
provides default values can be ommitted by defining the option with no data. These are
|
||||
netmask, broadcast, router, DNS server, domainname and hostname. Thus, for DHCPv4
|
||||
.B --dhcp-option = option:router
|
||||
will result in no router option being sent, rather than the default of the host on which dnsmasq is running. For DHCPv6, the same is true of the options DNS server and refresh time.
|
||||
|
||||
|
||||
Data types allowed are comma separated
|
||||
dotted-quad IPv4 addresses, []-wrapped IPv6 addresses, a decimal number, colon-separated hex digits
|
||||
@@ -1282,7 +1395,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:
|
||||
@@ -1301,6 +1414,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
|
||||
@@ -1309,18 +1426,20 @@ DHCP options. This make extra space available in the DHCP packet for
|
||||
options but can, rarely, confuse old or broken clients. This flag
|
||||
forces "simple and safe" behaviour to avoid problems in such a case.
|
||||
.TP
|
||||
.B --dhcp-relay=<local address>,<server address>[,<interface]
|
||||
.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
|
||||
addresses. A server address must be an IP literal address, not a
|
||||
domain name. In the case of DHCPv6, the server address may be the
|
||||
ALL_SERVERS multicast address, ff05::1:3. In this case the interface
|
||||
must be given, not be wildcard, and is used to direct the multicast to the
|
||||
correct interface to reach the DHCP server.
|
||||
domain name. If the server address is omitted, the request will be
|
||||
forwarded by broadcast (IPv4) or multicast (IPv6). In this case the interface
|
||||
must be given and not be wildcard. The server address may specify a non-standard
|
||||
port to relay to. If this is used then \fB--dhcp-proxy\fP should likely also be set,
|
||||
otherwise parts of the DHCP conversation which do not pass through the relay
|
||||
will be delivered to the wrong port.
|
||||
|
||||
Access control for DHCP clients has the same rules as for the DHCP
|
||||
server, see \fB--interface\fP, \fB--except-interface\fP, etc. The optional
|
||||
@@ -1340,6 +1459,11 @@ supported: the relay function will take precedence.
|
||||
|
||||
Both DHCPv4 and DHCPv6 relay is supported. It's not possible to relay
|
||||
DHCPv4 to a DHCPv6 server or vice-versa.
|
||||
|
||||
The DHCP relay function for IPv6 includes the ability to snoop
|
||||
prefix-delegation from relayed DHCP transactions. See
|
||||
.B --dhcp-script
|
||||
for details.
|
||||
.TP
|
||||
.B \-U, --dhcp-vendorclass=set:<tag>,[enterprise:<IANA-enterprise number>,]<vendor-class>
|
||||
Map from a vendor-class string to a tag. Most DHCP clients provide a
|
||||
@@ -1556,6 +1680,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
|
||||
@@ -1675,7 +1804,13 @@ If dnsmasq was compiled with HAVE_BROKEN_RTC, then
|
||||
the length of the lease (in seconds) is stored in
|
||||
DNSMASQ_LEASE_LENGTH, otherwise the time of lease expiry is stored in
|
||||
DNSMASQ_LEASE_EXPIRES. The number of seconds until lease expiry is
|
||||
always stored in DNSMASQ_TIME_REMAINING.
|
||||
always stored in DNSMASQ_TIME_REMAINING.
|
||||
|
||||
DNSMASQ_DATA_MISSING is set to "1" during "old" events for existing
|
||||
leases generated at startup to indicate that data not stored in the
|
||||
persistent lease database will not be present. This comprises everything
|
||||
other than IP address, hostname, MAC address, DUID, IAID and lease length
|
||||
or expiry time.
|
||||
|
||||
If a lease used to have a hostname, which is
|
||||
removed, an "old" event is generated with the new state of the lease,
|
||||
@@ -1697,6 +1832,11 @@ DNSMASQ_LOG_DHCP is set if
|
||||
.B --log-dhcp
|
||||
is in effect.
|
||||
|
||||
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
|
||||
|
||||
DNSMASQ_MUD_URL the Manufacturer Usage Description URL if provided by the client. (See RFC8520 for details.)
|
||||
|
||||
|
||||
For IPv4 only:
|
||||
|
||||
DNSMASQ_CLIENT_ID if the host provided a client-id.
|
||||
@@ -1706,8 +1846,6 @@ DHCP relay-agent added any of these options.
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
|
||||
|
||||
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
|
||||
|
||||
For IPv6 only:
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS_ID,
|
||||
@@ -1750,15 +1888,25 @@ receives a HUP signal, the script will be invoked for existing leases
|
||||
with an "old" event.
|
||||
|
||||
|
||||
There are four further actions which may appear as the first argument
|
||||
to the script, "init", "arp-add", "arp-del" and "tftp". More may be added in the future, so
|
||||
There are five further actions which may appear as the first argument
|
||||
to the script, "init", "arp-add", "arp-del", "relay-snoop" and "tftp".
|
||||
More may be added in the future, so
|
||||
scripts should be written to ignore unknown actions. "init" is
|
||||
described below in
|
||||
.B --leasefile-ro
|
||||
|
||||
The "tftp" action is invoked when a TFTP file transfer completes: the
|
||||
arguments are the file size in bytes, the address to which the file
|
||||
was sent, and the complete pathname of the file.
|
||||
|
||||
|
||||
The "relay-snoop" action is invoked when dnsmasq is configured as a DHCP
|
||||
relay for DHCPv6 and it relays a prefx delegation to a client. The arguments
|
||||
are the name of the interface where the client is conected, its (link-local)
|
||||
address on that interface and the delegated prefix. This information is
|
||||
sufficient to install routes to the delegated prefix of a router. See
|
||||
.B --dhcp-relay
|
||||
for more details on configuring DHCP relay.
|
||||
|
||||
The "arp-add" and "arp-del" actions are only called if enabled with
|
||||
.B --script-arp
|
||||
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
|
||||
@@ -1889,7 +2037,7 @@ is the address of the relay and the second, as before, specifies an extra subnet
|
||||
addresses may be allocated from.
|
||||
|
||||
.TP
|
||||
.B \-s, --domain=<domain>[,<address range>[,local]]
|
||||
.B \-s, --domain=<domain>[[,<address range>[,local]]|<interface>]
|
||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||
unconditionally (without the IP range) or for limited IP ranges. This has two effects;
|
||||
firstly it causes the DHCP server to return the domain to any hosts
|
||||
@@ -1923,7 +2071,11 @@ additional flag "local" may be supplied which has the effect of adding
|
||||
is identical to
|
||||
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
||||
.B --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
||||
The network size must be 8, 16 or 24 for this to be legal.
|
||||
|
||||
The address range can also be given as a network interface name, in which case
|
||||
all of the subnets currently assigned to the interface are used in matching the
|
||||
address. This allows hosts on different physical subnets to be given different
|
||||
domains in a way which updates automatically as the interface addresses change.
|
||||
.TP
|
||||
.B --dhcp-fqdn
|
||||
In the default mode, dnsmasq inserts the unqualified names of
|
||||
@@ -2096,6 +2248,41 @@ A special case of
|
||||
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
|
||||
in the configuration file included. Secondly, the file is re-read and the configuration
|
||||
therein is updated when dnsmasq receives SIGHUP.
|
||||
.TP
|
||||
.B \--conf-script=<file>[ <arg]
|
||||
Execute <file>, and treat what it emits to stdout as the contents of a configuration file.
|
||||
If the script exits with a non-zero exit code, dnsmasq treats this as a fatal error.
|
||||
The script can be passed arguments, space seperated from the filename and each other so, for instance
|
||||
.B --conf-dir="/etc/dnsmasq-uncompress-ads /share/ads-domains.gz"
|
||||
|
||||
with /etc/dnsmasq-uncompress-ads containing
|
||||
|
||||
set -e
|
||||
|
||||
zcat ${1} | sed -e "s:^:address=/:" -e "s:$:/:"
|
||||
|
||||
exit 0
|
||||
|
||||
and /share/ads-domains.gz containing a compressed
|
||||
list of ad server domains will save disk space with large ad-server blocklists.
|
||||
.TP
|
||||
.B --no-ident
|
||||
Do not respond to class CHAOS and type TXT in domain bind queries.
|
||||
|
||||
Without this option being set, the cache statistics are also available in the
|
||||
DNS as answers to queries of class CHAOS and type TXT in domain bind. The domain
|
||||
names are cachesize.bind, insertions.bind, evictions.bind, misses.bind,
|
||||
hits.bind, auth.bind and servers.bind unless disabled at compile-time. An
|
||||
example command to query this, using the
|
||||
.B dig
|
||||
utility would be
|
||||
|
||||
dig +short chaos txt cachesize.bind
|
||||
.TP
|
||||
.B --max-tcp-connections=<number>
|
||||
The maximum number of concurrent TCP connections. The application forks to
|
||||
handle each TCP request. The default maximum is 20.
|
||||
|
||||
.SH CONFIG FILE
|
||||
At startup, dnsmasq reads
|
||||
.I /etc/dnsmasq.conf,
|
||||
@@ -2140,20 +2327,11 @@ they expired in order to make room for new names and the total number
|
||||
of names that have been inserted into the cache. The number of cache hits and
|
||||
misses and the number of authoritative queries answered are also given. For each upstream
|
||||
server it gives the number of queries sent, and the number which
|
||||
resulted in an error. In
|
||||
resulted in an error. It also gives information on the number of forks for TCP connections. In
|
||||
.B --no-daemon
|
||||
mode or when full logging is enabled (\fB--log-queries\fP), a complete dump of the
|
||||
contents of the cache is made.
|
||||
|
||||
The cache statistics are also available in the DNS as answers to
|
||||
queries of class CHAOS and type TXT in domain bind. The domain names are cachesize.bind, insertions.bind, evictions.bind,
|
||||
misses.bind, hits.bind, auth.bind and servers.bind. An example command to query this, using the
|
||||
.B dig
|
||||
utility would be
|
||||
|
||||
dig +short chaos txt cachesize.bind
|
||||
|
||||
.PP
|
||||
When it receives SIGUSR2 and it is logging direct to a file (see
|
||||
.B --log-facility
|
||||
)
|
||||
@@ -2492,7 +2670,9 @@ file/directory, permissions).
|
||||
5 - Other miscellaneous problem.
|
||||
.PP
|
||||
11 or greater - a non zero return code was received from the
|
||||
lease-script process "init" call. The exit code from dnsmasq is the
|
||||
lease-script process "init" call or a
|
||||
.B \--conf-script
|
||||
file. The exit code from dnsmasq is the
|
||||
script's exit code with 10 added.
|
||||
|
||||
.SH LIMITS
|
||||
|
||||
1527
po/pt_BR.po
1527
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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)
|
||||
|
||||
68
src/auth.c
68
src/auth.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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;
|
||||
@@ -210,7 +210,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (local_query || in_zone(zone, intr->name, NULL))
|
||||
{
|
||||
found = 1;
|
||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
T_PTR, C_IN, "d", intr->name))
|
||||
@@ -234,7 +234,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid));
|
||||
log_query(flag | F_DHCP | F_REVERSE, name, &addr, record_source(crecp->uid), 0);
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
@@ -243,7 +243,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
||||
{
|
||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid), 0);
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL,
|
||||
@@ -257,7 +257,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
if (!found && is_rev_synth(flag, &addr, name) && (local_query || in_zone(zone, name, NULL)))
|
||||
{
|
||||
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL);
|
||||
log_query(F_CONFIG | F_REVERSE | flag, name, &addr, NULL, 0);
|
||||
found = 1;
|
||||
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
@@ -269,7 +269,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (found)
|
||||
nxdomain = 0;
|
||||
else
|
||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
|
||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -300,7 +300,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (rc == 2 && qtype == T_MX)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_MX, C_IN, "sd", rec->weight, rec->target))
|
||||
anscount++;
|
||||
@@ -315,7 +315,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (rc == 2 && qtype == T_SRV)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_SRV, C_IN, "sssd",
|
||||
rec->priority, rec->weight, rec->srvport, rec->target))
|
||||
@@ -349,7 +349,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (rc == 2 && txt->class == qtype)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, NULL, txt->class);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||
anscount++;
|
||||
@@ -363,7 +363,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (rc == 2 && qtype == T_TXT)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_TXT, C_IN, "t", txt->len, txt->txt))
|
||||
anscount++;
|
||||
@@ -377,7 +377,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (rc == 2 && qtype == T_NAPTR)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>", 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, T_NAPTR, C_IN, "sszzzd",
|
||||
na->order, na->pref, na->flags, na->services, na->regexp, na->replace))
|
||||
@@ -407,7 +407,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
continue;
|
||||
|
||||
found = 1;
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
qtype == T_A ? "4" : "6", &addrlist->addr))
|
||||
@@ -417,10 +417,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
if (!found && is_name_synthetic(flag, name, &addr) )
|
||||
{
|
||||
found = 1;
|
||||
nxdomain = 0;
|
||||
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL);
|
||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN, qtype == T_A ? "4" : "6", &addr))
|
||||
anscount++;
|
||||
@@ -433,8 +432,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (qtype == T_SOA)
|
||||
{
|
||||
auth = soa = 1; /* inhibits auth section */
|
||||
found = 1;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>");
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
|
||||
}
|
||||
else if (qtype == T_AXFR)
|
||||
{
|
||||
@@ -469,16 +467,14 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
soa = 1; /* inhibits auth section */
|
||||
ns = 1; /* ensure we include NS records! */
|
||||
axfr = 1;
|
||||
found = 1;
|
||||
axfroffset = nameoffset;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>");
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
|
||||
}
|
||||
else if (qtype == T_NS)
|
||||
{
|
||||
auth = 1;
|
||||
ns = 1; /* inhibits auth section */
|
||||
found = 1;
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>");
|
||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,9 +492,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
(local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||
{
|
||||
*cut = '.'; /* restore domain part */
|
||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
|
||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
||||
*cut = 0; /* remove domain part */
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||
@@ -518,8 +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));
|
||||
found = 1;
|
||||
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))
|
||||
@@ -566,7 +560,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
if (candidate)
|
||||
{
|
||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL, 0);
|
||||
strcpy(name, candidate->target);
|
||||
if (!strchr(name, '.'))
|
||||
{
|
||||
@@ -584,7 +578,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
else if (cache_find_non_terminal(name, now))
|
||||
nxdomain = 0;
|
||||
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -614,7 +608,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
if (subnet->prefixlen >= 16 )
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
a = a >> 8;
|
||||
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||
sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||
|
||||
}
|
||||
else
|
||||
@@ -627,7 +621,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
|
||||
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||
}
|
||||
p += sprintf(p, "ip6.arpa");
|
||||
sprintf(p, "ip6.arpa");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -874,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);
|
||||
@@ -892,14 +892,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
header->nscount = htons(0);
|
||||
addr.log.rcode = REFUSED;
|
||||
addr.log.ede = EDE_NOT_AUTH;
|
||||
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL);
|
||||
log_query(F_UPSTREAM | F_RCODE, "error", &addr, NULL, 0);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
131
src/blockdata.c
131
src/blockdata.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,7 +19,7 @@
|
||||
static struct blockdata *keyblock_free;
|
||||
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
||||
|
||||
static void blockdata_expand(int n)
|
||||
static void add_blocks(int n)
|
||||
{
|
||||
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
||||
|
||||
@@ -47,61 +47,72 @@ void blockdata_init(void)
|
||||
|
||||
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
blockdata_expand(daemon->cachesize);
|
||||
add_blocks(daemon->cachesize);
|
||||
}
|
||||
|
||||
void blockdata_report(void)
|
||||
{
|
||||
my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
|
||||
my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"),
|
||||
blockdata_count * sizeof(struct blockdata),
|
||||
blockdata_hwm * sizeof(struct blockdata),
|
||||
blockdata_alloced * sizeof(struct blockdata));
|
||||
}
|
||||
|
||||
static struct blockdata *new_block(void)
|
||||
{
|
||||
struct blockdata *block;
|
||||
|
||||
if (!keyblock_free)
|
||||
add_blocks(50);
|
||||
|
||||
if (keyblock_free)
|
||||
{
|
||||
block = keyblock_free;
|
||||
keyblock_free = block->next;
|
||||
blockdata_count++;
|
||||
if (blockdata_hwm < blockdata_count)
|
||||
blockdata_hwm = blockdata_count;
|
||||
block->next = NULL;
|
||||
return block;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
|
||||
{
|
||||
struct blockdata *block, *ret = NULL;
|
||||
struct blockdata **prev = &ret;
|
||||
size_t blen;
|
||||
|
||||
while (len > 0)
|
||||
do
|
||||
{
|
||||
if (!keyblock_free)
|
||||
blockdata_expand(50);
|
||||
|
||||
if (keyblock_free)
|
||||
{
|
||||
block = keyblock_free;
|
||||
keyblock_free = block->next;
|
||||
blockdata_count++;
|
||||
}
|
||||
else
|
||||
if (!(block = new_block()))
|
||||
{
|
||||
/* failed to alloc, free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (blockdata_hwm < blockdata_count)
|
||||
blockdata_hwm = blockdata_count;
|
||||
|
||||
if ((blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len) > 0)
|
||||
{
|
||||
if (data)
|
||||
{
|
||||
memcpy(block->key, data, blen);
|
||||
data += blen;
|
||||
}
|
||||
else if (!read_write(fd, block->key, blen, RW_READ))
|
||||
{
|
||||
/* failed read free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||
if (data)
|
||||
{
|
||||
memcpy(block->key, data, blen);
|
||||
data += blen;
|
||||
}
|
||||
else if (!read_write(fd, block->key, blen, 1))
|
||||
{
|
||||
/* failed read free partial chain */
|
||||
blockdata_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
len -= blen;
|
||||
*prev = block;
|
||||
prev = &block->next;
|
||||
block->next = NULL;
|
||||
}
|
||||
} while (len != 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -111,6 +122,58 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
|
||||
return blockdata_alloc_real(0, data, len);
|
||||
}
|
||||
|
||||
/* Add data to the end of the block.
|
||||
newlen is length of new data, NOT total new length.
|
||||
Use blockdata_alloc(NULL, 0) to make empty block to add to. */
|
||||
int blockdata_expand(struct blockdata *block, size_t oldlen, char *data, size_t newlen)
|
||||
{
|
||||
struct blockdata *b;
|
||||
|
||||
/* find size of current final block */
|
||||
for (b = block; oldlen > KEYBLOCK_LEN && b; b = b->next, oldlen -= KEYBLOCK_LEN);
|
||||
|
||||
/* chain to short for length, something is broken */
|
||||
if (oldlen > KEYBLOCK_LEN)
|
||||
{
|
||||
blockdata_free(block);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct blockdata *new;
|
||||
size_t blocksize = KEYBLOCK_LEN - oldlen;
|
||||
size_t size = (newlen <= blocksize) ? newlen : blocksize;
|
||||
|
||||
if (size != 0)
|
||||
{
|
||||
memcpy(&b->key[oldlen], data, size);
|
||||
data += size;
|
||||
newlen -= size;
|
||||
}
|
||||
|
||||
/* full blocks from now on. */
|
||||
oldlen = 0;
|
||||
|
||||
if (newlen == 0)
|
||||
break;
|
||||
|
||||
if ((new = new_block()))
|
||||
{
|
||||
b->next = new;
|
||||
b = new;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* failed to alloc, free partial chain */
|
||||
blockdata_free(block);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void blockdata_free(struct blockdata *blocks)
|
||||
{
|
||||
struct blockdata *tmp;
|
||||
@@ -130,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;
|
||||
@@ -165,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;
|
||||
}
|
||||
}
|
||||
|
||||
16
src/bpf.c
16
src/bpf.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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;
|
||||
@@ -147,7 +147,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||||
else
|
||||
broadcast.s_addr = 0;
|
||||
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||||
if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm))
|
||||
goto err;
|
||||
}
|
||||
else if (family == AF_INET6)
|
||||
@@ -212,8 +212,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
addr->s6_addr[3] = 0;
|
||||
}
|
||||
|
||||
if (!((*callback)(addr, prefix, scope_id, iface_index, flags,
|
||||
(int) preferred, (int)valid, parm)))
|
||||
if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags,
|
||||
(unsigned int) preferred, (unsigned int)valid, parm))
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
/* 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)))
|
||||
!callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
770
src/cache.c
770
src/cache.c
File diff suppressed because it is too large
Load Diff
39
src/config.h
39
src/config.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,15 +15,19 @@
|
||||
*/
|
||||
|
||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define MAX_PROCS 20 /* default max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define 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 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||
#define EDNS_PKTSZ 1232 /* default max EDNS.0 UDP packet from from /dnsflagday.net/2020 */
|
||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_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 TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
#define SMALL_PORT_RANGE 30 /* If DNS port range is smaller than this, use different allocation. */
|
||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
||||
@@ -58,6 +62,8 @@
|
||||
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
|
||||
#define LOOP_TEST_TYPE T_TXT
|
||||
#define DEFAULT_FAST_RETRY 1000 /* ms, default delay before fast retry */
|
||||
#define STALE_CACHE_EXPIRY 86400 /* 1 day in secs, default maximum expiry time for stale cache data */
|
||||
|
||||
/* compile-time options: uncomment below to enable or do eg.
|
||||
make COPTS=-DHAVE_BROKEN_RTC
|
||||
@@ -115,13 +121,14 @@ HAVE_IPSET
|
||||
define this to include the ability to selectively add resolved ip addresses
|
||||
to given ipsets.
|
||||
|
||||
HAVE_NFTSET
|
||||
define this to include the ability to selectively add resolved ip addresses
|
||||
to given nftables sets.
|
||||
|
||||
HAVE_AUTH
|
||||
define this to include the facility to act as an authoritative DNS
|
||||
server for one or more zones.
|
||||
|
||||
HAVE_CRYPTOHASH
|
||||
include just hash function from crypto library, but no DNSSEC.
|
||||
|
||||
HAVE_DNSSEC
|
||||
include DNSSEC validator.
|
||||
|
||||
@@ -190,9 +197,8 @@ RESOLVFILE
|
||||
/* #define HAVE_IDN */
|
||||
/* #define HAVE_LIBIDN2 */
|
||||
/* #define HAVE_CONNTRACK */
|
||||
/* #define HAVE_CRYPTOHASH */
|
||||
/* #define HAVE_DNSSEC */
|
||||
|
||||
/* #define HAVE_NFTSET */
|
||||
|
||||
/* Default locations for important system files. */
|
||||
|
||||
@@ -356,6 +362,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 */
|
||||
|
||||
@@ -420,14 +431,14 @@ static char *compile_opts =
|
||||
"no-"
|
||||
#endif
|
||||
"ipset "
|
||||
#ifndef HAVE_NFTSET
|
||||
"no-"
|
||||
#endif
|
||||
"nftset "
|
||||
#ifndef HAVE_AUTH
|
||||
"no-"
|
||||
#endif
|
||||
"auth "
|
||||
#if !defined(HAVE_CRYPTOHASH) && !defined(HAVE_DNSSEC)
|
||||
"no-"
|
||||
#endif
|
||||
"cryptohash "
|
||||
#ifndef HAVE_DNSSEC
|
||||
"no-"
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
||||
41
src/crypto.c
41
src/crypto.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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>
|
||||
@@ -309,14 +306,14 @@ static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_l
|
||||
mpz_init(y);
|
||||
}
|
||||
|
||||
mpz_import(x, 32 , 1, 1, 0, 0, p);
|
||||
mpz_import(y, 32 , 1, 1, 0, 0, p + 32);
|
||||
mpz_import(x, 32, -1, 1, 0, 0, p);
|
||||
mpz_import(y, 32, -1, 1, 0, 0, p + 32);
|
||||
|
||||
if (!ecc_point_set(gost_key, x, y))
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig);
|
||||
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig + 32);
|
||||
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig);
|
||||
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig + 32);
|
||||
|
||||
return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
|
||||
}
|
||||
@@ -390,7 +387,12 @@ static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key
|
||||
return dnsmasq_ecdsa_verify;
|
||||
|
||||
#if MIN_VERSION(3, 1)
|
||||
case 15: case 16:
|
||||
case 15:
|
||||
return dnsmasq_eddsa_verify;
|
||||
#endif
|
||||
|
||||
#if MIN_VERSION(3, 6)
|
||||
case 16:
|
||||
return dnsmasq_eddsa_verify;
|
||||
#endif
|
||||
}
|
||||
@@ -425,7 +427,9 @@ char *ds_digest_name(int digest)
|
||||
{
|
||||
case 1: return "sha1";
|
||||
case 2: return "sha256";
|
||||
case 3: return "gosthash94";
|
||||
#if MIN_VERSION(3, 6)
|
||||
case 3: return "gosthash94cp";
|
||||
#endif
|
||||
case 4: return "sha384";
|
||||
default: return NULL;
|
||||
}
|
||||
@@ -444,11 +448,17 @@ char *algo_digest_name(int algo)
|
||||
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
||||
case 8: return "sha256"; /* RSA/SHA-256 */
|
||||
case 10: return "sha512"; /* RSA/SHA-512 */
|
||||
case 12: return "gosthash94"; /* ECC-GOST */
|
||||
#if MIN_VERSION(3, 6)
|
||||
case 12: return "gosthash94cp"; /* ECC-GOST */
|
||||
#endif
|
||||
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
||||
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
||||
#if MIN_VERSION(3, 1)
|
||||
case 15: return "null_hash"; /* ED25519 */
|
||||
# if MIN_VERSION(3, 6)
|
||||
case 16: return "null_hash"; /* ED448 */
|
||||
# endif
|
||||
#endif
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@@ -463,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)
|
||||
{
|
||||
@@ -496,4 +503,4 @@ const struct nettle_hash *hash_find(char *name)
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
|
||||
#endif /* defined(HAVE_DNSSEC) */
|
||||
|
||||
317
src/dbus.c
317
src/dbus.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -52,6 +52,15 @@ const char* introspection_xml_template =
|
||||
" <method name=\"SetFilterWin2KOption\">\n"
|
||||
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFilterA\">\n"
|
||||
" <arg name=\"filter-a\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetFilterAAAA\">\n"
|
||||
" <arg name=\"filter-aaaa\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetLocaliseQueriesOption\">\n"
|
||||
" <arg name=\"localise-queries\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetBogusPrivOption\">\n"
|
||||
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
@@ -88,10 +97,16 @@ const char* introspection_xml_template =
|
||||
" <method name=\"GetMetrics\">\n"
|
||||
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"GetServerMetrics\">\n"
|
||||
" <arg name=\"metrics\" direction=\"out\" type=\"a{ss}\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"ClearMetrics\">\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
static char *introspection_xml = NULL;
|
||||
static int watches_modified = 0;
|
||||
|
||||
struct watch {
|
||||
DBusWatch *watch;
|
||||
@@ -113,14 +128,15 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
||||
w->watch = watch;
|
||||
w->next = daemon->watches;
|
||||
daemon->watches = w;
|
||||
watches_modified++;
|
||||
|
||||
w = data; /* no warning */
|
||||
(void)data; /* no warning */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
struct watch **up, *w, *tmp;
|
||||
struct watch **up, *w, *tmp;
|
||||
|
||||
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
|
||||
{
|
||||
@@ -129,21 +145,26 @@ static void remove_watch(DBusWatch *watch, void *data)
|
||||
{
|
||||
*up = tmp;
|
||||
free(w);
|
||||
watches_modified++;
|
||||
}
|
||||
else
|
||||
up = &(w->next);
|
||||
}
|
||||
|
||||
w = data; /* no warning */
|
||||
(void)data; /* no warning */
|
||||
}
|
||||
|
||||
static void dbus_read_servers(DBusMessage *message)
|
||||
static DBusMessage* dbus_read_servers(DBusMessage *message)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
union mysockaddr addr, source_addr;
|
||||
char *domain;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
{
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Failed to initialize dbus message iter");
|
||||
}
|
||||
|
||||
mark_servers(SERV_FROM_DBUS);
|
||||
|
||||
@@ -222,6 +243,7 @@ static void dbus_read_servers(DBusMessage *message)
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
cleanup_servers();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOOP
|
||||
@@ -279,6 +301,11 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
u16 flags = 0;
|
||||
char interface[IF_NAMESIZE];
|
||||
char *str_addr, *str_domain = NULL;
|
||||
struct server_details sdetails = { 0 };
|
||||
sdetails.addr = &addr;
|
||||
sdetails.source_addr = &source_addr;
|
||||
sdetails.interface = interface;
|
||||
sdetails.flags = &flags;
|
||||
|
||||
if (strings)
|
||||
{
|
||||
@@ -361,20 +388,6 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
strcpy(str_addr, str);
|
||||
}
|
||||
|
||||
/* parse the IP address */
|
||||
if ((addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, &flags)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 0.0.0.0 for server address == NULL, for Dbus */
|
||||
if (addr.in.sin_family == AF_INET &&
|
||||
addr.in.sin_addr.s_addr == 0)
|
||||
flags |= SERV_LITERAL_ADDRESS;
|
||||
|
||||
if (strings)
|
||||
{
|
||||
char *p;
|
||||
@@ -388,7 +401,31 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
else
|
||||
p = NULL;
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
||||
if (strings && strlen(str_addr) == 0)
|
||||
add_update_server(SERV_LITERAL_ADDRESS | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
||||
else
|
||||
{
|
||||
if ((addr_err = parse_server(str_addr, &sdetails)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
while (parse_server_next(&sdetails))
|
||||
{
|
||||
if ((addr_err = parse_server_addr(&sdetails)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
||||
}
|
||||
}
|
||||
} while ((str_domain = p));
|
||||
}
|
||||
else
|
||||
@@ -402,11 +439,40 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
|
||||
dbus_message_iter_get_basic(&string_iter, &str);
|
||||
dbus_message_iter_next (&string_iter);
|
||||
|
||||
if ((addr_err = parse_server(str_addr, &sdetails)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
|
||||
while (parse_server_next(&sdetails))
|
||||
{
|
||||
if ((addr_err = parse_server_addr(&sdetails)))
|
||||
{
|
||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s': %s",
|
||||
str, addr_err);
|
||||
break;
|
||||
}
|
||||
|
||||
/* 0.0.0.0 for server address == NULL, for Dbus */
|
||||
if (addr.in.sin_family == AF_INET &&
|
||||
addr.in.sin_addr.s_addr == 0)
|
||||
flags |= SERV_LITERAL_ADDRESS;
|
||||
else
|
||||
flags &= ~SERV_LITERAL_ADDRESS;
|
||||
|
||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
|
||||
}
|
||||
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
||||
}
|
||||
|
||||
|
||||
if (sdetails.orig_hostinfo)
|
||||
freeaddrinfo(sdetails.orig_hostinfo);
|
||||
|
||||
/* jump to next element in outer array */
|
||||
dbus_message_iter_next(&array_iter);
|
||||
}
|
||||
@@ -419,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
|
||||
@@ -545,6 +620,10 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
if (hw_len < 0)
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid HW address '%s'", hwaddr);
|
||||
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
@@ -632,6 +711,77 @@ static DBusMessage *dbus_get_metrics(DBusMessage* message)
|
||||
return reply;
|
||||
}
|
||||
|
||||
static void add_dict_entry(DBusMessageIter *container, const char *key, const char *val)
|
||||
{
|
||||
DBusMessageIter dict;
|
||||
|
||||
dbus_message_iter_open_container(container, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &val);
|
||||
dbus_message_iter_close_container(container, &dict);
|
||||
}
|
||||
|
||||
static void add_dict_int(DBusMessageIter *container, const char *key, const unsigned int val)
|
||||
{
|
||||
snprintf(daemon->namebuff, MAXDNAME, "%u", val);
|
||||
|
||||
add_dict_entry(container, key, daemon->namebuff);
|
||||
}
|
||||
|
||||
static DBusMessage *dbus_get_server_metrics(DBusMessage* message)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
DBusMessageIter server_array, dict_array, server_iter;
|
||||
struct server *serv;
|
||||
|
||||
dbus_message_iter_init_append(reply, &server_iter);
|
||||
dbus_message_iter_open_container(&server_iter, DBUS_TYPE_ARRAY, "a{ss}", &server_array);
|
||||
|
||||
/* sum counts from different records for same server */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
serv->flags &= ~SERV_MARK;
|
||||
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (!(serv->flags & SERV_MARK))
|
||||
{
|
||||
unsigned int port;
|
||||
unsigned int queries = 0, failed_queries = 0, nxdomain_replies = 0, retrys = 0;
|
||||
unsigned int sigma_latency = 0, count_latency = 0;
|
||||
|
||||
struct server *serv1;
|
||||
|
||||
for (serv1 = serv; serv1; serv1 = serv1->next)
|
||||
if (!(serv1->flags & SERV_MARK) && sockaddr_isequal(&serv->addr, &serv1->addr))
|
||||
{
|
||||
serv1->flags |= SERV_MARK;
|
||||
queries += serv1->queries;
|
||||
failed_queries += serv1->failed_queries;
|
||||
nxdomain_replies += serv1->nxdomain_replies;
|
||||
retrys += serv1->retrys;
|
||||
sigma_latency += serv1->query_latency;
|
||||
count_latency++;
|
||||
}
|
||||
|
||||
dbus_message_iter_open_container(&server_array, DBUS_TYPE_ARRAY, "{ss}", &dict_array);
|
||||
|
||||
port = prettyprint_addr(&serv->addr, daemon->namebuff);
|
||||
add_dict_entry(&dict_array, "address", daemon->namebuff);
|
||||
|
||||
add_dict_int(&dict_array, "port", port);
|
||||
add_dict_int(&dict_array, "queries", serv->queries);
|
||||
add_dict_int(&dict_array, "failed_queries", serv->failed_queries);
|
||||
add_dict_int(&dict_array, "nxdomain", serv->nxdomain_replies);
|
||||
add_dict_int(&dict_array, "retries", serv->retrys);
|
||||
add_dict_int(&dict_array, "latency", sigma_latency/count_latency);
|
||||
|
||||
dbus_message_iter_close_container(&server_array, &dict_array);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(&server_iter, &server_array);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
@@ -668,7 +818,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
#endif
|
||||
else if (strcmp(method, "SetServers") == 0)
|
||||
{
|
||||
dbus_read_servers(message);
|
||||
reply = dbus_read_servers(message);
|
||||
new_servers = 1;
|
||||
}
|
||||
else if (strcmp(method, "SetServersEx") == 0)
|
||||
@@ -685,6 +835,46 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
|
||||
}
|
||||
else if (strcmp(method, "SetFilterA") == 0)
|
||||
{
|
||||
static int done = 0;
|
||||
static struct rrlist list = { 0, NULL };
|
||||
dbus_bool_t enabled;
|
||||
|
||||
if (!(reply = dbus_get_bool(message, &enabled, "filter-A")))
|
||||
{
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
list.next = daemon->filter_rr;
|
||||
daemon->filter_rr = &list;
|
||||
}
|
||||
|
||||
list.rr = enabled ? T_A : 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "SetFilterAAAA") == 0)
|
||||
{
|
||||
static int done = 0;
|
||||
static struct rrlist list = { 0, NULL };
|
||||
dbus_bool_t enabled;
|
||||
|
||||
if (!(reply = dbus_get_bool(message, &enabled, "filter-AAAA")))
|
||||
{
|
||||
if (!done)
|
||||
{
|
||||
done = 1;
|
||||
list.next = daemon->filter_rr;
|
||||
daemon->filter_rr = &list;
|
||||
}
|
||||
|
||||
list.rr = enabled ? T_AAAA : 0;
|
||||
}
|
||||
}
|
||||
else if (strcmp(method, "SetLocaliseQueriesOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_LOCALISE, "localise-queries");
|
||||
}
|
||||
else if (strcmp(method, "SetBogusPrivOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||
@@ -703,6 +893,14 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
reply = dbus_get_metrics(message);
|
||||
}
|
||||
else if (strcmp(method, "GetServerMetrics") == 0)
|
||||
{
|
||||
reply = dbus_get_server_metrics(message);
|
||||
}
|
||||
else if (strcmp(method, "ClearMetrics") == 0)
|
||||
{
|
||||
clear_metrics();
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache = 1;
|
||||
else
|
||||
@@ -719,7 +917,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
if (clear_cache)
|
||||
clear_cache_and_reload(dnsmasq_time());
|
||||
|
||||
method = user_data; /* no warning */
|
||||
(void)user_data; /* no warning */
|
||||
|
||||
/* If no reply or no error, return nothing */
|
||||
if (!reply)
|
||||
@@ -745,8 +943,11 @@ char *dbus_init(void)
|
||||
|
||||
dbus_error_init (&dbus_error);
|
||||
if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
|
||||
return NULL;
|
||||
|
||||
{
|
||||
dbus_error_free(&dbus_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(connection, FALSE);
|
||||
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
||||
NULL, NULL, NULL);
|
||||
@@ -780,41 +981,53 @@ void set_dbus_listeners(void)
|
||||
{
|
||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
int poll_flags = POLLERR;
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
poll_listen(fd, POLLIN);
|
||||
|
||||
poll_flags |= POLLIN;
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
poll_listen(fd, POLLOUT);
|
||||
poll_flags |= POLLOUT;
|
||||
|
||||
poll_listen(fd, POLLERR);
|
||||
poll_listen(fd, poll_flags);
|
||||
}
|
||||
}
|
||||
|
||||
void check_dbus_listeners()
|
||||
static int check_dbus_watches()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
struct watch *w;
|
||||
|
||||
watches_modified = 0;
|
||||
for (w = daemon->watches; w; w = w->next)
|
||||
if (dbus_watch_get_enabled(w->watch))
|
||||
{
|
||||
unsigned int flags = 0;
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
if (poll_check(fd, POLLIN))
|
||||
int poll_flags = poll_check(fd, POLLIN|POLLOUT|POLLERR);
|
||||
|
||||
if ((poll_flags & POLLIN) != 0)
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
|
||||
if (poll_check(fd, POLLOUT))
|
||||
if ((poll_flags & POLLOUT) != 0)
|
||||
flags |= DBUS_WATCH_WRITABLE;
|
||||
|
||||
if (poll_check(fd, POLLERR))
|
||||
if ((poll_flags & POLLERR) != 0)
|
||||
flags |= DBUS_WATCH_ERROR;
|
||||
|
||||
if (flags != 0)
|
||||
dbus_watch_handle(w->watch, flags);
|
||||
{
|
||||
dbus_watch_handle(w->watch, flags);
|
||||
if (watches_modified)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void check_dbus_listeners()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
|
||||
while (!check_dbus_watches()) ;
|
||||
|
||||
if (connection)
|
||||
{
|
||||
dbus_connection_ref (connection);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -88,7 +88,7 @@ int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool)
|
||||
for (; check; check = check->next)
|
||||
{
|
||||
const int check_len = strlen(check->net);
|
||||
const int is_wc = (check->net[check_len - 1] == '*');
|
||||
const int is_wc = (check_len > 0 && check->net[check_len - 1] == '*');
|
||||
|
||||
/* '#' for not is for backwards compat. */
|
||||
if (check->net[0] != '!' && check->net[0] != '#')
|
||||
@@ -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)
|
||||
@@ -553,11 +575,11 @@ char *whichdevice(void)
|
||||
return NULL;
|
||||
|
||||
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
|
||||
if (if_tmp->name && (!if_tmp->used || strchr(if_tmp->name, '*')))
|
||||
if (if_tmp->name && (!(if_tmp->flags & INAME_USED) || strchr(if_tmp->name, '*')))
|
||||
return NULL;
|
||||
|
||||
for (found = NULL, iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->dhcp_ok)
|
||||
if (iface->dhcp4_ok || iface->dhcp6_ok)
|
||||
{
|
||||
if (!found)
|
||||
found = iface;
|
||||
@@ -566,12 +588,16 @@ char *whichdevice(void)
|
||||
}
|
||||
|
||||
if (found)
|
||||
return found->name;
|
||||
|
||||
{
|
||||
char *ret = safe_malloc(strlen(found->name)+1);
|
||||
strcpy(ret, found->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bindtodevice(char *device, int fd)
|
||||
static int bindtodevice(char *device, int fd)
|
||||
{
|
||||
size_t len = strlen(device)+1;
|
||||
if (len > IFNAMSIZ)
|
||||
@@ -579,7 +605,33 @@ void bindtodevice(char *device, int fd)
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bind_dhcp_devices(char *bound_device)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (bound_device)
|
||||
{
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (!daemon->relay4)
|
||||
ret |= bindtodevice(bound_device, daemon->dhcpfd);
|
||||
|
||||
if (daemon->enable_pxe && daemon->pxefd != -1)
|
||||
ret |= bindtodevice(bound_device, daemon->pxefd);
|
||||
}
|
||||
|
||||
#if defined(HAVE_DHCP6)
|
||||
if (daemon->doing_dhcp6 && !daemon->relay6)
|
||||
ret |= bindtodevice(bound_device, daemon->dhcp6fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -655,6 +707,7 @@ static const struct opttab_t {
|
||||
{ "client-machine-id", 97, 0 },
|
||||
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */
|
||||
{ "subnet-select", 118, OT_INTERNAL },
|
||||
{ "domain-search", 119, OT_RFC1035_NAME },
|
||||
{ "sip-server", 120, 0 },
|
||||
@@ -691,6 +744,8 @@ static const struct opttab_t opttab6[] = {
|
||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||
{ "information-refresh-time", 32, OT_TIME },
|
||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||
{ "posix-timezone", 41, OT_NAME }, /* RFC 4833, Sec. 3 */
|
||||
{ "tzdb-timezone", 42, OT_NAME }, /* RFC 4833, Sec. 3 */
|
||||
{ "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ },
|
||||
{ "bootfile-url", 59, OT_NAME },
|
||||
{ "bootfile-param", 60, OT_CSTRING },
|
||||
@@ -805,7 +860,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
||||
for (i = 0, j = 0; i < opt_len && j < buf_len ; i++)
|
||||
{
|
||||
char c = val[i];
|
||||
if (isprint((int)c))
|
||||
if (isprint((unsigned char)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
@@ -819,7 +874,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
||||
for (k = i + 1; k < opt_len && k < l && j < buf_len ; k++)
|
||||
{
|
||||
char c = val[k];
|
||||
if (isprint((int)c))
|
||||
if (isprint((unsigned char)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
i = l;
|
||||
@@ -840,7 +895,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
||||
for (k = 0; k < len && j < buf_len; k++)
|
||||
{
|
||||
char c = *p++;
|
||||
if (isprint((int)c))
|
||||
if (isprint((unsigned char)c))
|
||||
buf[j++] = c;
|
||||
}
|
||||
i += len +2;
|
||||
@@ -985,11 +1040,34 @@ void log_context(int family, struct dhcp_context *context)
|
||||
|
||||
void log_relay(int family, struct dhcp_relay *relay)
|
||||
{
|
||||
int broadcast = relay->server.addr4.s_addr == 0;
|
||||
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
|
||||
if (family == AF_INET && relay->port != DHCP_SERVER_PORT)
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
struct in6_addr multicast;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
|
||||
|
||||
if (family == AF_INET6)
|
||||
{
|
||||
broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast);
|
||||
if (relay->port != DHCPV6_SERVER_PORT)
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (relay->interface)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||
{
|
||||
if (broadcast)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s via %s"), daemon->addrbuff, relay->interface);
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||
}
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -64,6 +64,7 @@
|
||||
#define OPTION_SIP_SERVER 120
|
||||
#define OPTION_VENDOR_IDENT 124
|
||||
#define OPTION_VENDOR_IDENT_OPT 125
|
||||
#define OPTION_MUD_URL_V4 161
|
||||
#define OPTION_END 255
|
||||
|
||||
#define SUBOPT_CIRCUIT_ID 1
|
||||
|
||||
200
src/dhcp.c
200
src/dhcp.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
struct iface_param {
|
||||
struct dhcp_context *current;
|
||||
struct dhcp_relay *relay;
|
||||
struct in_addr relay_local;
|
||||
int ind;
|
||||
};
|
||||
|
||||
@@ -34,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(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index);
|
||||
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)
|
||||
@@ -177,11 +175,15 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
if ((sz = recv_dhcp_packet(fd, &msg)) == -1 ||
|
||||
(sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))))
|
||||
return;
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, fd);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
|
||||
recvtime = tv.tv_sec;
|
||||
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
@@ -295,19 +297,14 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
}
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
if (tmp->name && (tmp->flags & INAME_4) && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
/* unlinked contexts/relays are marked by context->current == context */
|
||||
for (context = daemon->dhcp; context; context = context->next)
|
||||
context->current = context;
|
||||
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
relay->current = relay;
|
||||
|
||||
parm.current = NULL;
|
||||
parm.relay = NULL;
|
||||
parm.relay_local.s_addr = 0;
|
||||
parm.ind = iface_index;
|
||||
|
||||
if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
||||
@@ -320,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;
|
||||
|
||||
@@ -329,15 +326,12 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
there is more than one address on the interface in the same subnet */
|
||||
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
|
||||
}
|
||||
|
||||
if (!iface_enumerate(AF_INET, &parm, complete_context))
|
||||
return;
|
||||
|
||||
/* We're relaying this request */
|
||||
if (parm.relay_local.s_addr != 0 &&
|
||||
relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
|
||||
|
||||
if (!iface_enumerate(AF_INET, &parm, (callback_t){.af_inet=complete_context}))
|
||||
return;
|
||||
|
||||
relay_upstream4(iface_index, mess, (size_t)sz);
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->dhcp)
|
||||
return;
|
||||
@@ -397,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;
|
||||
@@ -455,6 +453,17 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
if (ntohs(mess->flags) & 0x8000)
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
else
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
|
||||
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
|
||||
(union mysockaddr *)&dest, fd);
|
||||
#endif
|
||||
|
||||
send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
|
||||
return;
|
||||
}
|
||||
@@ -463,6 +472,11 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
|
||||
(union mysockaddr *)&dest, fd);
|
||||
#endif
|
||||
|
||||
while(retry_send(sendmsg(fd, &msg, 0)));
|
||||
|
||||
@@ -613,14 +627,9 @@ static int complete_context(struct in_addr local, int if_index, char *label,
|
||||
}
|
||||
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
if (if_index == param->ind && relay->local.addr4.s_addr == local.s_addr && relay->current == relay &&
|
||||
(param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
|
||||
{
|
||||
relay->current = param->relay;
|
||||
param->relay = relay;
|
||||
param->relay_local = local;
|
||||
}
|
||||
|
||||
if (relay->local.addr4.s_addr == local.s_addr)
|
||||
relay->iface_index = if_index;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -904,14 +913,14 @@ void dhcp_read_ethers(void)
|
||||
|
||||
lineno++;
|
||||
|
||||
while (strlen(buff) > 0 && isspace((int)buff[strlen(buff)-1]))
|
||||
while (strlen(buff) > 0 && isspace((unsigned char)buff[strlen(buff)-1]))
|
||||
buff[strlen(buff)-1] = 0;
|
||||
|
||||
if ((*buff == '#') || (*buff == '+') || (*buff == 0))
|
||||
continue;
|
||||
|
||||
for (ip = buff; *ip && !isspace((int)*ip); ip++);
|
||||
for(; *ip && isspace((int)*ip); ip++)
|
||||
for (ip = buff; *ip && !isspace((unsigned char)*ip); ip++);
|
||||
for(; *ip && isspace((unsigned char)*ip); ip++)
|
||||
*ip = 0;
|
||||
if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
|
||||
{
|
||||
@@ -1061,55 +1070,102 @@ char *host_from_dns(struct in_addr addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
|
||||
static void relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
|
||||
{
|
||||
/* ->local is same value for all relays on ->current chain */
|
||||
union all_addr from;
|
||||
|
||||
struct in_addr giaddr = mess->giaddr;
|
||||
u8 hops = mess->hops;
|
||||
struct dhcp_relay *relay;
|
||||
|
||||
if (mess->op != BOOTREQUEST)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr4 = relay->local.addr4;
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
break;
|
||||
|
||||
/* No relay config. */
|
||||
if (!relay)
|
||||
return;
|
||||
|
||||
/* already gatewayed ? */
|
||||
if (mess->giaddr.s_addr)
|
||||
{
|
||||
/* if so check if by us, to stomp on loops. */
|
||||
if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* plug in our address */
|
||||
mess->giaddr.s_addr = relay->local.addr4.s_addr;
|
||||
}
|
||||
for (; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
{
|
||||
union mysockaddr to;
|
||||
union all_addr from;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
return 1;
|
||||
mess->hops = hops;
|
||||
mess->giaddr = giaddr;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
continue;
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr4 = relay->local.addr4;
|
||||
|
||||
for (; relay; relay = relay->current)
|
||||
{
|
||||
union mysockaddr to;
|
||||
|
||||
to.sa.sa_family = AF_INET;
|
||||
to.in.sin_addr = relay->server.addr4;
|
||||
to.in.sin_port = htons(daemon->dhcp_server_port);
|
||||
|
||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
/* already gatewayed ? */
|
||||
if (giaddr.s_addr)
|
||||
{
|
||||
/* if so check if by us, to stomp on loops. */
|
||||
if (giaddr.s_addr == relay->local.addr4.s_addr)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* plug in our address */
|
||||
mess->giaddr.s_addr = relay->local.addr4.s_addr;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (relay->interface)
|
||||
safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE);
|
||||
|
||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||
ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface);
|
||||
continue;
|
||||
}
|
||||
|
||||
to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
{
|
||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||
union mysockaddr fromsock;
|
||||
fromsock.in.sin_port = htons(daemon->dhcp_server_port);
|
||||
fromsock.in.sin_addr = from.addr4;
|
||||
fromsock.sa.sa_family = AF_INET;
|
||||
|
||||
dump_packet_udp(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, -1);
|
||||
}
|
||||
|
||||
/* Save this for replies */
|
||||
relay->iface_index = iface_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
if (relay->server.addr4.s_addr == 0)
|
||||
snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface);
|
||||
else
|
||||
inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
/* restore in case of a local reply. */
|
||||
mess->giaddr = giaddr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -55,12 +55,15 @@
|
||||
#define OPTION6_RECONF_ACCEPT 20
|
||||
#define OPTION6_DNS_SERVER 23
|
||||
#define OPTION6_DOMAIN_SEARCH 24
|
||||
#define OPTION6_IA_PD 25
|
||||
#define OPTION6_IAPREFIX 26
|
||||
#define OPTION6_REFRESH_TIME 32
|
||||
#define OPTION6_REMOTE_ID 37
|
||||
#define OPTION6_SUBSCRIBER_ID 38
|
||||
#define OPTION6_FQDN 39
|
||||
#define OPTION6_NTP_SERVER 56
|
||||
#define OPTION6_CLIENT_MAC 79
|
||||
#define OPTION6_MUD_URL 112
|
||||
|
||||
#define NTP_SUBOPTION_SRV_ADDR 1
|
||||
#define NTP_SUBOPTION_MC_ADDR 2
|
||||
|
||||
135
src/dhcp6.c
135
src/dhcp6.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
struct iface_param {
|
||||
struct dhcp_context *current;
|
||||
struct dhcp_relay *relay;
|
||||
struct in6_addr fallback, relay_local, ll_addr, ula_addr;
|
||||
struct in6_addr fallback, ll_addr, ula_addr;
|
||||
int ind, addr_match;
|
||||
};
|
||||
|
||||
@@ -90,11 +89,10 @@ void dhcp6_init(void)
|
||||
void dhcp6_packet(time_t now)
|
||||
{
|
||||
struct dhcp_context *context;
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param parm;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
int if_index = 0;
|
||||
uint32_t if_index = 0;
|
||||
union {
|
||||
struct cmsghdr align; /* this ensures alignment */
|
||||
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||
@@ -105,7 +103,8 @@ void dhcp6_packet(time_t now)
|
||||
struct iname *tmp;
|
||||
unsigned short port;
|
||||
struct in6_addr dst_addr;
|
||||
|
||||
struct in6_addr all_servers;
|
||||
|
||||
memset(&dst_addr, 0, sizeof(dst_addr));
|
||||
|
||||
msg.msg_control = control_u.control6;
|
||||
@@ -134,10 +133,42 @@ void dhcp6_packet(time_t now)
|
||||
|
||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* This works around a possible Linux kernel bug when using interfaces
|
||||
enslaved to a VRF. The scope_id in the source address gets set
|
||||
to the index of the VRF interface, not the slave. Fortunately,
|
||||
the interface index returned by packetinfo is correct so we use
|
||||
that instead. Log this once, so if it triggers in other circumstances
|
||||
we've not anticipated and breaks things, we get some clues. */
|
||||
if (from.sin6_scope_id != if_index)
|
||||
{
|
||||
from.sin6_port = htons(port);
|
||||
static int logged = 0;
|
||||
|
||||
if (!logged)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING,
|
||||
_("Working around kernel bug: faulty source address scope for VRF slave %s"),
|
||||
ifr.ifr_name);
|
||||
logged = 1;
|
||||
}
|
||||
|
||||
from.sin6_scope_id = if_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
if (relay_reply6(&from, sz, ifr.ifr_name))
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
|
||||
(union mysockaddr *)&from, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||
sizeof(from))));
|
||||
@@ -145,24 +176,23 @@ void dhcp6_packet(time_t now)
|
||||
else
|
||||
{
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
parm.current = NULL;
|
||||
parm.relay = NULL;
|
||||
memset(&parm.relay_local, 0, IN6ADDRSZ);
|
||||
parm.ind = if_index;
|
||||
parm.addr_match = 0;
|
||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
||||
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
||||
|
||||
|
||||
/* If the interface on which the DHCPv6 request was received is
|
||||
an alias of some other interface (as specified by the
|
||||
--bridge-interface option), change parm.ind so that we look
|
||||
@@ -200,13 +230,25 @@ void dhcp6_packet(time_t now)
|
||||
context->current = context;
|
||||
memset(&context->local6, 0, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
relay->current = relay;
|
||||
|
||||
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
return;
|
||||
|
||||
|
||||
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=complete_context6}))
|
||||
return;
|
||||
|
||||
/* Check for a relay again after iface_enumerate/complete_context has had
|
||||
chance to fill in relay->iface_index fields. This handles first time through
|
||||
and any changes in interface config. */
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
return;
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
|
||||
@@ -218,23 +260,10 @@ void dhcp6_packet(time_t now)
|
||||
return;
|
||||
}
|
||||
|
||||
if (parm.relay)
|
||||
{
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
struct in6_addr all_servers;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
|
||||
return;
|
||||
}
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->doing_dhcp6)
|
||||
return;
|
||||
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
@@ -247,11 +276,16 @@ void dhcp6_packet(time_t now)
|
||||
if (port != 0)
|
||||
{
|
||||
from.sin6_port = htons(port);
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||
sizeof(from))));
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
|
||||
NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from))));
|
||||
}
|
||||
|
||||
|
||||
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file()
|
||||
may trigger sending an RA packet, which overwrites our buffer. */
|
||||
lease_update_file(now);
|
||||
@@ -292,7 +326,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
|
||||
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
|
||||
break;
|
||||
|
||||
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
|
||||
while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr))));
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 100000000; /* 100ms */
|
||||
@@ -312,6 +346,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param *param = vparam;
|
||||
struct iname *tmp;
|
||||
int match = !daemon->if_addrs;
|
||||
|
||||
(void)scope; /* warning */
|
||||
|
||||
@@ -333,7 +368,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
||||
param->addr_match = 1;
|
||||
match = param->addr_match = 1;
|
||||
|
||||
/* Determine a globally address on the arrival interface, even
|
||||
if we have no matching dhcp-context, because we're only
|
||||
@@ -405,16 +440,12 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local)))
|
||||
{
|
||||
relay->current = param->relay;
|
||||
param->relay = relay;
|
||||
param->relay_local = *local;
|
||||
}
|
||||
|
||||
|
||||
if (match)
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6))
|
||||
relay->iface_index = if_index;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -586,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);
|
||||
@@ -636,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;
|
||||
@@ -770,7 +801,7 @@ void dhcp_construct_contexts(time_t now)
|
||||
if (context->flags & CONTEXT_CONSTRUCTED)
|
||||
context->flags |= CONTEXT_GC;
|
||||
|
||||
iface_enumerate(AF_INET6, ¶m, construct_worker);
|
||||
iface_enumerate(AF_INET6, ¶m, (callback_t){.af_inet6=construct_worker});
|
||||
|
||||
for (up = &daemon->dhcp6, context = daemon->dhcp6; context; context = tmp)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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))
|
||||
|
||||
872
src/dnsmasq.c
872
src/dnsmasq.c
File diff suppressed because it is too large
Load Diff
328
src/dnsmasq.h
328
src/dnsmasq.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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-2021 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (c) 2000-2024 Simon Kelley"
|
||||
|
||||
/* We do defines that influence behavior of stdio.h, so complain
|
||||
if included too early. */
|
||||
@@ -133,6 +133,7 @@ typedef unsigned long long u64;
|
||||
#include <sys/uio.h>
|
||||
#include <syslog.h>
|
||||
#include <dirent.h>
|
||||
#include <netdb.h>
|
||||
#ifndef HAVE_LINUX_NETWORK
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
@@ -154,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
|
||||
|
||||
@@ -275,7 +272,14 @@ struct event_desc {
|
||||
#define OPT_UMBRELLA_DEVID 64
|
||||
#define OPT_CMARK_ALST_EN 65
|
||||
#define OPT_QUIET_TFTP 66
|
||||
#define OPT_LAST 67
|
||||
#define OPT_STRIP_ECS 67
|
||||
#define OPT_STRIP_MAC 68
|
||||
#define OPT_NORR 69
|
||||
#define OPT_NO_IDENT 70
|
||||
#define OPT_CACHE_RR 71
|
||||
#define OPT_LOCALHOST_SERVICE 72
|
||||
#define OPT_LOG_PROTO 73
|
||||
#define OPT_LAST 74
|
||||
|
||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||
@@ -318,17 +322,28 @@ union all_addr {
|
||||
unsigned char algo;
|
||||
unsigned char digest;
|
||||
} ds;
|
||||
struct {
|
||||
struct blockdata *target;
|
||||
unsigned short targetlen, srvport, priority, weight;
|
||||
} srv;
|
||||
/* for log_query */
|
||||
struct {
|
||||
unsigned short keytag, algo, digest, rcode;
|
||||
int ede;
|
||||
} log;
|
||||
/* for arbitrary RR record stored in block */
|
||||
struct {
|
||||
unsigned short rrtype;
|
||||
unsigned short datalen;
|
||||
struct blockdata *rrdata;
|
||||
} rrblock;
|
||||
/* for arbitrary RR record small enough to go in addr.
|
||||
NOTE: rrblock and rrdata are discriminated by the F_KEYTAG bit
|
||||
in the cache flags. */
|
||||
struct datablock {
|
||||
unsigned short rrtype;
|
||||
unsigned char datalen; /* also length of SOA in negative records. */
|
||||
char data[1];
|
||||
} rrdata;
|
||||
};
|
||||
|
||||
#define RR_IMDATALEN (sizeof(union all_addr) - offsetof(struct datablock, data))
|
||||
|
||||
struct bogus_addr {
|
||||
int is6, prefix;
|
||||
@@ -438,6 +453,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 */
|
||||
@@ -505,7 +525,8 @@ struct crec {
|
||||
#define F_NOEXTRA (1u<<27)
|
||||
#define F_DOMAINSRV (1u<<28)
|
||||
#define F_RCODE (1u<<29)
|
||||
#define F_SRV (1u<<30)
|
||||
#define F_RR (1u<<30)
|
||||
#define F_STALE (1u<<31)
|
||||
|
||||
#define UID_NONE 0
|
||||
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||
@@ -530,23 +551,23 @@ union mysockaddr {
|
||||
|
||||
|
||||
/* The actual values here matter, since we sort on them to get records in the order
|
||||
IPv6 addr, IPv4 addr, all zero return, no-data return, send upstream. */
|
||||
#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next three flags */
|
||||
#define SERV_ALL_ZEROS 2 /* return all zeros for A and AAAA */
|
||||
#define SERV_4ADDR 4 /* addr is IPv4 */
|
||||
#define SERV_6ADDR 8 /* addr is IPv6 */
|
||||
#define SERV_HAS_SOURCE 16 /* source address defined */
|
||||
#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */
|
||||
#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */
|
||||
#define SERV_FROM_DBUS 128 /* 1 if source is DBus */
|
||||
#define SERV_MARK 256 /* for mark-and-delete and log code */
|
||||
#define SERV_WILDCARD 512 /* domain has leading '*' */
|
||||
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
||||
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
||||
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
||||
#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */
|
||||
#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */
|
||||
IPv6 addr, IPv4 addr, all zero return, resolvconf servers, upstream server, no-data return */
|
||||
#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next four flags */
|
||||
#define SERV_USE_RESOLV 2 /* forward this domain in the normal way */
|
||||
#define SERV_ALL_ZEROS 4 /* return all zeros for A and AAAA */
|
||||
#define SERV_4ADDR 8 /* addr is IPv4 */
|
||||
#define SERV_6ADDR 16 /* addr is IPv6 */
|
||||
#define SERV_HAS_SOURCE 32 /* source address defined */
|
||||
#define SERV_FOR_NODOTS 64 /* server for names with no domain part only */
|
||||
#define SERV_WARNED_RECURSIVE 128 /* avoid warning spam */
|
||||
#define SERV_FROM_DBUS 256 /* 1 if source is DBus */
|
||||
#define SERV_MARK 512 /* for mark-and-delete and log code */
|
||||
#define SERV_WILDCARD 1024 /* domain has leading '*' */
|
||||
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
||||
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
||||
#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */
|
||||
#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */
|
||||
|
||||
struct serverfd {
|
||||
int fd;
|
||||
@@ -578,9 +599,9 @@ 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;
|
||||
unsigned int queries, failed_queries;
|
||||
int tcpfd;
|
||||
unsigned int queries, failed_queries, nxdomain_replies, retrys;
|
||||
unsigned int query_latency, mma_latency;
|
||||
time_t forwardtime;
|
||||
int forwardcount;
|
||||
#ifdef HAVE_LOOP
|
||||
@@ -609,6 +630,11 @@ struct serv_local {
|
||||
struct server *next;
|
||||
};
|
||||
|
||||
struct rebind_domain {
|
||||
char *domain;
|
||||
struct rebind_domain *next;
|
||||
};
|
||||
|
||||
struct ipsets {
|
||||
char **sets;
|
||||
char *domain;
|
||||
@@ -624,7 +650,8 @@ struct allowlist {
|
||||
struct irec {
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* only valid for IPv4 */
|
||||
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
|
||||
int tftp_ok, dhcp4_ok, dhcp6_ok, mtu, done, warned, dad;
|
||||
int dns_auth, index, multicast_done, found, label;
|
||||
char *name;
|
||||
struct irec *next;
|
||||
};
|
||||
@@ -640,10 +667,19 @@ struct listener {
|
||||
struct iname {
|
||||
char *name;
|
||||
union mysockaddr addr;
|
||||
int used;
|
||||
int flags;
|
||||
struct iname *next;
|
||||
};
|
||||
|
||||
#define INAME_USED 1
|
||||
#define INAME_4 2
|
||||
#define INAME_6 4
|
||||
|
||||
struct rrlist {
|
||||
unsigned short rr;
|
||||
struct rrlist *next;
|
||||
};
|
||||
|
||||
/* subnet parameters from command line */
|
||||
struct mysubnet {
|
||||
union mysockaddr addr;
|
||||
@@ -656,6 +692,7 @@ struct resolvc {
|
||||
struct resolvc *next;
|
||||
int is_default, logged;
|
||||
time_t mtime;
|
||||
ino_t ino;
|
||||
char *name;
|
||||
#ifdef HAVE_INOTIFY
|
||||
int wd; /* inotify watch descriptor */
|
||||
@@ -674,21 +711,32 @@ struct hostsfile {
|
||||
struct hostsfile *next;
|
||||
int flags;
|
||||
char *fname;
|
||||
#ifdef HAVE_INOTIFY
|
||||
int wd; /* inotify watch descriptor */
|
||||
#endif
|
||||
unsigned int index; /* matches to cache entries for logging */
|
||||
};
|
||||
|
||||
struct dyndir {
|
||||
struct dyndir *next;
|
||||
struct hostsfile *files;
|
||||
int flags;
|
||||
char *dname;
|
||||
#ifdef HAVE_INOTIFY
|
||||
int wd; /* inotify watch descriptor */
|
||||
#endif
|
||||
};
|
||||
|
||||
/* packet-dump flags */
|
||||
#define DUMP_QUERY 0x0001
|
||||
#define DUMP_REPLY 0x0002
|
||||
#define DUMP_UP_QUERY 0x0004
|
||||
#define DUMP_UP_REPLY 0x0008
|
||||
#define DUMP_SEC_QUERY 0x0010
|
||||
#define DUMP_SEC_REPLY 0x0020
|
||||
#define DUMP_BOGUS 0x0040
|
||||
#define DUMP_SEC_BOGUS 0x0080
|
||||
#define DUMP_QUERY 0x0001
|
||||
#define DUMP_REPLY 0x0002
|
||||
#define DUMP_UP_QUERY 0x0004
|
||||
#define DUMP_UP_REPLY 0x0008
|
||||
#define DUMP_SEC_QUERY 0x0010
|
||||
#define DUMP_SEC_REPLY 0x0020
|
||||
#define DUMP_BOGUS 0x0040
|
||||
#define DUMP_SEC_BOGUS 0x0080
|
||||
#define DUMP_DHCP 0x1000
|
||||
#define DUMP_DHCPV6 0x2000
|
||||
#define DUMP_RA 0x4000
|
||||
#define DUMP_TFTP 0x8000
|
||||
|
||||
/* DNSSEC status values. */
|
||||
#define STAT_SECURE 0x10000
|
||||
@@ -700,6 +748,7 @@ struct hostsfile {
|
||||
#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 */
|
||||
@@ -710,23 +759,21 @@ struct hostsfile {
|
||||
#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))
|
||||
|
||||
#define FREC_NOREBIND 1
|
||||
#define FREC_CHECKING_DISABLED 2
|
||||
#define FREC_HAS_SUBNET 4
|
||||
#define FREC_NO_CACHE 4
|
||||
#define FREC_DNSKEY_QUERY 8
|
||||
#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 FREC_NO_CACHE 2048
|
||||
|
||||
#define HASH_SIZE 32 /* SHA-256 digest size */
|
||||
#define FREC_HAS_PHEADER 128
|
||||
#define FREC_GONE_TO_TCP 256
|
||||
|
||||
struct frec {
|
||||
struct frec_src {
|
||||
@@ -734,7 +781,7 @@ struct frec {
|
||||
union all_addr dest;
|
||||
unsigned int iface, log_id;
|
||||
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 */
|
||||
@@ -742,11 +789,12 @@ struct frec {
|
||||
unsigned short new_id;
|
||||
int forwardall, flags;
|
||||
time_t time;
|
||||
unsigned char *hash[HASH_SIZE];
|
||||
#ifdef HAVE_DNSSEC
|
||||
int class, work_counter;
|
||||
struct blockdata *stash; /* Saved reply, whilst we validate */
|
||||
u32 forward_timestamp;
|
||||
int forward_delay;
|
||||
struct blockdata *stash; /* saved query or saved reply, whilst we validate */
|
||||
size_t stash_len;
|
||||
#ifdef HAVE_DNSSEC
|
||||
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. */
|
||||
@@ -771,6 +819,7 @@ struct frec {
|
||||
#define ACTION_TFTP 5
|
||||
#define ACTION_ARP 6
|
||||
#define ACTION_ARP_DEL 7
|
||||
#define ACTION_RELAY_SNOOP 8
|
||||
|
||||
#define LEASE_NEW 1 /* newly created */
|
||||
#define LEASE_CHANGED 2 /* modified */
|
||||
@@ -782,6 +831,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 */
|
||||
@@ -902,6 +957,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;
|
||||
@@ -962,6 +1018,8 @@ struct dhcp_bridge {
|
||||
|
||||
struct cond_domain {
|
||||
char *domain, *prefix; /* prefix is text-prefix on domain name */
|
||||
char *interface; /* These two set when domain comes from interface. */
|
||||
struct addrlist *al;
|
||||
struct in_addr start, end;
|
||||
struct in6_addr start6, end6;
|
||||
int is6, indexed, prefixlen;
|
||||
@@ -1066,10 +1124,21 @@ 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 */
|
||||
struct dhcp_relay *current, *next;
|
||||
int port; /* Port of relay we forward to. */
|
||||
#ifdef HAVE_SCRIPT
|
||||
struct snoop_record {
|
||||
struct in6_addr client, prefix;
|
||||
int prefix_len;
|
||||
struct snoop_record *next;
|
||||
} *snoop_records;
|
||||
#endif
|
||||
struct dhcp_relay *next;
|
||||
};
|
||||
|
||||
extern struct daemon {
|
||||
@@ -1085,6 +1154,7 @@ extern struct daemon {
|
||||
struct naptr *naptr;
|
||||
struct txt_record *txt, *rr;
|
||||
struct ptr_record *ptr;
|
||||
struct rrlist *cache_rr, *filter_rr;
|
||||
struct host_record *host_records, *host_records_tail;
|
||||
struct cname *cnames;
|
||||
struct auth_zone *auth_zones;
|
||||
@@ -1105,15 +1175,17 @@ extern struct daemon {
|
||||
char *lease_change_command;
|
||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
||||
struct bogus_addr *bogus_addr, *ignore_addr;
|
||||
struct server *servers, *local_domains, **serverarray, *no_rebind;
|
||||
struct server *servers, *servers_tail, *local_domains, **serverarray;
|
||||
struct rebind_domain *no_rebind;
|
||||
int server_has_wildcard;
|
||||
int serverarraysz, serverarrayhwm;
|
||||
struct ipsets *ipsets;
|
||||
struct ipsets *ipsets, *nftsets;
|
||||
u32 allowlist_mask;
|
||||
struct allowlist *allowlists;
|
||||
int log_fac; /* log facility */
|
||||
char *log_file; /* optional log file */
|
||||
int max_logs; /* queue limit */
|
||||
int randport_limit; /* Maximum number of source ports for query. */
|
||||
int cachesize, ftabsize;
|
||||
int port, query_port, min_port, max_port;
|
||||
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
|
||||
@@ -1121,6 +1193,7 @@ extern struct daemon {
|
||||
u32 umbrella_org;
|
||||
u32 umbrella_asset;
|
||||
u8 umbrella_device[8];
|
||||
int host_index;
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp, *dhcp6;
|
||||
struct ra_interface *ra_interfaces;
|
||||
@@ -1141,7 +1214,8 @@ extern struct daemon {
|
||||
int doing_ra, doing_dhcp6;
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
||||
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
|
||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
||||
struct dyndir *dynamic_dirs;
|
||||
int dhcp_max, tftp_max, tftp_mtu;
|
||||
int dhcp_server_port, dhcp_client_port;
|
||||
int start_tftp_port, end_tftp_port;
|
||||
@@ -1158,6 +1232,8 @@ extern struct daemon {
|
||||
int dump_mask;
|
||||
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||
u32 metrics[__METRIC_MAX];
|
||||
int fast_retry_time, fast_retry_timeout;
|
||||
int cache_max_expiry;
|
||||
#ifdef HAVE_DNSSEC
|
||||
struct ds_config *ds;
|
||||
char *timestamp_file;
|
||||
@@ -1167,13 +1243,14 @@ extern struct daemon {
|
||||
char *packet; /* packet buffer */
|
||||
int packet_buff_sz; /* size of above */
|
||||
char *namebuff; /* MAXDNAME size buffer */
|
||||
char *workspacename;
|
||||
#ifdef HAVE_DNSSEC
|
||||
char *keyname; /* MAXDNAME size buffer */
|
||||
char *workspacename; /* ditto */
|
||||
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;
|
||||
@@ -1184,8 +1261,8 @@ extern struct daemon {
|
||||
struct server *srv_save; /* Used for resend on DoD */
|
||||
size_t packet_len; /* " " */
|
||||
int fd_save; /* " " */
|
||||
pid_t tcp_pids[MAX_PROCS];
|
||||
int tcp_pipes[MAX_PROCS];
|
||||
pid_t *tcp_pids;
|
||||
int *tcp_pipes;
|
||||
int pipe_to_parent;
|
||||
int numrrand;
|
||||
struct randfd *randomsocks;
|
||||
@@ -1216,13 +1293,18 @@ extern struct daemon {
|
||||
unsigned char *duid;
|
||||
struct iovec outpacket;
|
||||
int dhcp6fd, icmp6fd;
|
||||
# ifdef HAVE_SCRIPT
|
||||
struct snoop_record *free_snoops;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* DBus stuff */
|
||||
/* void * here to avoid depending on dbus headers outside dbus.c */
|
||||
void *dbus;
|
||||
#ifdef HAVE_DBUS
|
||||
struct watch *watches;
|
||||
#endif
|
||||
|
||||
/* UBus stuff */
|
||||
#ifdef HAVE_UBUS
|
||||
/* void * here to avoid depending on ubus headers outside ubus.c */
|
||||
@@ -1240,14 +1322,24 @@ extern struct daemon {
|
||||
/* file for packet dumps. */
|
||||
int dumpfd;
|
||||
#endif
|
||||
int max_procs;
|
||||
uint max_procs_used;
|
||||
} *daemon;
|
||||
|
||||
struct server_details {
|
||||
union mysockaddr *addr, *source_addr;
|
||||
struct addrinfo *hostinfo, *orig_hostinfo;
|
||||
char *interface, *source, *scope_id, *interface_opt;
|
||||
int serv_port, source_port, addr_type, scope_index, valid;
|
||||
u16 *flags;
|
||||
};
|
||||
|
||||
/* cache.c */
|
||||
void cache_init(void);
|
||||
unsigned short rrtype(char *in);
|
||||
void next_uid(struct crec *crecp);
|
||||
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg);
|
||||
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg, unsigned short type);
|
||||
char *record_source(unsigned int index);
|
||||
char *querystr(char *desc, unsigned short type);
|
||||
int cache_find_non_terminal(char *name, time_t now);
|
||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||
union all_addr *addr, time_t now,
|
||||
@@ -1256,6 +1348,7 @@ struct crec *cache_find_by_name(struct crec *crecp,
|
||||
char *name, time_t now, unsigned int prot);
|
||||
void cache_end_insert(void);
|
||||
void cache_start_insert(void);
|
||||
unsigned int cache_remove_uid(const unsigned int uid);
|
||||
int cache_recv_insert(time_t now, int fd);
|
||||
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
||||
time_t now, unsigned long ttl, unsigned int flags);
|
||||
@@ -1277,6 +1370,8 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size,
|
||||
void blockdata_init(void);
|
||||
void blockdata_report(void);
|
||||
struct blockdata *blockdata_alloc(char *data, size_t len);
|
||||
int blockdata_expand(struct blockdata *block, size_t oldlen,
|
||||
char *data, size_t newlen);
|
||||
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);
|
||||
struct blockdata *blockdata_read(int fd, size_t len);
|
||||
void blockdata_write(struct blockdata *block, size_t len, int fd);
|
||||
@@ -1289,6 +1384,7 @@ 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);
|
||||
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
|
||||
@@ -1298,14 +1394,14 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
||||
char *name, unsigned short *typep);
|
||||
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, char **ipsets, int is_sign, int check_rebind,
|
||||
int no_cache_dnssec, int secure, int *doctored);
|
||||
time_t now, struct ipsets *ipsets, struct ipsets *nftsets, int is_sign,
|
||||
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);
|
||||
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);
|
||||
@@ -1321,28 +1417,25 @@ int private_net(struct in_addr addr, int ban_localhost);
|
||||
/* 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);
|
||||
@@ -1357,6 +1450,7 @@ void rand_init(void);
|
||||
unsigned short rand16(void);
|
||||
u32 rand32(void);
|
||||
u64 rand64(void);
|
||||
int rr_on_list(struct rrlist *list, unsigned short rr);
|
||||
int legal_hostname(char *name);
|
||||
char *canonicalise(char *in, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||
@@ -1364,11 +1458,15 @@ void *safe_malloc(size_t size);
|
||||
void safe_strncpy(char *dest, const char *src, size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
void *whine_realloc(void *ptr, size_t size);
|
||||
int sa_len(union mysockaddr *addr);
|
||||
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
|
||||
int sockaddr_isnull(const union mysockaddr *s);
|
||||
int hostname_order(const char *a, const char *b);
|
||||
int hostname_isequal(const char *a, const char *b);
|
||||
int hostname_issubdomain(char *a, char *b);
|
||||
time_t dnsmasq_time(void);
|
||||
u32 dnsmasq_milliseconds(void);
|
||||
int netmask_length(struct in_addr mask);
|
||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||
int is_same_net_prefix(struct in_addr a, struct in_addr b, int prefix);
|
||||
@@ -1412,13 +1510,21 @@ void read_servers_file(void);
|
||||
void set_option_bool(unsigned int opt);
|
||||
void reset_option_bool(unsigned int opt);
|
||||
struct hostsfile *expand_filelist(struct hostsfile *list);
|
||||
char *parse_server(char *arg, union mysockaddr *addr,
|
||||
union mysockaddr *source_addr, char *interface, u16 *flags);
|
||||
char *parse_server(char *arg, struct server_details *sdetails);
|
||||
char *parse_server_addr(struct server_details *sdetails);
|
||||
int parse_server_next(struct server_details *sdetails);
|
||||
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, char *keyname, 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);
|
||||
@@ -1428,6 +1534,7 @@ int send_from(int fd, int nowild, char *packet, size_t len,
|
||||
void resend_query(void);
|
||||
int allocate_rfd(struct randfd_list **fdlp, struct server *serv);
|
||||
void free_rfds(struct randfd_list **fdlp);
|
||||
int fast_retry(time_t now);
|
||||
|
||||
/* network.c */
|
||||
int indextoname(int fd, int index, char *name);
|
||||
@@ -1511,6 +1618,7 @@ void lease_update_from_configs(void);
|
||||
int do_script_run(time_t now);
|
||||
void rerun_scripts(void);
|
||||
void lease_find_interfaces(time_t now);
|
||||
void lease_calc_fqdns(void);
|
||||
#ifdef HAVE_SCRIPT
|
||||
void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
|
||||
unsigned int len, int delim);
|
||||
@@ -1536,6 +1644,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, int class, struct server *server, int *keycount, int *validatecount);
|
||||
#endif
|
||||
|
||||
/* netlink.c */
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
@@ -1553,7 +1665,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
|
||||
@@ -1583,6 +1701,12 @@ void ipset_init(void);
|
||||
int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove);
|
||||
#endif
|
||||
|
||||
/* nftset.c */
|
||||
#ifdef HAVE_NFTSET
|
||||
void nftset_init(void);
|
||||
int add_to_nftset(const char *setpath, const union all_addr *ipaddr, int flags, int remove);
|
||||
#endif
|
||||
|
||||
/* pattern.c */
|
||||
#ifdef HAVE_CONNTRACK
|
||||
int is_valid_dns_name(const char *value);
|
||||
@@ -1602,6 +1726,9 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
||||
void queue_arp(int action, unsigned char *mac, int maclen,
|
||||
int family, union all_addr *addr);
|
||||
int helper_buf_empty(void);
|
||||
#ifdef HAVE_DHCP6
|
||||
void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* tftp.c */
|
||||
@@ -1644,10 +1771,13 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
|
||||
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
|
||||
size_t sz, struct in6_addr *client_addr, time_t now);
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
|
||||
int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address,
|
||||
u32 scope_id, time_t now);
|
||||
|
||||
unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
|
||||
int relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
|
||||
# ifdef HAVE_SCRIPT
|
||||
int do_snoop_script_run(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* dhcp-common.c */
|
||||
@@ -1655,8 +1785,9 @@ unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arriva
|
||||
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);
|
||||
@@ -1674,7 +1805,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
char *whichdevice(void);
|
||||
void bindtodevice(char *device, int fd);
|
||||
int bind_dhcp_devices(char *bound_device);
|
||||
#endif
|
||||
# ifdef HAVE_DHCP6
|
||||
void display_opts6(void);
|
||||
@@ -1732,18 +1863,24 @@ void poll_listen(int fd, short event);
|
||||
int do_poll(int timeout);
|
||||
|
||||
/* rrfilter.c */
|
||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
|
||||
u16 *rrfilter_desc(int type);
|
||||
size_t rrfilter(struct dns_header *header, size_t *plen, int mode);
|
||||
short *rrfilter_desc(int type);
|
||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
||||
int to_wire(char *name);
|
||||
void from_wire(char *name);
|
||||
/* modes. */
|
||||
#define RRFILTER_EDNS0 0
|
||||
#define RRFILTER_DNSSEC 1
|
||||
#define RRFILTER_CONF 2
|
||||
|
||||
/* edns0.c */
|
||||
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 *check_subnet, int *cacheable);
|
||||
union mysockaddr *source, time_t now, int *cacheable);
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
|
||||
|
||||
/* arp.c */
|
||||
@@ -1753,7 +1890,10 @@ int do_arp_script_run(void);
|
||||
/* dump.c */
|
||||
#ifdef HAVE_DUMPFILE
|
||||
void dump_init(void);
|
||||
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst);
|
||||
void dump_packet_udp(int mask, void *packet, size_t len, union mysockaddr *src,
|
||||
union mysockaddr *dst, int fd);
|
||||
void dump_packet_icmp(int mask, void *packet, size_t len, union mysockaddr *src,
|
||||
union mysockaddr *dst);
|
||||
#endif
|
||||
|
||||
/* domain-match.c */
|
||||
|
||||
885
src/dnssec.c
885
src/dnssec.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -207,16 +207,20 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||
}
|
||||
}
|
||||
|
||||
if (found)
|
||||
if (found && filter_servers(try, flags, &nlow, &nhigh))
|
||||
/* We have a match, but it may only be (say) an IPv6 address, and
|
||||
if the query wasn't for an AAAA record, it's no good, and we need
|
||||
to continue generalising */
|
||||
{
|
||||
/* We've matched a setting which says to use servers without a domain.
|
||||
Continue the search with empty query */
|
||||
if (daemon->serverarray[try]->flags & SERV_USE_RESOLV)
|
||||
crop_query = qlen;
|
||||
else if (filter_servers(try, flags, &nlow, &nhigh))
|
||||
/* We have a match, but it may only be (say) an IPv6 address, and
|
||||
if the query wasn't for an AAAA record, it's no good, and we need
|
||||
to continue generalising */
|
||||
Continue the search with empty query. We set the F_SERVER flag
|
||||
so that --address=/#/... doesn't match. */
|
||||
if (daemon->serverarray[nlow]->flags & SERV_USE_RESOLV)
|
||||
{
|
||||
crop_query = qlen;
|
||||
flags |= F_SERVER;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -249,9 +253,10 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||
if (highout)
|
||||
*highout = nhigh;
|
||||
|
||||
if (nlow == nhigh)
|
||||
/* qlen == -1 when we failed to match even an empty query, if there are no default servers. */
|
||||
if (nlow == nhigh || qlen == -1)
|
||||
return 0;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -273,7 +278,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
nlow--;
|
||||
|
||||
while (nhigh < daemon->serverarraysz-1 && order_servers(daemon->serverarray[nhigh], daemon->serverarray[nhigh+1]) == 0)
|
||||
nhigh++;
|
||||
nhigh++;
|
||||
|
||||
nhigh++;
|
||||
|
||||
@@ -293,13 +298,13 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
else
|
||||
{
|
||||
/* Now the servers are on order between low and high, in the order
|
||||
IPv6 addr, IPv4 addr, return zero for both, send upstream, no-data return.
|
||||
IPv6 addr, IPv4 addr, return zero for both, resolvconf servers, send upstream, no-data return.
|
||||
|
||||
See which of those match our query in that priority order and narrow (low, high) */
|
||||
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++);
|
||||
|
||||
if (i != nlow && (flags & F_IPV6))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV6))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
@@ -307,7 +312,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_4ADDR); i++);
|
||||
|
||||
if (i != nlow && (flags & F_IPV4))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV4))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
@@ -315,38 +320,46 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_ALL_ZEROS); i++);
|
||||
|
||||
if (i != nlow && (flags & (F_IPV4 | F_IPV6)))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & (F_IPV4 | F_IPV6)))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
nlow = i;
|
||||
|
||||
/* now look for a server */
|
||||
for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
||||
|
||||
/* Short to resolv.conf servers */
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++);
|
||||
|
||||
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)
|
||||
nlow = nhigh;
|
||||
else
|
||||
nhigh = i;
|
||||
}
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
/* --local=/domain/, only return if we don't need a server. */
|
||||
if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER))
|
||||
nhigh = i;
|
||||
/* now look for a server */
|
||||
for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
||||
|
||||
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)
|
||||
nlow = nhigh;
|
||||
else
|
||||
nhigh = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* --local=/domain/, only return if we don't need a server. */
|
||||
if (flags & (F_DNSSECOK | F_DOMAINSRV | F_SERVER))
|
||||
nhigh = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*lowout = nlow;
|
||||
*highout = nhigh;
|
||||
|
||||
@@ -387,16 +400,24 @@ int is_local_answer(time_t now, int first, char *name)
|
||||
|
||||
size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header *header, char *name, char *limit, int first, int last, int ede)
|
||||
{
|
||||
int trunc = 0;
|
||||
int trunc = 0, anscount = 0;
|
||||
unsigned char *p;
|
||||
int start;
|
||||
union all_addr addr;
|
||||
|
||||
if (flags & (F_NXDOMAIN | F_NOERR))
|
||||
log_query(flags | gotname | F_NEG | F_CONFIG | F_FORWARD, name, NULL, NULL);
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
@@ -410,9 +431,9 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
else
|
||||
addr.addr4 = srv->addr;
|
||||
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr);
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
|
||||
anscount++;
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
|
||||
}
|
||||
|
||||
if (flags & gotname & F_IPV6)
|
||||
@@ -425,14 +446,21 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
else
|
||||
addr.addr6 = srv->addr;
|
||||
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL);
|
||||
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr))
|
||||
anscount++;
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
|
||||
}
|
||||
|
||||
if (trunc)
|
||||
header->hb3 |= HB3_TC;
|
||||
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -485,7 +513,7 @@ static int order(char *qdomain, size_t qlen, struct server *serv)
|
||||
if (qlen > dlen)
|
||||
return -1;
|
||||
|
||||
return strcmp(qdomain, serv->domain);
|
||||
return hostname_order(qdomain, serv->domain);
|
||||
}
|
||||
|
||||
static int order_servers(struct server *s1, struct server *s2)
|
||||
@@ -520,35 +548,66 @@ static int order_qsort(const void *a, const void *b)
|
||||
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
|
||||
in a very specific order. We flip the SERV_LITERAL_ADDRESS bit
|
||||
so the order is IPv6 literal, IPv4 literal, all-zero literal,
|
||||
upstream server, NXDOMAIN literal. */
|
||||
unqualified servers, upstream server, NXDOMAIN literal. */
|
||||
if (rc == 0)
|
||||
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
|
||||
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
|
||||
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
|
||||
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
||||
/* When loading large numbers of server=.... lines during startup,
|
||||
there's no possibility that there will be server records that can be reused, but
|
||||
searching a long list for each server added grows as O(n^2) and slows things down.
|
||||
This flag is set only if is known there may be free server records that can be reused.
|
||||
There's a call to mark_servers(0) in read_opts() to reset the flag before
|
||||
main config read. */
|
||||
|
||||
static int maybe_free_servers = 0;
|
||||
|
||||
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||
void mark_servers(int flag)
|
||||
{
|
||||
struct server *serv;
|
||||
struct server *serv, *next, **up;
|
||||
|
||||
maybe_free_servers = !!flag;
|
||||
|
||||
daemon->servers_tail = NULL;
|
||||
|
||||
/* mark everything with argument flag */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
{
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
|
||||
for (serv = daemon->local_domains; serv; serv = serv->next)
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
daemon->servers_tail = serv;
|
||||
}
|
||||
|
||||
/* --address etc is different: since they are expected to be
|
||||
1) numerous and 2) not reloaded often. We just delete
|
||||
and recreate. */
|
||||
if (flag)
|
||||
for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = next)
|
||||
{
|
||||
next = serv->next;
|
||||
|
||||
if (serv->flags & flag)
|
||||
{
|
||||
*up = next;
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_servers(void)
|
||||
@@ -556,7 +615,7 @@ void cleanup_servers(void)
|
||||
struct server *serv, *tmp, **up;
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
for (serv = daemon->servers, up = &daemon->servers, daemon->servers_tail = NULL; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
@@ -567,21 +626,11 @@ void cleanup_servers(void)
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
{
|
||||
up = &serv->next;
|
||||
daemon->servers_tail = serv;
|
||||
}
|
||||
}
|
||||
|
||||
for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
{
|
||||
*up = serv->next;
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
}
|
||||
|
||||
int add_update_server(int flags,
|
||||
@@ -609,90 +658,109 @@ int add_update_server(int flags,
|
||||
|
||||
if (*domain == 0)
|
||||
alloc_domain = whine_malloc(1);
|
||||
else if (!(alloc_domain = canonicalise((char *)domain, NULL)))
|
||||
return 0;
|
||||
|
||||
/* See if there is a suitable candidate, and unmark
|
||||
only do this for forwarding servers, not
|
||||
address or local, to avoid delays on large numbers. */
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
break;
|
||||
|
||||
if (serv)
|
||||
{
|
||||
free(alloc_domain);
|
||||
alloc_domain = serv->domain;
|
||||
}
|
||||
else
|
||||
alloc_domain = canonicalise((char *)domain, NULL);
|
||||
|
||||
if (!alloc_domain)
|
||||
return 0;
|
||||
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (flags & SERV_LITERAL_ADDRESS)
|
||||
{
|
||||
if (flags & SERV_6ADDR)
|
||||
size = sizeof(struct serv_addr6);
|
||||
else if (flags & SERV_4ADDR)
|
||||
size = sizeof(struct serv_addr4);
|
||||
else
|
||||
size = sizeof(struct serv_local);
|
||||
}
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
size = sizeof(struct serv_addr6);
|
||||
else if (flags & SERV_4ADDR)
|
||||
size = sizeof(struct serv_addr4);
|
||||
else
|
||||
size = sizeof(struct server);
|
||||
size = sizeof(struct serv_local);
|
||||
|
||||
if (!(serv = whine_malloc(size)))
|
||||
return 0;
|
||||
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
{
|
||||
serv->next = daemon->local_domains;
|
||||
daemon->local_domains = serv;
|
||||
free(alloc_domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
serv->next = daemon->local_domains;
|
||||
daemon->local_domains = serv;
|
||||
|
||||
if (flags & SERV_4ADDR)
|
||||
((struct serv_addr4*)serv)->addr = local_addr->addr4;
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
((struct serv_addr6*)serv)->addr = local_addr->addr6;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Upstream servers. See if there is a suitable candidate, if so unmark
|
||||
and move to the end of the list, for order. The entry found may already
|
||||
be at the end. */
|
||||
struct server **up, *tmp;
|
||||
|
||||
serv = NULL;
|
||||
|
||||
if (maybe_free_servers)
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
{
|
||||
/* Need to move down? */
|
||||
if (serv->next)
|
||||
{
|
||||
*up = serv->next;
|
||||
daemon->servers_tail->next = serv;
|
||||
daemon->servers_tail = serv;
|
||||
serv->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
|
||||
if (serv)
|
||||
{
|
||||
free(alloc_domain);
|
||||
alloc_domain = serv->domain;
|
||||
}
|
||||
else
|
||||
{
|
||||
struct server *s;
|
||||
/* Add to the end of the chain, for order */
|
||||
if (!daemon->servers)
|
||||
daemon->servers = serv;
|
||||
else
|
||||
if (!(serv = whine_malloc(sizeof(struct server))))
|
||||
{
|
||||
for (s = daemon->servers; s->next; s = s->next);
|
||||
s->next = serv;
|
||||
free(alloc_domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
serv->next = NULL;
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
/* Add to the end of the chain, for order */
|
||||
if (daemon->servers_tail)
|
||||
daemon->servers_tail->next = serv;
|
||||
else
|
||||
daemon->servers = serv;
|
||||
daemon->servers_tail = serv;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(flags & SERV_IS_LOCAL))
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
serv->flags = flags;
|
||||
serv->domain = alloc_domain;
|
||||
serv->domain_len = strlen(alloc_domain);
|
||||
|
||||
if (flags & SERV_4ADDR)
|
||||
((struct serv_addr4*)serv)->addr = local_addr->addr4;
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
((struct serv_addr6*)serv)->addr = local_addr->addr6;
|
||||
|
||||
if (!(flags & SERV_IS_LOCAL))
|
||||
{
|
||||
|
||||
#ifdef HAVE_LOOP
|
||||
serv->uid = rand32();
|
||||
#endif
|
||||
|
||||
|
||||
if (interface)
|
||||
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
||||
if (addr)
|
||||
serv->addr = *addr;
|
||||
if (source_addr)
|
||||
serv->source_addr = *source_addr;
|
||||
}
|
||||
|
||||
serv->tcpfd = -1;
|
||||
}
|
||||
|
||||
serv->flags = flags;
|
||||
serv->domain = alloc_domain;
|
||||
serv->domain_len = strlen(alloc_domain);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
108
src/domain.c
108
src/domain.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,12 +22,13 @@ static int match_domain(struct in_addr addr, struct cond_domain *c);
|
||||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||
static int match_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||
|
||||
int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
int is_name_synthetic(int flags, char *name, union all_addr *addrp)
|
||||
{
|
||||
char *p;
|
||||
struct cond_domain *c = NULL;
|
||||
int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET;
|
||||
|
||||
union all_addr addr;
|
||||
|
||||
for (c = daemon->synth_domains; c; c = c->next)
|
||||
{
|
||||
int found = 0;
|
||||
@@ -74,7 +75,7 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
if (!c->is6 &&
|
||||
index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
|
||||
{
|
||||
addr->addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||
addr.addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
@@ -86,8 +87,8 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
index <= addr6part(&c->end6) - addr6part(&c->start6))
|
||||
{
|
||||
u64 start = addr6part(&c->start6);
|
||||
addr->addr6 = c->start6;
|
||||
setaddr6part(&addr->addr6, start + index);
|
||||
addr.addr6 = c->start6;
|
||||
setaddr6part(&addr.addr6, start + index);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
@@ -114,29 +115,18 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
|
||||
*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);
|
||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, &addr))
|
||||
found = (prot == AF_INET) ? match_domain(addr.addr4, c) : match_domain6(&addr.addr6, c);
|
||||
}
|
||||
|
||||
/* restore name */
|
||||
@@ -148,7 +138,12 @@ int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||
|
||||
|
||||
if (found)
|
||||
return 1;
|
||||
{
|
||||
if (addrp)
|
||||
*addrp = addr;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -188,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);
|
||||
@@ -198,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);
|
||||
@@ -230,9 +217,17 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
|
||||
|
||||
static int match_domain(struct in_addr addr, struct cond_domain *c)
|
||||
{
|
||||
if (!c->is6 &&
|
||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
if (c->interface)
|
||||
{
|
||||
struct addrlist *al;
|
||||
for (al = c->al; al; al = al->next)
|
||||
if (!(al->flags & ADDRLIST_IPV6) &&
|
||||
is_same_net_prefix(addr, al->addr.addr4, al->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
else if (!c->is6 &&
|
||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -259,12 +254,21 @@ char *get_domain(struct in_addr addr)
|
||||
|
||||
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||
{
|
||||
u64 addrpart = addr6part(addr);
|
||||
|
||||
if (c->is6)
|
||||
|
||||
/* subnet from interface address. */
|
||||
if (c->interface)
|
||||
{
|
||||
struct addrlist *al;
|
||||
for (al = c->al; al; al = al->next)
|
||||
if (al->flags & ADDRLIST_IPV6 &&
|
||||
is_same_net6(addr, &al->addr.addr6, al->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
else if (c->is6)
|
||||
{
|
||||
if (c->prefixlen >= 64)
|
||||
{
|
||||
u64 addrpart = addr6part(addr);
|
||||
if (is_same_net6(addr, &c->start6, 64) &&
|
||||
addrpart >= addr6part(&c->start6) &&
|
||||
addrpart <= addr6part(&c->end6))
|
||||
@@ -273,7 +277,7 @@ static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||
else if (is_same_net6(addr, &c->start6, c->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
180
src/dump.c
180
src/dump.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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,7 +18,11 @@
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
static u32 packet_count;
|
||||
static void do_dump_packet(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int port, int proto);
|
||||
|
||||
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
|
||||
struct pcap_hdr_s {
|
||||
@@ -47,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++;
|
||||
@@ -79,7 +91,45 @@ void dump_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
|
||||
void dump_packet_udp(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int fd)
|
||||
{
|
||||
union mysockaddr fd_addr;
|
||||
socklen_t addr_len = sizeof(fd_addr);
|
||||
|
||||
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
|
||||
{
|
||||
/* if fd is negative it carries a port number (negated)
|
||||
which we use as a source or destination when not otherwise
|
||||
specified so wireshark can ID the packet.
|
||||
If both src and dst are specified, set this to -1 to avoid
|
||||
a spurious getsockname() call. */
|
||||
int port = (fd < 0) ? -fd : -1;
|
||||
|
||||
/* fd >= 0 is a file descriptor and the address of that file descriptor is used
|
||||
in place of a NULL src or dst. */
|
||||
if (fd >= 0 && getsockname(fd, (struct sockaddr *)&fd_addr, &addr_len) != -1)
|
||||
{
|
||||
if (!src)
|
||||
src = &fd_addr;
|
||||
|
||||
if (!dst)
|
||||
dst = &fd_addr;
|
||||
}
|
||||
|
||||
do_dump_packet(mask, packet, len, src, dst, port, IPPROTO_UDP);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_packet_icmp(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst)
|
||||
{
|
||||
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
|
||||
do_dump_packet(mask, packet, len, src, dst, -1, IPPROTO_ICMP);
|
||||
}
|
||||
|
||||
static void do_dump_packet(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int port, int proto)
|
||||
{
|
||||
struct ip ip;
|
||||
struct ip6_hdr ip6;
|
||||
@@ -96,13 +146,14 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
void *iphdr;
|
||||
size_t ipsz;
|
||||
int rc;
|
||||
|
||||
/* if port != -1 it carries a port number
|
||||
which we use as a source or destination when not otherwise
|
||||
specified so wireshark can ID the packet.
|
||||
If both src and dst are specified, set this to -1 to avoid
|
||||
a spurious getsockname() call. */
|
||||
udp.uh_sport = udp.uh_dport = htons(port < 0 ? 0 : port);
|
||||
|
||||
if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
|
||||
return;
|
||||
|
||||
/* So wireshark can Id the packet. */
|
||||
udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
|
||||
|
||||
if (src)
|
||||
family = src->sa.sa_family;
|
||||
else
|
||||
@@ -115,10 +166,16 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
memset(&ip6, 0, sizeof(ip6));
|
||||
|
||||
ip6.ip6_vfc = 6 << 4;
|
||||
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
|
||||
ip6.ip6_nxt = IPPROTO_UDP;
|
||||
ip6.ip6_hops = 64;
|
||||
|
||||
if ((ip6.ip6_nxt = proto) == IPPROTO_UDP)
|
||||
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
|
||||
else
|
||||
{
|
||||
proto = ip6.ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6.ip6_plen = htons(len);
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
|
||||
@@ -134,9 +191,8 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
/* start UDP checksum */
|
||||
for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2)
|
||||
{
|
||||
sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ;
|
||||
sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ;
|
||||
|
||||
sum += ntohs((ip6.ip6_src.s6_addr[i] << 8) + (ip6.ip6_src.s6_addr[i+1])) ;
|
||||
sum += ntohs((ip6.ip6_dst.s6_addr[i] << 8) + (ip6.ip6_dst.s6_addr[i+1])) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -147,9 +203,15 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
|
||||
ip.ip_v = IPVERSION;
|
||||
ip.ip_hl = sizeof(struct ip) / 4;
|
||||
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
|
||||
ip.ip_ttl = IPDEFTTL;
|
||||
ip.ip_p = IPPROTO_UDP;
|
||||
|
||||
if ((ip.ip_p = proto) == IPPROTO_UDP)
|
||||
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
|
||||
else
|
||||
{
|
||||
ip.ip_len = htons(sizeof(struct ip) + len);
|
||||
proto = ip.ip_p = IPPROTO_ICMP;
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
@@ -170,7 +232,7 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
/* start UDP checksum */
|
||||
/* start UDP/ICMP checksum */
|
||||
sum = ip.ip_src.s_addr & 0xffff;
|
||||
sum += (ip.ip_src.s_addr >> 16) & 0xffff;
|
||||
sum += ip.ip_dst.s_addr & 0xffff;
|
||||
@@ -180,31 +242,61 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
if (len & 1)
|
||||
((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
|
||||
|
||||
udp.uh_sum = 0;
|
||||
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
|
||||
sum += htons(IPPROTO_UDP);
|
||||
sum += htons(sizeof(struct udphdr) + len);
|
||||
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||
sum += ((u16 *)&udp)[i];
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
if (proto == IPPROTO_UDP)
|
||||
{
|
||||
/* Add Remaining part of the pseudoheader. Note that though the
|
||||
IPv6 pseudoheader is very different to the IPv4 one, the
|
||||
net result of this calculation is correct as long as the
|
||||
packet length is less than 65536, which is fine for us. */
|
||||
sum += htons(IPPROTO_UDP);
|
||||
sum += htons(sizeof(struct udphdr) + len);
|
||||
|
||||
udp.uh_sum = 0;
|
||||
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
|
||||
|
||||
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||
sum += ((u16 *)&udp)[i];
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ICMP - ICMPv6 packet is a superset of ICMP */
|
||||
struct icmp6_hdr *icmp = packet;
|
||||
|
||||
/* See comment in UDP code above. */
|
||||
sum += htons(proto);
|
||||
sum += htons(len);
|
||||
|
||||
icmp->icmp6_cksum = 0;
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
icmp->icmp6_cksum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + len;
|
||||
}
|
||||
|
||||
rc = gettimeofday(&time, NULL);
|
||||
pcap_header.ts_sec = time.tv_sec;
|
||||
pcap_header.ts_usec = time.tv_usec;
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
|
||||
|
||||
if (rc == -1 ||
|
||||
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
|
||||
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
|
||||
!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) && (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 UDP packet %u mask 0x%04x"), ++packet_count, mask);
|
||||
my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
217
src/edns0.c
217
src/edns0.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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);
|
||||
|
||||
@@ -178,7 +182,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
memcpy(buff, datap, rdlen);
|
||||
|
||||
/* now, delete OPT RR */
|
||||
plen = rrfilter(header, plen, 0);
|
||||
rrfilter(header, &plen, RRFILTER_EDNS0);
|
||||
|
||||
/* Now, force addition of a new one */
|
||||
p = NULL;
|
||||
@@ -191,21 +195,18 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
if (!(p = skip_questions(header, plen)) ||
|
||||
!(p = skip_section(p,
|
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
{
|
||||
free(buff);
|
||||
return plen;
|
||||
}
|
||||
if (p + 11 > limit)
|
||||
{
|
||||
free(buff);
|
||||
return plen; /* Too big */
|
||||
}
|
||||
header, plen)) ||
|
||||
p + 11 > limit)
|
||||
{
|
||||
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;
|
||||
@@ -248,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)
|
||||
@@ -264,44 +265,62 @@ static void encoder(unsigned char *in, char *out)
|
||||
out[3] = char64(in[2]);
|
||||
}
|
||||
|
||||
/* OPT_ADD_MAC = MAC is added (if available)
|
||||
OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
|
||||
OPT_STRIP_MAC = MAC is removed */
|
||||
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *l3, time_t now, int *cacheablep)
|
||||
{
|
||||
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
|
||||
int replace = 0, maclen = 0;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
char encode[18]; /* handle 6 byte MACs */
|
||||
char encode[18]; /* handle 6 byte MACs ONLY */
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
|
||||
if ((option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) && (maclen = find_mac(l3, mac, 1, now)) == 6)
|
||||
{
|
||||
replace = 1;
|
||||
*cacheablep = 0;
|
||||
|
||||
if (option_bool(OPT_MAC_HEX))
|
||||
print_mac(encode, mac, maclen);
|
||||
else
|
||||
{
|
||||
encoder(mac, encode);
|
||||
encoder(mac+3, encode+4);
|
||||
encode[8] = 0;
|
||||
}
|
||||
if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 1;
|
||||
*cacheablep = 0;
|
||||
|
||||
if (option_bool(OPT_MAC_HEX))
|
||||
print_mac(encode, mac, maclen);
|
||||
else
|
||||
{
|
||||
encoder(mac, encode);
|
||||
encoder(mac+3, encode+4);
|
||||
encode[8] = 0;
|
||||
}
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 2;
|
||||
|
||||
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
|
||||
if (replace != 0 || maclen == 6)
|
||||
plen = add_pseudoheader(header, plen, limit, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
|
||||
/* OPT_ADD_MAC = MAC is added (if available)
|
||||
OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
|
||||
OPT_STRIP_MAC = MAC is removed */
|
||||
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *l3, time_t now, int *cacheablep)
|
||||
{
|
||||
int maclen;
|
||||
int maclen = 0, replace = 0;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) != 0)
|
||||
|
||||
if (option_bool(OPT_ADD_MAC) && (maclen = find_mac(l3, mac, 1, now)) != 0)
|
||||
{
|
||||
*cacheablep = 0;
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
|
||||
if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 1;
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 2;
|
||||
|
||||
if (replace != 0 || maclen != 0)
|
||||
plen = add_pseudoheader(header, plen, limit, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
@@ -378,27 +397,54 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source,
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
|
||||
/* OPT_CLIENT_SUBNET = client subnet is added
|
||||
OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced
|
||||
OPT_STRIP_ECS = client subnet is removed */
|
||||
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, int *cacheable)
|
||||
{
|
||||
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
|
||||
|
||||
int len;
|
||||
int replace = 0, len = 0;
|
||||
struct subnet_opt opt;
|
||||
|
||||
len = calc_subnet_opt(&opt, source, cacheable);
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
if (option_bool(OPT_STRIP_ECS))
|
||||
replace = 1;
|
||||
len = calc_subnet_opt(&opt, source, cacheable);
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_ECS))
|
||||
replace = 2;
|
||||
else
|
||||
{
|
||||
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;
|
||||
@@ -410,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
|
||||
@@ -458,62 +509,56 @@ 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];
|
||||
|
||||
if (daemon->umbrella_org) {
|
||||
PUTSHORT(UMBRELLA_ORG, u);
|
||||
PUTLONG(daemon->umbrella_org, u);
|
||||
}
|
||||
|
||||
int family = source->sa.sa_family;
|
||||
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
||||
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
|
||||
|
||||
if (daemon->umbrella_org)
|
||||
{
|
||||
PUTSHORT(UMBRELLA_ORG, u);
|
||||
PUTLONG(daemon->umbrella_org, u);
|
||||
}
|
||||
|
||||
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
||||
memcpy(u, get_addrp(source, family), size);
|
||||
u += size;
|
||||
|
||||
if (option_bool(OPT_UMBRELLA_DEVID))
|
||||
{
|
||||
PUTSHORT(UMBRELLA_DEVICE, u);
|
||||
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
||||
u += UMBRELLA_DEVICESZ;
|
||||
}
|
||||
|
||||
if (option_bool(OPT_UMBRELLA_DEVID)) {
|
||||
PUTSHORT(UMBRELLA_DEVICE, u);
|
||||
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
||||
u += UMBRELLA_DEVICESZ;
|
||||
}
|
||||
|
||||
if (daemon->umbrella_asset) {
|
||||
PUTSHORT(UMBRELLA_ASSET, u);
|
||||
PUTLONG(daemon->umbrella_asset, u);
|
||||
}
|
||||
|
||||
int len = u - &opt.magic[0];
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, len, 0, 1);
|
||||
if (daemon->umbrella_asset)
|
||||
{
|
||||
PUTSHORT(UMBRELLA_ASSET, u);
|
||||
PUTLONG(daemon->umbrella_asset, u);
|
||||
}
|
||||
|
||||
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
|
||||
in the reply. Set *cacheable to zero if we add an option which the answer
|
||||
may depend on. */
|
||||
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
|
||||
union mysockaddr *source, time_t now, int *cacheable)
|
||||
{
|
||||
*check_subnet = 0;
|
||||
*cacheable = 1;
|
||||
|
||||
if (option_bool(OPT_ADD_MAC))
|
||||
plen = add_mac(header, plen, limit, source, now, cacheable);
|
||||
|
||||
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
|
||||
plen = add_dns_client(header, plen, limit, source, now, cacheable);
|
||||
plen = add_mac(header, plen, limit, source, now, cacheable);
|
||||
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);
|
||||
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
*check_subnet = 1;
|
||||
}
|
||||
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
2410
src/forward.c
2410
src/forward.c
File diff suppressed because it is too large
Load Diff
@@ -1,284 +0,0 @@
|
||||
/* Copyright (c) 2012-2020 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 implementaion.
|
||||
*/
|
||||
|
||||
#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))
|
||||
break; /* 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))
|
||||
break; /* 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))
|
||||
break; /* 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))
|
||||
break; /* 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] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (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
|
||||
84
src/helper.c
84
src/helper.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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)
|
||||
@@ -233,8 +233,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
is6 = (data.flags != AF_INET);
|
||||
data.action = ACTION_ARP;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
else if (data.action == ACTION_RELAY_SNOOP)
|
||||
{
|
||||
is6 = 1;
|
||||
action_str = "relay-snoop";
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* stringify MAC into dhcp_buff */
|
||||
p = daemon->dhcp_buff;
|
||||
@@ -253,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 */
|
||||
@@ -286,7 +291,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
char *dot;
|
||||
hostname = (char *)buf;
|
||||
hostname[data.hostname_len - 1] = 0;
|
||||
if (data.action != ACTION_TFTP)
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_RELAY_SNOOP)
|
||||
{
|
||||
if (!legal_hostname(hostname))
|
||||
hostname = NULL;
|
||||
@@ -332,6 +337,24 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else if (data.action == ACTION_RELAY_SNOOP)
|
||||
{
|
||||
lua_getglobal(lua, "snoop");
|
||||
if (lua_type(lua, -1) != LUA_TFUNCTION)
|
||||
lua_pop(lua, 1); /* tftp function optional */
|
||||
else
|
||||
{
|
||||
lua_pushstring(lua, action_str); /* arg1 - action */
|
||||
lua_newtable(lua); /* arg2 - data table */
|
||||
lua_pushstring(lua, daemon->addrbuff);
|
||||
lua_setfield(lua, -2, "client_address");
|
||||
lua_pushstring(lua, hostname);
|
||||
lua_setfield(lua, -2, "prefix");
|
||||
lua_pushstring(lua, data.interface);
|
||||
lua_setfield(lua, -2, "client_interface");
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else if (data.action == ACTION_ARP)
|
||||
{
|
||||
lua_getglobal(lua, "arp");
|
||||
@@ -398,6 +421,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
end = extradata + data.ed_len;
|
||||
buf = extradata;
|
||||
|
||||
lua_pushnumber(lua, data.ed_len == 0 ? 1 : 0);
|
||||
lua_setfield(lua, -2, "data_missing");
|
||||
|
||||
if (!is6)
|
||||
buf = grab_extradata_lua(buf, end, "vendor_class");
|
||||
@@ -425,15 +451,17 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
buf = grab_extradata_lua(buf, end, "subscriber_id");
|
||||
buf = grab_extradata_lua(buf, end, "remote_id");
|
||||
}
|
||||
|
||||
|
||||
buf = grab_extradata_lua(buf, end, "requested_options");
|
||||
buf = grab_extradata_lua(buf, end, "mud_url");
|
||||
buf = grab_extradata_lua(buf, end, "tags");
|
||||
|
||||
if (is6)
|
||||
buf = grab_extradata_lua(buf, end, "relay_address");
|
||||
else if (data.giaddr.s_addr != 0)
|
||||
{
|
||||
inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||
lua_pushstring(lua, daemon->addrbuff);
|
||||
inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
|
||||
lua_pushstring(lua, daemon->dhcp_buff2);
|
||||
lua_setfield(lua, -2, "relay_address");
|
||||
}
|
||||
|
||||
@@ -553,7 +581,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
close(pipeout[1]);
|
||||
}
|
||||
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP && data.action != ACTION_RELAY_SNOOP)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
|
||||
@@ -576,6 +604,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
end = extradata + data.ed_len;
|
||||
buf = extradata;
|
||||
|
||||
if (data.ed_len == 0)
|
||||
my_setenv("DNSMASQ_DATA_MISSING", "1", &err);
|
||||
|
||||
if (!is6)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
|
||||
@@ -604,18 +635,19 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
|
||||
}
|
||||
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_MUD_URL", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
|
||||
|
||||
|
||||
if (is6)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
|
||||
else
|
||||
{
|
||||
const char *giaddr = NULL;
|
||||
if (data.giaddr.s_addr != 0)
|
||||
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
|
||||
my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err);
|
||||
}
|
||||
|
||||
@@ -640,6 +672,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
||||
close(pipefd[0]);
|
||||
|
||||
if (data.action == ACTION_RELAY_SNOOP)
|
||||
strcpy(daemon->packet, data.interface);
|
||||
|
||||
p = strrchr(daemon->lease_change_command, '/');
|
||||
if (err == 0)
|
||||
{
|
||||
@@ -810,6 +845,29 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
bytes_in_buf = p - (unsigned char *)buf;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len)
|
||||
{
|
||||
/* no script */
|
||||
if (daemon->helperfd == -1)
|
||||
return;
|
||||
|
||||
inet_ntop(AF_INET6, prefix, daemon->addrbuff, ADDRSTRLEN);
|
||||
|
||||
/* 5 for /nnn and zero on the end of the prefix. */
|
||||
buff_alloc(sizeof(struct script_data) + ADDRSTRLEN + 5);
|
||||
memset(buf, 0, sizeof(struct script_data));
|
||||
|
||||
buf->action = ACTION_RELAY_SNOOP;
|
||||
buf->addr6 = *client;
|
||||
buf->hostname_len = sprintf((char *)(buf+1), "%s/%u", daemon->addrbuff, prefix_len) + 1;
|
||||
|
||||
indextoname(daemon->dhcp6fd, if_index, buf->interface);
|
||||
|
||||
bytes_in_buf = sizeof(struct script_data) + buf->hostname_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
/* This nastily re-uses DHCP-fields for TFTP stuff */
|
||||
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
||||
|
||||
146
src/inotify.c
146
src/inotify.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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)
|
||||
@@ -133,74 +133,112 @@ void inotify_dnsmasq_init()
|
||||
}
|
||||
}
|
||||
|
||||
static struct hostsfile *dyndir_addhosts(struct dyndir *dd, char *path)
|
||||
{
|
||||
/* Check if this file is already known in dd->files */
|
||||
struct hostsfile *ah = NULL;
|
||||
for(ah = dd->files; ah; ah = ah->next)
|
||||
if(ah && ah->fname && strcmp(path, ah->fname) == 0)
|
||||
return ah;
|
||||
|
||||
/* Not known, create new hostsfile record for this dyndir */
|
||||
struct hostsfile *newah = NULL;
|
||||
if(!(newah = whine_malloc(sizeof(struct hostsfile))))
|
||||
return NULL;
|
||||
|
||||
/* Add this file to the tip of the linked list */
|
||||
newah->next = dd->files;
|
||||
dd->files = newah;
|
||||
|
||||
/* Copy flags, set index and the full file path */
|
||||
newah->flags = dd->flags;
|
||||
newah->index = daemon->host_index++;
|
||||
newah->fname = path;
|
||||
|
||||
return newah;
|
||||
}
|
||||
|
||||
|
||||
/* initialisation for dynamic-dir. Set inotify watch for each directory, and read pre-existing files */
|
||||
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz)
|
||||
{
|
||||
struct hostsfile *ah;
|
||||
|
||||
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||
struct dyndir *dd;
|
||||
|
||||
for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
|
||||
{
|
||||
DIR *dir_stream = NULL;
|
||||
struct dirent *ent;
|
||||
struct stat buf;
|
||||
|
||||
if (!(ah->flags & flag))
|
||||
|
||||
if (!(dd->flags & flag))
|
||||
continue;
|
||||
|
||||
if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
|
||||
|
||||
if (stat(dd->dname, &buf) == -1)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
||||
ah->fname, strerror(errno));
|
||||
dd->dname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(ah->flags & AH_WD_DONE))
|
||||
|
||||
if (!(S_ISDIR(buf.st_mode)))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
||||
dd->dname, _("not a directory"));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(dd->flags & AH_WD_DONE))
|
||||
{
|
||||
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
|
||||
ah->flags |= AH_WD_DONE;
|
||||
dd->wd = inotify_add_watch(daemon->inotifyfd, dd->dname, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE);
|
||||
dd->flags |= AH_WD_DONE;
|
||||
}
|
||||
|
||||
/* Read contents of dir _after_ calling add_watch, in the hope of avoiding
|
||||
a race which misses files being added as we start */
|
||||
if (ah->wd == -1 || !(dir_stream = opendir(ah->fname)))
|
||||
if (dd->wd == -1 || !(dir_stream = opendir(dd->dname)))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
|
||||
ah->fname, strerror(errno));
|
||||
dd->dname, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
while ((ent = readdir(dir_stream)))
|
||||
{
|
||||
size_t lendir = strlen(ah->fname);
|
||||
size_t lendir = strlen(dd->dname);
|
||||
size_t lenfile = strlen(ent->d_name);
|
||||
char *path;
|
||||
|
||||
|
||||
/* ignore emacs backups and dotfiles */
|
||||
if (lenfile == 0 ||
|
||||
ent->d_name[lenfile - 1] == '~' ||
|
||||
(ent->d_name[0] == '#' && ent->d_name[lenfile - 1] == '#') ||
|
||||
ent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
|
||||
if ((path = whine_malloc(lendir + lenfile + 2)))
|
||||
{
|
||||
strcpy(path, ah->fname);
|
||||
struct hostsfile *ah;
|
||||
|
||||
strcpy(path, dd->dname);
|
||||
strcat(path, "/");
|
||||
strcat(path, ent->d_name);
|
||||
|
||||
if (!(ah = dyndir_addhosts(dd, path)))
|
||||
{
|
||||
free(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ignore non-regular files */
|
||||
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
|
||||
{
|
||||
if (ah->flags & AH_HOSTS)
|
||||
if (dd->flags & AH_HOSTS)
|
||||
total_size = read_hostsfile(path, ah->index, total_size, rhash, revhashsz);
|
||||
#ifdef HAVE_DHCP
|
||||
else if (ah->flags & (AH_DHCP_HST | AH_DHCP_OPT))
|
||||
option_read_dynfile(path, ah->flags);
|
||||
else if (dd->flags & (AH_DHCP_HST | AH_DHCP_OPT))
|
||||
option_read_dynfile(path, dd->flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,7 +249,7 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
|
||||
int inotify_check(time_t now)
|
||||
{
|
||||
int hit = 0;
|
||||
struct hostsfile *ah;
|
||||
struct dyndir *dd;
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -242,36 +280,51 @@ int inotify_check(time_t now)
|
||||
if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
|
||||
hit = 1;
|
||||
|
||||
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||
if (ah->wd == in->wd)
|
||||
for (dd = daemon->dynamic_dirs; dd; dd = dd->next)
|
||||
if (dd->wd == in->wd)
|
||||
{
|
||||
size_t lendir = strlen(ah->fname);
|
||||
size_t lendir = strlen(dd->dname);
|
||||
char *path;
|
||||
|
||||
|
||||
if ((path = whine_malloc(lendir + in->len + 2)))
|
||||
{
|
||||
strcpy(path, ah->fname);
|
||||
struct hostsfile *ah = NULL;
|
||||
|
||||
strcpy(path, dd->dname);
|
||||
strcat(path, "/");
|
||||
strcat(path, in->name);
|
||||
|
||||
my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
|
||||
|
||||
if (ah->flags & AH_HOSTS)
|
||||
/* Is this is a deletion event? */
|
||||
if (in->mask & IN_DELETE)
|
||||
my_syslog(LOG_INFO, _("inotify: %s removed"), path);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("inotify: %s new or modified"), path);
|
||||
|
||||
if (dd->flags & AH_HOSTS)
|
||||
{
|
||||
read_hostsfile(path, ah->index, 0, NULL, 0);
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
if ((ah = dyndir_addhosts(dd, path)))
|
||||
{
|
||||
/* Propagate the consequences of loading a new dhcp-host */
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
lease_update_dns(1);
|
||||
}
|
||||
const unsigned int removed = cache_remove_uid(ah->index);
|
||||
if (removed > 0)
|
||||
my_syslog(LOG_INFO, _("inotify: flushed %u names read from %s"), removed, path);
|
||||
|
||||
/* (Re-)load hostsfile only if this event isn't triggered by deletion */
|
||||
if (!(in->mask & IN_DELETE))
|
||||
read_hostsfile(path, ah->index, 0, NULL, 0);
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
{
|
||||
/* Propagate the consequences of loading a new dhcp-host */
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
lease_update_dns(1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_DHCP
|
||||
else if (ah->flags & AH_DHCP_HST)
|
||||
else if (dd->flags & AH_DHCP_HST)
|
||||
{
|
||||
if (option_read_dynfile(path, AH_DHCP_HST))
|
||||
{
|
||||
@@ -282,11 +335,12 @@ int inotify_check(time_t now)
|
||||
lease_update_dns(1);
|
||||
}
|
||||
}
|
||||
else if (ah->flags & AH_DHCP_OPT)
|
||||
else if (dd->flags & AH_DHCP_OPT)
|
||||
option_read_dynfile(path, AH_DHCP_OPT);
|
||||
#endif
|
||||
|
||||
free(path);
|
||||
if (!ah)
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
||||
@@ -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))));
|
||||
|
||||
65
src/lease.c
65
src/lease.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
|
||||
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
|
||||
@@ -28,8 +27,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
||||
struct dhcp_lease *lease;
|
||||
int clid_len, hw_len, hw_type;
|
||||
int items;
|
||||
char *domain = NULL;
|
||||
|
||||
|
||||
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
|
||||
|
||||
/* client-id max length is 255 which is 255*2 digits + 254 colons
|
||||
@@ -69,8 +67,8 @@ static int read_leases(time_t now, FILE *leasestream)
|
||||
|
||||
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr4))
|
||||
{
|
||||
if ((lease = lease4_allocate(addr.addr4)))
|
||||
domain = get_domain(lease->addr);
|
||||
lease = lease4_allocate(addr.addr4);
|
||||
|
||||
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explicit MAC address type means ether. */
|
||||
@@ -90,10 +88,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
||||
}
|
||||
|
||||
if ((lease = lease6_allocate(&addr.addr6, lease_type)))
|
||||
{
|
||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||
domain = get_domain6(&lease->addr6);
|
||||
}
|
||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
@@ -114,7 +109,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
||||
hw_len, hw_type, clid_len, now, 0);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, NULL, NULL);
|
||||
|
||||
ei = atol(daemon->dhcp_buff3);
|
||||
|
||||
@@ -155,6 +150,10 @@ void lease_init(time_t now)
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command)
|
||||
{
|
||||
/* 6 == strlen(" init") plus terminator */
|
||||
if (strlen(daemon->lease_change_command) + 6 > DHCP_BUFF_SZ)
|
||||
die(_("lease-change script name is too long"), NULL, EC_FILE);
|
||||
|
||||
strcpy(daemon->dhcp_buff, daemon->lease_change_command);
|
||||
strcat(daemon->dhcp_buff, " init");
|
||||
leasestream = popen(daemon->dhcp_buff, "r");
|
||||
@@ -412,7 +411,7 @@ static int find_interface_v4(struct in_addr local, int if_index, char *label,
|
||||
#ifdef HAVE_DHCP6
|
||||
static int find_interface_v6(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)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
@@ -469,9 +468,9 @@ void lease_find_interfaces(time_t now)
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
lease->new_prefixlen = lease->new_interface = 0;
|
||||
|
||||
iface_enumerate(AF_INET, &now, find_interface_v4);
|
||||
iface_enumerate(AF_INET, &now, (callback_t){.af_inet=find_interface_v4});
|
||||
#ifdef HAVE_DHCP6
|
||||
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
||||
iface_enumerate(AF_INET6, &now, (callback_t){.af_inet6=find_interface_v6});
|
||||
#endif
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
@@ -946,6 +945,36 @@ static void kill_name(struct dhcp_lease *lease)
|
||||
lease->hostname = lease->fqdn = NULL;
|
||||
}
|
||||
|
||||
void lease_calc_fqdns(void)
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
for (lease = leases; lease; lease = lease->next)
|
||||
{
|
||||
char *domain;
|
||||
|
||||
if (lease->hostname)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
if (lease->flags & (LEASE_TA | LEASE_NA))
|
||||
domain = get_domain6(&lease->addr6);
|
||||
else
|
||||
#endif
|
||||
domain = get_domain(lease->addr);
|
||||
|
||||
if (domain)
|
||||
{
|
||||
/* This is called only during startup, before forking, hence safe_malloc() */
|
||||
lease->fqdn = safe_malloc(strlen(lease->hostname) + strlen(domain) + 2);
|
||||
|
||||
strcpy(lease->fqdn, lease->hostname);
|
||||
strcat(lease->fqdn, ".");
|
||||
strcat(lease->fqdn, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
|
||||
{
|
||||
struct dhcp_lease *lease_tmp;
|
||||
@@ -1180,17 +1209,11 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned
|
||||
if ((lease->extradata_size - lease->extradata_len) < (len + 1))
|
||||
{
|
||||
size_t newsz = lease->extradata_len + len + 100;
|
||||
unsigned char *new = whine_malloc(newsz);
|
||||
unsigned char *new = whine_realloc(lease->extradata, newsz);
|
||||
|
||||
if (!new)
|
||||
return;
|
||||
|
||||
if (lease->extradata)
|
||||
{
|
||||
memcpy(new, lease->extradata, lease->extradata_len);
|
||||
free(lease->extradata);
|
||||
}
|
||||
|
||||
lease->extradata = new;
|
||||
lease->extradata_size = newsz;
|
||||
}
|
||||
|
||||
25
src/log.c
25
src/log.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -100,10 +100,23 @@ int log_start(struct passwd *ent_pw, int errfd)
|
||||
/* If we're running as root and going to change uid later,
|
||||
change the ownership here so that the file is always owned by
|
||||
the dnsmasq user. Then logrotate can just copy the owner.
|
||||
Failure of the chown call is OK, (for instance when started as non-root) */
|
||||
if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 &&
|
||||
fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
ret = errno;
|
||||
Failure of the chown call is OK, (for instance when started as non-root).
|
||||
|
||||
If we've created a file with group-id root, we also make
|
||||
the file group-writable. This gives processes in the root group
|
||||
write access to the file and avoids the problem that on some systems,
|
||||
once the file is owned by the dnsmasq user, it can't be written
|
||||
whilst dnsmasq is running as root during startup.
|
||||
*/
|
||||
if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0)
|
||||
{
|
||||
struct stat ls;
|
||||
if (getgid() == 0 && fstat(log_fd, &ls) == 0 && ls.st_gid == 0 &&
|
||||
(ls.st_mode & S_IWGRP) == 0)
|
||||
(void)fchmod(log_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
if (fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
ret = errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -118,7 +131,7 @@ int log_reopen(char *log_file)
|
||||
/* NOTE: umask is set to 022 by the time this gets called */
|
||||
|
||||
if (log_file)
|
||||
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,7 +19,7 @@
|
||||
#ifdef HAVE_LOOP
|
||||
static ssize_t loop_make_probe(u32 uid);
|
||||
|
||||
void loop_send_probes()
|
||||
void loop_send_probes(void)
|
||||
{
|
||||
struct server *serv;
|
||||
struct randfd_list *rfds = NULL;
|
||||
@@ -92,7 +92,7 @@ int detect_loop(char *query, int type)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (!isxdigit(query[i]))
|
||||
if (!isxdigit((unsigned char)query[i]))
|
||||
return 0;
|
||||
|
||||
uid = strtol(query, NULL, 16);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,6 +22,11 @@ const char * metric_names[] = {
|
||||
"dns_queries_forwarded",
|
||||
"dns_auth_answered",
|
||||
"dns_local_answered",
|
||||
"dns_stale_answered",
|
||||
"dns_unanswered",
|
||||
"dnssec_max_crypto_use",
|
||||
"dnssec_max_sig_fail",
|
||||
"dnssec_max_work",
|
||||
"bootp",
|
||||
"pxe",
|
||||
"dhcp_ack",
|
||||
@@ -37,8 +42,29 @@ const char * metric_names[] = {
|
||||
"leases_pruned_4",
|
||||
"leases_allocated_6",
|
||||
"leases_pruned_6",
|
||||
"tcp_connections",
|
||||
};
|
||||
|
||||
const char* get_metric_name(int i) {
|
||||
return metric_names[i];
|
||||
}
|
||||
|
||||
void clear_metrics(void)
|
||||
{
|
||||
int i;
|
||||
struct server *serv;
|
||||
|
||||
for (i = 0; i < __METRIC_MAX; i++)
|
||||
daemon->metrics[i] = 0;
|
||||
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
{
|
||||
serv->queries = 0;
|
||||
serv->failed_queries = 0;
|
||||
serv->failed_queries = 0;
|
||||
serv->retrys = 0;
|
||||
serv->nxdomain_replies = 0;
|
||||
serv->query_latency = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -21,6 +21,11 @@ enum {
|
||||
METRIC_DNS_QUERIES_FORWARDED,
|
||||
METRIC_DNS_AUTH_ANSWERED,
|
||||
METRIC_DNS_LOCAL_ANSWERED,
|
||||
METRIC_DNS_STALE_ANSWERED,
|
||||
METRIC_DNS_UNANSWERED_QUERY,
|
||||
METRIC_CRYPTO_HWM,
|
||||
METRIC_SIG_FAIL_HWM,
|
||||
METRIC_WORK_HWM,
|
||||
METRIC_BOOTP,
|
||||
METRIC_PXE,
|
||||
METRIC_DHCPACK,
|
||||
@@ -36,8 +41,10 @@ enum {
|
||||
METRIC_LEASES_PRUNED_4,
|
||||
METRIC_LEASES_ALLOCATED_6,
|
||||
METRIC_LEASES_PRUNED_6,
|
||||
METRIC_TCP_CONNECTIONS,
|
||||
|
||||
__METRIC_MAX,
|
||||
};
|
||||
|
||||
const char* get_metric_name(int);
|
||||
void clear_metrics(void);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -66,17 +66,10 @@ char *netlink_init(void)
|
||||
addr.nl_pad = 0;
|
||||
addr.nl_pid = 0; /* autobind */
|
||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra || daemon->doing_dhcp6)
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
#endif
|
||||
|
||||
/* May not be able to have permission to set multicast groups don't die in that case */
|
||||
if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1)
|
||||
{
|
||||
@@ -158,7 +151,7 @@ static ssize_t netlink_recv(int flags)
|
||||
family = AF_LOCAL finds MAC addresses.
|
||||
returns 0 on failure, 1 on success, -1 when restart is required
|
||||
*/
|
||||
int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
int iface_enumerate(int family, void *parm, callback_t callback)
|
||||
{
|
||||
struct sockaddr_nl addr;
|
||||
struct nlmsghdr *h;
|
||||
@@ -254,7 +247,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
}
|
||||
|
||||
if (addr.s_addr && callback_ok)
|
||||
if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm)))
|
||||
if (!callback.af_inet(addr, ifa->ifa_index, label, netmask, broadcast, parm))
|
||||
callback_ok = 0;
|
||||
}
|
||||
else if (ifa->ifa_family == AF_INET6)
|
||||
@@ -265,7 +258,16 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
|
||||
while (RTA_OK(rta, len1))
|
||||
{
|
||||
if (rta->rta_type == IFA_ADDRESS)
|
||||
/*
|
||||
* Important comment: (from if_addr.h)
|
||||
* IFA_ADDRESS is prefix address, rather than local interface address.
|
||||
* It makes no difference for normally configured broadcast interfaces,
|
||||
* but for point-to-point IFA_ADDRESS is DESTINATION address,
|
||||
* local address is supplied in IFA_LOCAL attribute.
|
||||
*/
|
||||
if (rta->rta_type == IFA_LOCAL)
|
||||
addrp = ((struct in6_addr *)(rta+1));
|
||||
else if (rta->rta_type == IFA_ADDRESS && !addrp)
|
||||
addrp = ((struct in6_addr *)(rta+1));
|
||||
else if (rta->rta_type == IFA_CACHEINFO)
|
||||
{
|
||||
@@ -286,9 +288,9 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
flags |= IFACE_PERMANENT;
|
||||
|
||||
if (addrp && callback_ok)
|
||||
if (!((*callback)(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
||||
if (!callback.af_inet6(addrp, (int)(ifa->ifa_prefixlen), (int)(ifa->ifa_scope),
|
||||
(int)(ifa->ifa_index), flags,
|
||||
(int) preferred, (int)valid, parm)))
|
||||
(unsigned int)preferred, (unsigned int)valid, parm))
|
||||
callback_ok = 0;
|
||||
}
|
||||
}
|
||||
@@ -316,7 +318,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
|
||||
if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
|
||||
inaddr && mac && callback_ok)
|
||||
if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
|
||||
if (!callback.af_unspec(neigh->ndm_family, inaddr, mac, maclen, parm))
|
||||
callback_ok = 0;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
@@ -340,7 +342,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
}
|
||||
|
||||
if (mac && callback_ok && !((link->ifi_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) &&
|
||||
!((*callback)((int)link->ifi_index, (unsigned int)link->ifi_type, mac, maclen, parm)))
|
||||
!callback.af_local((int)link->ifi_index, (unsigned int)link->ifi_type, mac, maclen, parm))
|
||||
callback_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
210
src/network.c
210
src/network.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -114,13 +114,8 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
struct iname *tmp;
|
||||
int ret = 1, match_addr = 0;
|
||||
|
||||
/* Note: have to check all and not bail out early, so that we set the
|
||||
"used" flags.
|
||||
|
||||
May be called with family == AF_LOCALto check interface by name only. */
|
||||
|
||||
if (auth)
|
||||
*auth = 0;
|
||||
/* Note: have to check all and not bail out early, so that we set the "used" flags.
|
||||
May be called with family == AF_LOCAL to check interface by name only. */
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
@@ -128,7 +123,10 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
|
||||
for (tmp = daemon->if_names; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, name))
|
||||
ret = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (addr)
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
@@ -136,11 +134,17 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
{
|
||||
if (family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
ret = match_addr = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = match_addr = 1;
|
||||
}
|
||||
else if (family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||
&addr->addr6))
|
||||
ret = match_addr = tmp->used = 1;
|
||||
{
|
||||
tmp->flags |= INAME_USED;
|
||||
ret = match_addr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,25 +153,29 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
if (tmp->name && wildcard_match(tmp->name, name))
|
||||
ret = 0;
|
||||
|
||||
|
||||
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||
if (tmp->name)
|
||||
{
|
||||
if (strcmp(tmp->name, name) == 0 &&
|
||||
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
|
||||
break;
|
||||
}
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
break;
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
|
||||
break;
|
||||
|
||||
if (tmp && auth)
|
||||
if (auth)
|
||||
{
|
||||
*auth = 1;
|
||||
ret = 1;
|
||||
*auth = 0;
|
||||
|
||||
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||
if (tmp->name)
|
||||
{
|
||||
if (strcmp(tmp->name, name) == 0 &&
|
||||
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
|
||||
break;
|
||||
}
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
break;
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
|
||||
break;
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
*auth = 1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -232,10 +240,12 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
|
||||
{
|
||||
struct irec *iface;
|
||||
struct cond_domain *cond;
|
||||
int loopback;
|
||||
struct ifreq ifr;
|
||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||
int dhcp_ok = 1;
|
||||
int dhcp4_ok = 1;
|
||||
int dhcp6_ok = 1;
|
||||
int auth_dns = 0;
|
||||
int is_label = 0;
|
||||
#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
|
||||
@@ -251,7 +261,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
loopback = ifr.ifr_flags & IFF_LOOPBACK;
|
||||
|
||||
if (loopback)
|
||||
dhcp_ok = 0;
|
||||
dhcp4_ok = dhcp6_ok = 0;
|
||||
|
||||
if (!label)
|
||||
label = ifr.ifr_name;
|
||||
@@ -359,13 +369,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
struct in_addr newaddr = addr->in.sin_addr;
|
||||
|
||||
if (int_name->flags & INP4)
|
||||
{
|
||||
if (netmask.s_addr == 0xffff)
|
||||
continue;
|
||||
|
||||
newaddr.s_addr = (addr->in.sin_addr.s_addr & netmask.s_addr) |
|
||||
(int_name->proto4.s_addr & ~netmask.s_addr);
|
||||
}
|
||||
newaddr.s_addr = (addr->in.sin_addr.s_addr & netmask.s_addr) |
|
||||
(int_name->proto4.s_addr & ~netmask.s_addr);
|
||||
|
||||
/* check for duplicates. */
|
||||
for (lp = int_name->addr; lp; lp = lp->next)
|
||||
@@ -398,10 +403,6 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
{
|
||||
int i;
|
||||
|
||||
/* No sense in doing /128. */
|
||||
if (prefixlen == 128)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int bits = ((i+1)*8) - prefixlen;
|
||||
@@ -454,7 +455,37 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Update addresses for domain=<domain>,<interface> */
|
||||
for (cond = daemon->cond_domain; cond; cond = cond->next)
|
||||
if (cond->interface && strncmp(label, cond->interface, IF_NAMESIZE) == 0)
|
||||
{
|
||||
struct addrlist *al;
|
||||
|
||||
if (param->spare)
|
||||
{
|
||||
al = param->spare;
|
||||
param->spare = al->next;
|
||||
}
|
||||
else
|
||||
al = whine_malloc(sizeof(struct addrlist));
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
{
|
||||
al->addr.addr4 = addr->in.sin_addr;
|
||||
al->flags = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
al->addr.addr6 = addr->in6.sin6_addr;
|
||||
al->flags = ADDRLIST_IPV6;
|
||||
}
|
||||
|
||||
al->prefixlen = prefixlen;
|
||||
al->next = cond->al;
|
||||
cond->al = al;
|
||||
}
|
||||
|
||||
/* check whether the interface IP has been added already
|
||||
we call this routine multiple times. */
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
@@ -480,7 +511,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
if ((lo->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||
{
|
||||
strcpy(lo->name, ifr.ifr_name);
|
||||
lo->used = 1;
|
||||
lo->flags |= INAME_USED;
|
||||
lo->next = daemon->if_names;
|
||||
daemon->if_names = lo;
|
||||
}
|
||||
@@ -502,14 +533,17 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
if (auth_dns)
|
||||
{
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
dhcp4_ok = dhcp6_ok = 0;
|
||||
}
|
||||
else
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
{
|
||||
tftp_ok = 0;
|
||||
dhcp_ok = 0;
|
||||
if (tmp->flags & INAME_4)
|
||||
dhcp4_ok = 0;
|
||||
if (tmp->flags & INAME_6)
|
||||
dhcp6_ok = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -536,7 +570,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
iface->addr = *addr;
|
||||
iface->netmask = netmask;
|
||||
iface->tftp_ok = tftp_ok;
|
||||
iface->dhcp_ok = dhcp_ok;
|
||||
iface->dhcp4_ok = dhcp4_ok;
|
||||
iface->dhcp6_ok = dhcp6_ok;
|
||||
iface->dns_auth = auth_dns;
|
||||
iface->mtu = mtu;
|
||||
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
||||
@@ -561,7 +596,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
|
||||
static int iface_allowed_v6(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)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* dummy */
|
||||
@@ -612,7 +647,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||
/*
|
||||
* Clean old interfaces no longer found.
|
||||
*/
|
||||
static void clean_interfaces()
|
||||
static void clean_interfaces(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
struct irec **up = &daemon->interfaces;
|
||||
@@ -692,6 +727,7 @@ int enumerate_interfaces(int reset)
|
||||
int errsave, ret = 1;
|
||||
struct addrlist *addr, *tmp;
|
||||
struct interface_name *intname;
|
||||
struct cond_domain *cond;
|
||||
struct irec *iface;
|
||||
#ifdef HAVE_AUTH
|
||||
struct auth_zone *zone;
|
||||
@@ -751,6 +787,19 @@ again:
|
||||
intname->addr = NULL;
|
||||
}
|
||||
|
||||
/* remove addresses stored against cond-domains. */
|
||||
for (cond = daemon->cond_domain; cond; cond = cond->next)
|
||||
{
|
||||
for (addr = cond->al; addr; addr = tmp)
|
||||
{
|
||||
tmp = addr->next;
|
||||
addr->next = spare;
|
||||
spare = addr;
|
||||
}
|
||||
|
||||
cond->al = NULL;
|
||||
}
|
||||
|
||||
/* Remove list of addresses of local interfaces */
|
||||
for (addr = daemon->interface_addrs; addr; addr = tmp)
|
||||
{
|
||||
@@ -784,12 +833,12 @@ again:
|
||||
|
||||
param.spare = spare;
|
||||
|
||||
ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
|
||||
ret = iface_enumerate(AF_INET6, ¶m, (callback_t){.af_inet6=iface_allowed_v6});
|
||||
if (ret < 0)
|
||||
goto again;
|
||||
else if (ret)
|
||||
{
|
||||
ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
||||
ret = iface_enumerate(AF_INET, ¶m, (callback_t){.af_inet=iface_allowed_v4});
|
||||
if (ret < 0)
|
||||
goto again;
|
||||
}
|
||||
@@ -871,15 +920,24 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
||||
|
||||
errno = errsave;
|
||||
|
||||
if (dienow)
|
||||
/* Failure to bind addresses given by --listen-address at this point
|
||||
because there's no interface with the address is OK if we're doing bind-dynamic.
|
||||
If/when an interface is created with the relevant address we'll notice
|
||||
and attempt to bind it then. This is in the generic error path so we close the socket,
|
||||
but EADDRNOTAVAIL is only a possible error from bind()
|
||||
|
||||
When a new address is created and we call this code again (dienow == 0) there
|
||||
may still be configured addresses when don't exist, (consider >1 --listen-address,
|
||||
when the first is created, the second will still be missing) so we suppress
|
||||
EADDRNOTAVAIL even in that case to avoid confusing log entries.
|
||||
*/
|
||||
if (!option_bool(OPT_CLEVERBIND) || errno != EADDRNOTAVAIL)
|
||||
{
|
||||
/* failure to bind addresses given by --listen-address at this point
|
||||
is OK if we're doing bind-dynamic */
|
||||
if (!option_bool(OPT_CLEVERBIND))
|
||||
if (dienow)
|
||||
die(s, daemon->addrbuff, EC_BADNET);
|
||||
else
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
}
|
||||
else
|
||||
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -1163,7 +1221,7 @@ void create_bound_listeners(int dienow)
|
||||
(no netmask) and some MTU login the tftp code. */
|
||||
|
||||
for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
|
||||
if (!if_tmp->used &&
|
||||
if (!(if_tmp->flags & INAME_USED) &&
|
||||
(new = create_listeners(&if_tmp->addr, !!option_bool(OPT_TFTP), dienow)))
|
||||
{
|
||||
new->next = daemon->listeners;
|
||||
@@ -1251,7 +1309,7 @@ void join_multicast(int dienow)
|
||||
struct irec *iface, *tmp;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp_ok && !iface->multicast_done)
|
||||
if (iface->addr.sa.sa_family == AF_INET6 && iface->dhcp6_ok && !iface->multicast_done)
|
||||
{
|
||||
/* There's an irec per address but we only want to join for multicast
|
||||
once per interface. Weed out duplicates. */
|
||||
@@ -1327,7 +1385,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
|
||||
or both are set. Otherwise use the OS's random ephemeral port allocation by
|
||||
leaving port == 0 and tries == 1 */
|
||||
ports_avail = daemon->max_port - daemon->min_port + 1;
|
||||
tries = ports_avail < 30 ? 3 * ports_avail : 100;
|
||||
tries = (ports_avail < SMALL_PORT_RANGE) ? ports_avail : 100;
|
||||
port = htons(daemon->min_port + (rand16() % ports_avail));
|
||||
}
|
||||
|
||||
@@ -1356,7 +1414,16 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
|
||||
if (--tries == 0)
|
||||
return 0;
|
||||
|
||||
port = htons(daemon->min_port + (rand16() % ports_avail));
|
||||
/* For small ranges, do a systematic search, not a random one. */
|
||||
if (ports_avail < SMALL_PORT_RANGE)
|
||||
{
|
||||
unsigned short hport = ntohs(port);
|
||||
if (hport++ == daemon->max_port)
|
||||
hport = daemon->min_port;
|
||||
port = htons(hport);
|
||||
}
|
||||
else
|
||||
port = htons(daemon->min_port + (rand16() % ports_avail));
|
||||
}
|
||||
|
||||
if (!is_tcp && ifindex > 0)
|
||||
@@ -1520,10 +1587,6 @@ void check_servers(int no_loop_check)
|
||||
|
||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||
{
|
||||
/* Init edns_pktsz for newly created server records. */
|
||||
if (serv->edns_pktsz == 0)
|
||||
serv->edns_pktsz = daemon->edns_pktsz;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
{
|
||||
@@ -1586,6 +1649,9 @@ void check_servers(int no_loop_check)
|
||||
if (serv->sfd)
|
||||
serv->sfd->used = 1;
|
||||
|
||||
if (count == SERVERS_LOGGED)
|
||||
my_syslog(LOG_INFO, _("more servers are defined but not logged"));
|
||||
|
||||
if (++count > SERVERS_LOGGED)
|
||||
continue;
|
||||
|
||||
@@ -1623,7 +1689,8 @@ void check_servers(int no_loop_check)
|
||||
continue;
|
||||
|
||||
if ((serv->flags & SERV_LITERAL_ADDRESS) &&
|
||||
!(serv->flags & (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)))
|
||||
!(serv->flags & (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)) &&
|
||||
strlen(serv->domain))
|
||||
{
|
||||
count--;
|
||||
if (++locals <= LOCALS_LOGGED)
|
||||
@@ -1739,6 +1806,8 @@ int reload_servers(char *fname)
|
||||
/* Called when addresses are added or deleted from an interface */
|
||||
void newaddress(time_t now)
|
||||
{
|
||||
struct dhcp_relay *relay;
|
||||
|
||||
(void)now;
|
||||
|
||||
if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
|
||||
@@ -1747,6 +1816,12 @@ void newaddress(time_t now)
|
||||
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
create_bound_listeners(0);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* clear cache of subnet->relay index */
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
relay->iface_index = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
|
||||
@@ -1757,5 +1832,8 @@ void newaddress(time_t now)
|
||||
|
||||
if (daemon->doing_dhcp6)
|
||||
lease_find_interfaces(now);
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
relay->iface_index = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
100
src/nftset.c
Normal file
100
src/nftset.c
Normal file
@@ -0,0 +1,100 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2024 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined (HAVE_NFTSET) && defined (HAVE_LINUX_NETWORK)
|
||||
|
||||
#include <nftables/libnftables.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
static struct nft_ctx *ctx = NULL;
|
||||
static const char *cmd_add = "add element %s { %s }";
|
||||
static const char *cmd_del = "delete element %s { %s }";
|
||||
|
||||
void nftset_init()
|
||||
{
|
||||
ctx = nft_ctx_new(NFT_CTX_DEFAULT);
|
||||
if (ctx == NULL)
|
||||
die(_("failed to create nftset context"), NULL, EC_MISC);
|
||||
|
||||
/* disable libnftables output */
|
||||
nft_ctx_buffer_error(ctx);
|
||||
}
|
||||
|
||||
int add_to_nftset(const char *setname, const union all_addr *ipaddr, int flags, int remove)
|
||||
{
|
||||
const char *cmd = remove ? cmd_del : cmd_add;
|
||||
int ret, af = (flags & F_IPV4) ? AF_INET : AF_INET6;
|
||||
size_t new_sz;
|
||||
char *err_str, *new, *nl;
|
||||
const char *err;
|
||||
static char *cmd_buf = NULL;
|
||||
static size_t cmd_buf_sz = 0;
|
||||
|
||||
inet_ntop(af, ipaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||
|
||||
if (setname[1] == ' ' && (setname[0] == '4' || setname[0] == '6'))
|
||||
{
|
||||
if (setname[0] == '4' && !(flags & F_IPV4))
|
||||
return -1;
|
||||
|
||||
if (setname[0] == '6' && !(flags & F_IPV6))
|
||||
return -1;
|
||||
|
||||
setname += 2;
|
||||
}
|
||||
|
||||
if (cmd_buf_sz == 0)
|
||||
new_sz = 150; /* initial allocation */
|
||||
else
|
||||
new_sz = snprintf(cmd_buf, cmd_buf_sz, cmd, setname, daemon->addrbuff);
|
||||
|
||||
if (new_sz > cmd_buf_sz)
|
||||
{
|
||||
if (!(new = whine_malloc(new_sz + 10)))
|
||||
return 0;
|
||||
|
||||
if (cmd_buf)
|
||||
free(cmd_buf);
|
||||
cmd_buf = new;
|
||||
cmd_buf_sz = new_sz + 10;
|
||||
snprintf(cmd_buf, cmd_buf_sz, cmd, setname, daemon->addrbuff);
|
||||
}
|
||||
|
||||
ret = nft_run_cmd_from_buffer(ctx, cmd_buf);
|
||||
err = nft_ctx_get_error_buffer(ctx);
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
/* Log only first line of error return. */
|
||||
if ((err_str = whine_malloc(strlen(err) + 1)))
|
||||
{
|
||||
strcpy(err_str, err);
|
||||
if ((nl = strchr(err_str, '\n')))
|
||||
*nl = 0;
|
||||
my_syslog(LOG_ERR, "nftset %s %s", setname, err_str);
|
||||
free(err_str);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
1631
src/option.c
1631
src/option.c
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -23,7 +23,7 @@ static size_t outpacket_counter;
|
||||
|
||||
void end_opt6(int container)
|
||||
{
|
||||
void *p = daemon->outpacket.iov_base + container + 2;
|
||||
uint8_t *p = (uint8_t *)daemon->outpacket.iov_base + container + 2;
|
||||
u16 len = outpacket_counter - container - 4 ;
|
||||
|
||||
PUTSHORT(len, p);
|
||||
@@ -50,11 +50,11 @@ int save_counter(int newval)
|
||||
|
||||
void *expand(size_t headroom)
|
||||
{
|
||||
void *ret;
|
||||
uint8_t *ret;
|
||||
|
||||
if (expand_buf(&daemon->outpacket, outpacket_counter + headroom))
|
||||
{
|
||||
ret = daemon->outpacket.iov_base + outpacket_counter;
|
||||
ret = (uint8_t *)daemon->outpacket.iov_base + outpacket_counter;
|
||||
outpacket_counter += headroom;
|
||||
return ret;
|
||||
}
|
||||
@@ -65,7 +65,7 @@ void *expand(size_t headroom)
|
||||
int new_opt6(int opt)
|
||||
{
|
||||
int ret = outpacket_counter;
|
||||
void *p;
|
||||
unsigned char *p;
|
||||
|
||||
if ((p = expand(4)))
|
||||
{
|
||||
@@ -88,7 +88,7 @@ void *put_opt6(void *data, size_t len)
|
||||
|
||||
void put_opt6_long(unsigned int val)
|
||||
{
|
||||
void *p;
|
||||
unsigned char *p;
|
||||
|
||||
if ((p = expand(4)))
|
||||
PUTLONG(val, p);
|
||||
@@ -96,7 +96,7 @@ void put_opt6_long(unsigned int val)
|
||||
|
||||
void put_opt6_short(unsigned int val)
|
||||
{
|
||||
void *p;
|
||||
uint8_t *p;
|
||||
|
||||
if ((p = expand(2)))
|
||||
PUTSHORT(val, p);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -129,9 +129,9 @@ int is_valid_dns_name(const char *value)
|
||||
|
||||
size_t num_bytes = 0;
|
||||
size_t num_labels = 0;
|
||||
const char *label = NULL;
|
||||
const char *c, *label = NULL;
|
||||
int is_label_numeric = 1;
|
||||
for (const char *c = value;; c++)
|
||||
for (c = value;; c++)
|
||||
{
|
||||
if (*c &&
|
||||
*c != '-' && *c != '.' &&
|
||||
@@ -242,11 +242,11 @@ int is_valid_dns_name_pattern(const char *value)
|
||||
|
||||
size_t num_bytes = 0;
|
||||
size_t num_labels = 0;
|
||||
const char *label = NULL;
|
||||
const char *c, *label = NULL;
|
||||
int is_label_numeric = 1;
|
||||
size_t num_wildcards = 0;
|
||||
int previous_label_has_wildcard = 1;
|
||||
for (const char *c = value;; c++)
|
||||
for (c = value;; c++)
|
||||
{
|
||||
if (*c &&
|
||||
*c != '*' && /* Wildcard. */
|
||||
|
||||
19
src/poll.c
19
src/poll.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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,28 +96,21 @@ void poll_listen(int fd, short event)
|
||||
pollfds[i].events |= event;
|
||||
else
|
||||
{
|
||||
if (arrsize != nfds)
|
||||
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
else
|
||||
if (arrsize == nfds)
|
||||
{
|
||||
/* Array too small, extend. */
|
||||
struct pollfd *new;
|
||||
|
||||
arrsize = (arrsize == 0) ? 64 : arrsize * 2;
|
||||
|
||||
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
|
||||
if (!(new = whine_realloc(pollfds, arrsize * sizeof(struct pollfd))))
|
||||
return;
|
||||
|
||||
if (pollfds)
|
||||
{
|
||||
memcpy(new, pollfds, i * sizeof(struct pollfd));
|
||||
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
free(pollfds);
|
||||
}
|
||||
|
||||
pollfds = new;
|
||||
}
|
||||
|
||||
|
||||
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
|
||||
pollfds[i].fd = fd;
|
||||
pollfds[i].events = event;
|
||||
nfds++;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
|
||||
75
src/radv.c
75
src/radv.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2024 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
|
||||
@@ -58,7 +58,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
unsigned int preferred, unsigned int valid, void *vparam);
|
||||
static int iface_search(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
int prefered, int valid, void *vparam);
|
||||
unsigned int prefered, unsigned int valid, void *vparam);
|
||||
static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||
static void new_timeout(struct dhcp_context *context, char *iface_name, time_t now);
|
||||
static unsigned int calc_lifetime(struct ra_interface *ra);
|
||||
@@ -123,7 +123,11 @@ void ra_start_unsolicited(time_t now, struct dhcp_context *context)
|
||||
and pick up new interfaces */
|
||||
|
||||
if (context)
|
||||
context->ra_short_period_start = context->ra_time = now;
|
||||
{
|
||||
context->ra_short_period_start = now;
|
||||
/* start after 1 second to get logging right at startup. */
|
||||
context->ra_time = now + 1;
|
||||
}
|
||||
else
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||
@@ -162,7 +166,7 @@ void icmp6_packet(time_t now)
|
||||
return;
|
||||
|
||||
packet = (unsigned char *)daemon->outpacket.iov_base;
|
||||
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
@@ -182,29 +186,42 @@ void icmp6_packet(time_t now)
|
||||
return;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, interface))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, interface))
|
||||
return;
|
||||
|
||||
if (packet[1] != 0)
|
||||
return;
|
||||
|
||||
|
||||
if (packet[0] == ICMP6_ECHO_REPLY)
|
||||
lease_ping_reply(&from.sin6_addr, packet, interface);
|
||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||
{
|
||||
char *mac = "";
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
ssize_t rem;
|
||||
unsigned char *p;
|
||||
int opt_sz;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
|
||||
#endif
|
||||
|
||||
/* look for link-layer address option for logging */
|
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||
for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz)
|
||||
{
|
||||
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||
return;
|
||||
}
|
||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||
mac = daemon->namebuff;
|
||||
opt_sz = p[1] * 8;
|
||||
|
||||
if (opt_sz == 0 || opt_sz > rem)
|
||||
return; /* Bad packet */
|
||||
|
||||
if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME))
|
||||
{
|
||||
print_mac(daemon->namebuff, &p[2], opt_sz - 2);
|
||||
mac = daemon->namebuff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||
|
||||
@@ -290,7 +307,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
|
||||
/* If no link-local address then we can't advertise since source address of
|
||||
advertisement must be link local address: RFC 4861 para 6.1.2. */
|
||||
if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
|
||||
if (!iface_enumerate(AF_INET6, &parm, (callback_t){.af_inet6=add_prefixes}) ||
|
||||
parm.link_pref_time == 0)
|
||||
return;
|
||||
|
||||
@@ -432,10 +449,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
put_opt6_long(mtu);
|
||||
}
|
||||
|
||||
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
|
||||
iface_enumerate(AF_LOCAL, &send_iface, (callback_t){.af_local=add_lla});
|
||||
|
||||
/* RDNSS, RFC 6106, use relevant DHCP6 options */
|
||||
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6);
|
||||
(void)option_filter(parm.tags, NULL, daemon->dhcp_opts6, 0);
|
||||
|
||||
for (opt_cfg = daemon->dhcp_opts6; opt_cfg; opt_cfg = opt_cfg->next)
|
||||
{
|
||||
@@ -543,6 +560,16 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
{
|
||||
struct sockaddr_in6 src;
|
||||
src.sin6_family = AF_INET6;
|
||||
src.sin6_addr = parm.link_local;
|
||||
|
||||
dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&addr,
|
||||
sizeof(addr))));
|
||||
@@ -746,6 +773,8 @@ static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void
|
||||
add 7 to round up */
|
||||
int len = (maclen + 9) >> 3;
|
||||
unsigned char *p = expand(len << 3);
|
||||
if (!p)
|
||||
return 1;
|
||||
memset(p, 0, len << 3);
|
||||
*p++ = ICMP6_OPT_SOURCE_MAC;
|
||||
*p++ = len;
|
||||
@@ -794,7 +823,7 @@ time_t periodic_ra(time_t now)
|
||||
param.iface = context->if_index;
|
||||
new_timeout(context, param.name, now);
|
||||
}
|
||||
else if (iface_enumerate(AF_INET6, ¶m, iface_search))
|
||||
else if (iface_enumerate(AF_INET6, ¶m, (callback_t){.af_inet6=iface_search}))
|
||||
/* There's a context overdue, but we can't find an interface
|
||||
associated with it, because it's for a subnet we dont
|
||||
have an interface on. Probably we're doing DHCP on
|
||||
@@ -807,7 +836,8 @@ time_t periodic_ra(time_t now)
|
||||
{
|
||||
struct iname *tmp;
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, param.name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, param.name))
|
||||
break;
|
||||
if (!tmp)
|
||||
{
|
||||
@@ -826,7 +856,7 @@ time_t periodic_ra(time_t now)
|
||||
aparam.iface = param.iface;
|
||||
aparam.alias_ifs = NULL;
|
||||
aparam.num_alias_ifs = 0;
|
||||
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
|
||||
iface_enumerate(AF_LOCAL, &aparam, (callback_t){.af_local=send_ra_to_aliases});
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => %d alias(es)",
|
||||
param.name, daemon->addrbuff, aparam.num_alias_ifs);
|
||||
|
||||
@@ -841,7 +871,7 @@ time_t periodic_ra(time_t now)
|
||||
those. */
|
||||
aparam.max_alias_ifs = aparam.num_alias_ifs;
|
||||
aparam.num_alias_ifs = 0;
|
||||
iface_enumerate(AF_LOCAL, &aparam, send_ra_to_aliases);
|
||||
iface_enumerate(AF_LOCAL, &aparam, (callback_t){.af_local=send_ra_to_aliases});
|
||||
for (; aparam.num_alias_ifs; aparam.num_alias_ifs--)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-ADVERT(%s) %s => i/f %d",
|
||||
@@ -890,7 +920,7 @@ static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t ma
|
||||
|
||||
static int iface_search(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)
|
||||
{
|
||||
struct search_param *param = vparam;
|
||||
struct dhcp_context *context;
|
||||
@@ -906,7 +936,8 @@ static int iface_search(struct in6_addr *local, int prefix,
|
||||
return 1;
|
||||
|
||||
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, param->name))
|
||||
if (tmp->name && (tmp->flags & INAME_6) &&
|
||||
wildcard_match(tmp->name, param->name))
|
||||
return 1;
|
||||
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user