mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
275
Commits
v2.69test5
...
v2.74test2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b842bc97bb | ||
|
|
0f38fa05a6 | ||
|
|
45c5cb1f8f | ||
|
|
f6d6956261 | ||
|
|
60176c7bf4 | ||
|
|
362c9303da | ||
|
|
5e95a552ee | ||
|
|
90cb222551 | ||
|
|
850163288d | ||
|
|
e3ec6f0bd7 | ||
|
|
f7bfbdc872 | ||
|
|
4918bd5505 | ||
|
|
9bad339af8 | ||
|
|
ba4fc0f996 | ||
|
|
2fd5bc952d | ||
|
|
0ddb8769bb | ||
|
|
654f59e762 | ||
|
|
d91b1fd402 | ||
|
|
c6d82c9ba6 | ||
|
|
4d25cf89d5 | ||
|
|
24e9207e13 | ||
|
|
89130d91d6 | ||
|
|
d644b2a17d | ||
|
|
bd7bfa21c4 | ||
|
|
403de05925 | ||
|
|
46c89f2bd0 | ||
|
|
23facf0d77 | ||
|
|
549b1a478c | ||
|
|
7f8565b94c | ||
|
|
06568c6636 | ||
|
|
5d07d77e75 | ||
|
|
62018e1f72 | ||
|
|
7c0f2543a7 | ||
|
|
ca85a28241 | ||
|
|
585840b033 | ||
|
|
dec180ac00 | ||
|
|
86fa104692 | ||
|
|
b059c96dc6 | ||
|
|
a77cec8d58 | ||
|
|
64bcff1c7c | ||
|
|
2ed162ac20 | ||
|
|
e66b4dff3c | ||
|
|
8efd731cc4 | ||
|
|
a5ae1f8587 | ||
|
|
b8f16556d3 | ||
|
|
cbe379ad6b | ||
|
|
338b340be9 | ||
|
|
a006eb7e14 | ||
|
|
554b580e97 | ||
|
|
0df29f5e23 | ||
|
|
b4c0f092d8 | ||
|
|
78c6184752 | ||
|
|
38440b204d | ||
|
|
ad4a8ff7d9 | ||
|
|
04b0ac0537 | ||
|
|
982faf4024 | ||
|
|
fe3992f9fa | ||
|
|
7aa970e2c7 | ||
|
|
30d0879ed5 | ||
|
|
fd6ad9e481 | ||
|
|
794fccca7f | ||
|
|
394ff492da | ||
|
|
1e153945de | ||
|
|
0b8a5a30a7 | ||
|
|
150162bc37 | ||
|
|
8805283088 | ||
|
|
65c7212000 | ||
|
|
979fe86bc8 | ||
|
|
ff841ebf5a | ||
|
|
360f2513ab | ||
|
|
4c960fa90a | ||
|
|
9003b50b13 | ||
|
|
f6e62e2af9 | ||
|
|
47b9ac59c7 | ||
|
|
0705a7e2d5 | ||
|
|
28b879ac47 | ||
|
|
caeea190f1 | ||
|
|
8ff70de618 | ||
|
|
ee4d1cea92 | ||
|
|
f4f400776b | ||
|
|
b467a454b4 | ||
|
|
efb8b5566a | ||
|
|
f9c863708c | ||
|
|
2941d3ac89 | ||
|
|
d36b732c4c | ||
|
|
d2c5458e31 | ||
|
|
8d8a54ec79 | ||
|
|
1062667618 | ||
|
|
6ef15b34ca | ||
|
|
3d04f46334 | ||
|
|
aff3396280 | ||
|
|
70d1873dd9 | ||
|
|
0491805d2f | ||
|
|
61b838dd57 | ||
|
|
fbf01f7046 | ||
|
|
5f4dc5c6ca | ||
|
|
2ae195f5a7 | ||
|
|
393415597c | ||
|
|
ae4624bf46 | ||
|
|
5e321739db | ||
|
|
9f79ee4ae3 | ||
|
|
28de38768e | ||
|
|
25cf5e373e | ||
|
|
424c4a8a53 | ||
|
|
97e618a0e3 | ||
|
|
d8dbd903d0 | ||
|
|
81c538efce | ||
|
|
d310ab7ecb | ||
|
|
0b1008d367 | ||
|
|
32fc6dbe03 | ||
|
|
83d2ed09fc | ||
|
|
fbc5205702 | ||
|
|
cbc6524234 | ||
|
|
094b5c3d90 | ||
|
|
3267804598 | ||
|
|
476693678e | ||
|
|
bd9520b7ad | ||
|
|
3ad3f3bbd4 | ||
|
|
ad946d555d | ||
|
|
800c5cc1e7 | ||
|
|
857973e6f7 | ||
|
|
9c448c8018 | ||
|
|
193de4abf5 | ||
|
|
98906275a0 | ||
|
|
b9ff5c8f43 | ||
|
|
3d9d2dd001 | ||
|
|
17b475912f | ||
|
|
e9828b6f66 | ||
|
|
72eba2bffc | ||
|
|
6ac3bc0452 | ||
|
|
00cd9d5519 | ||
|
|
f2658275b2 | ||
|
|
25e27235dd | ||
|
|
bf2db4b084 | ||
|
|
5782649ad9 | ||
|
|
288df49c96 | ||
|
|
10cfc0ddb3 | ||
|
|
15b1b7e9c3 | ||
|
|
00c0f69aa5 | ||
|
|
51943369e3 | ||
|
|
2d75f2e4a5 | ||
|
|
976afc93e4 | ||
|
|
7f68f82146 | ||
|
|
85900a246c | ||
|
|
b4f971a081 | ||
|
|
3e1551a1de | ||
|
|
af292dae6d | ||
|
|
933878f2c8 | ||
|
|
d54409dcd3 | ||
|
|
5bf50af2d0 | ||
|
|
c43b8a6326 | ||
|
|
b06900d1a3 | ||
|
|
f2f02fc3fb | ||
|
|
aaeea9f6ed | ||
|
|
2bb6f7735f | ||
|
|
40766e55e8 | ||
|
|
b5ea1cc255 | ||
|
|
6d8e8ac0fa | ||
|
|
24b167ada8 | ||
|
|
993f8cbb1b | ||
|
|
47a9516980 | ||
|
|
dc8a1b1bcf | ||
|
|
cdb755c5f1 | ||
|
|
063efb330a | ||
|
|
70772c9091 | ||
|
|
10d8540f62 | ||
|
|
006c162382 | ||
|
|
6799a46605 | ||
|
|
c4638f9e66 | ||
|
|
4b34f5d22f | ||
|
|
a0358e5ddb | ||
|
|
a03f8d4c37 | ||
|
|
c4a0937683 | ||
|
|
2f4c4b6076 | ||
|
|
a008a843cf | ||
|
|
d92c53e700 | ||
|
|
a754e1d7b2 | ||
|
|
8e9ffba66e | ||
|
|
15a97ad6fb | ||
|
|
91f4a5e4b5 | ||
|
|
0fa7e62947 | ||
|
|
62f992f06c | ||
|
|
a23949d44d | ||
|
|
b692f23466 | ||
|
|
8aa999ef69 | ||
|
|
20b215f293 | ||
|
|
e6096e643a | ||
|
|
8938ae05ac | ||
|
|
9d1b22aac2 | ||
|
|
1fc02680af | ||
|
|
4872aa747b | ||
|
|
7ea3d3fdca | ||
|
|
50f86ce8e4 | ||
|
|
7e22cf28f8 | ||
|
|
3b1b3e9d50 | ||
|
|
ab72091de2 | ||
|
|
66f57867d8 | ||
|
|
6375838445 | ||
|
|
82a14af5e7 | ||
|
|
97dce08ed7 | ||
|
|
198d940af6 | ||
|
|
1d7e0a36e3 | ||
|
|
10068600f8 | ||
|
|
b7639d5815 | ||
|
|
49752b90d5 | ||
|
|
e98bd52e25 | ||
|
|
8a8bbad0cf | ||
|
|
fec216df32 | ||
|
|
4e1fe44428 | ||
|
|
51967f9807 | ||
|
|
b37f8b99ae | ||
|
|
fc2833f172 | ||
|
|
490f90758d | ||
|
|
56618c31f6 | ||
|
|
604f7598c2 | ||
|
|
2a7a2b84ec | ||
|
|
3e21a1a6fa | ||
|
|
2b29191e7c | ||
|
|
03431d6373 | ||
|
|
cc1a29e250 | ||
|
|
e62e9b6187 | ||
|
|
19c51cfa49 | ||
|
|
d5082158ee | ||
|
|
3f7483e816 | ||
|
|
0c8584eabc | ||
|
|
f00690f93e | ||
|
|
89b12ed35b | ||
|
|
1a9a3489ec | ||
|
|
c8a80487cd | ||
|
|
4ea8e80dd9 | ||
|
|
c07d30dcb1 | ||
|
|
d588ab54d4 | ||
|
|
f8b422a7b6 | ||
|
|
29fe922b14 | ||
|
|
8707019237 | ||
|
|
d1fbb77e0f | ||
|
|
1fbe4d2f5f | ||
|
|
0575610fa1 | ||
|
|
e3f1455850 | ||
|
|
bd9b3cf55b | ||
|
|
14db4212ab | ||
|
|
00a5b5d477 | ||
|
|
b8eac19177 | ||
|
|
b47b04c846 | ||
|
|
613ad15d02 | ||
|
|
24187530fb | ||
|
|
a857daa351 | ||
|
|
f01d7be6c6 | ||
|
|
d387380a25 | ||
|
|
f2e4c277c4 | ||
|
|
5107ace14a | ||
|
|
7b1eae4f50 | ||
|
|
c152dc8492 | ||
|
|
7bcca0060f | ||
|
|
d68c2ca2b7 | ||
|
|
de73a497ca | ||
|
|
e3ec15af10 | ||
|
|
dac74312da | ||
|
|
2ecd9bd5c0 | ||
|
|
a0ab18f6eb | ||
|
|
ebe95a831f | ||
|
|
ee4158678a | ||
|
|
83349b8aa4 | ||
|
|
7fa836e105 | ||
|
|
1633e30834 | ||
|
|
c8ca33f810 | ||
|
|
e243c072b5 | ||
|
|
da4f372271 | ||
|
|
610e782a29 | ||
|
|
854cf26907 | ||
|
|
bb201c211a | ||
|
|
12fae49fff | ||
|
|
fd372273bd | ||
|
|
b98d22c191 | ||
|
|
160f6507c3 |
No files matched your search
+1
-1
@@ -3,7 +3,7 @@ src/*.mo
|
|||||||
src/dnsmasq.pot
|
src/dnsmasq.pot
|
||||||
src/dnsmasq
|
src/dnsmasq
|
||||||
src/dnsmasq_baseline
|
src/dnsmasq_baseline
|
||||||
src/.configured
|
src/.copts_*
|
||||||
contrib/wrt/dhcp_lease_time
|
contrib/wrt/dhcp_lease_time
|
||||||
contrib/wrt/dhcp_release
|
contrib/wrt/dhcp_release
|
||||||
debian/base/
|
debian/base/
|
||||||
|
|||||||
@@ -1,3 +1,220 @@
|
|||||||
|
version 2.74
|
||||||
|
Fix reversion in 2.73 where --conf-file would attempt to
|
||||||
|
read the default file, rather than no file.
|
||||||
|
|
||||||
|
Fix inotify code to handle dangling symlinks better and
|
||||||
|
not SEGV in some circumstances.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.73
|
||||||
|
Fix crash at startup when an empty suffix is supplied to
|
||||||
|
--conf-dir, also trivial memory leak. Thanks to
|
||||||
|
Tomas Hozza for spotting this.
|
||||||
|
|
||||||
|
Remove floor of 4096 on advertised EDNS0 packet size when
|
||||||
|
DNSSEC in use, the original rationale for this has long gone.
|
||||||
|
Thanks to Anders Kaseorg for spotting this.
|
||||||
|
|
||||||
|
Use inotify for checking on updates to /etc/resolv.conf and
|
||||||
|
friends under Linux. This fixes race conditions when the files are
|
||||||
|
updated rapidly and saves CPU by noy polling. To build
|
||||||
|
a binary that runs on old Linux kernels without inotify,
|
||||||
|
use make COPTS=-DNO_INOTIFY
|
||||||
|
|
||||||
|
Fix breakage of --domain=<domain>,<subnet>,local - only reverse
|
||||||
|
queries were intercepted. THis appears to have been broken
|
||||||
|
since 2.69. Thanks to Josh Stone for finding the bug.
|
||||||
|
|
||||||
|
Eliminate IPv6 privacy addresses and deprecated addresses from
|
||||||
|
the answers given by --interface-name. Note that reverse queries
|
||||||
|
(ie looking for names, given addresses) are not affected.
|
||||||
|
Thanks to Michael Gorbach for the suggestion.
|
||||||
|
|
||||||
|
Fix crash in DNSSEC code with long RRs. Thanks to Marco Davids
|
||||||
|
for the bug report.
|
||||||
|
|
||||||
|
Add --ignore-address option. Ignore replies to A-record
|
||||||
|
queries which include the specified address. No error is
|
||||||
|
generated, dnsmasq simply continues to listen for another
|
||||||
|
reply. This is useful to defeat blocking strategies which
|
||||||
|
rely on quickly supplying a forged answer to a DNS
|
||||||
|
request for certain domains, before the correct answer can
|
||||||
|
arrive. Thanks to Glen Huang for the patch.
|
||||||
|
|
||||||
|
Revisit the part of DNSSEC validation which determines if an
|
||||||
|
unsigned answer is legit, or is in some part of the DNS
|
||||||
|
tree which should be signed. Dnsmasq now works from the
|
||||||
|
DNS root downward looking for the limit of signed
|
||||||
|
delegations, rather than working bottom up. This is
|
||||||
|
both more correct, and less likely to trip over broken
|
||||||
|
nameservers in the unsigned parts of the DNS tree
|
||||||
|
which don't respond well to DNSSEC queries.
|
||||||
|
|
||||||
|
Add --log-queries=extra option, which makes logs easier
|
||||||
|
to search automatically.
|
||||||
|
|
||||||
|
Add --min-cache-ttl option. I've resisted this for a long
|
||||||
|
time, on the grounds that disbelieving TTLs is never a
|
||||||
|
good idea, but I've been persuaded that there are
|
||||||
|
sometimes reasons to do it. (Step forward, GFW).
|
||||||
|
To avoid misuse, there's a hard limit on the TTL
|
||||||
|
floor of one hour. Thansk to RinSatsuki for the patch.
|
||||||
|
|
||||||
|
Cope with multiple interfaces with the same link-local
|
||||||
|
address. (IPv6 addresses are scoped, so this is allowed.)
|
||||||
|
Thanks to Cory Benfield for help with this.
|
||||||
|
|
||||||
|
Add --dhcp-hostsdir. This allows addition of new host
|
||||||
|
configurations to a running dnsmasq instance much more
|
||||||
|
cheaply than having dnsmasq re-read all its existing
|
||||||
|
configuration each time.
|
||||||
|
|
||||||
|
Don't reply to DHCPv6 SOLICIT messages if we're not
|
||||||
|
configured to do stateful DHCPv6. Thanks to Win King Wan
|
||||||
|
for the patch.
|
||||||
|
|
||||||
|
Fix broken DNSSEC validation of ECDSA signatures.
|
||||||
|
|
||||||
|
Add --dnssec-timestamp option, which provides an automatic
|
||||||
|
way to detect when the system time becomes valid after
|
||||||
|
boot on systems without an RTC, whilst allowing DNS
|
||||||
|
queries before the clock is valid so that NTP can run.
|
||||||
|
Thanks to Kevin Darbyshire-Bryant for developing this idea.
|
||||||
|
|
||||||
|
Add --tftp-no-fail option. Thanks to Stefan Tomanek for
|
||||||
|
the patch.
|
||||||
|
|
||||||
|
Fix crash caused by looking up servers.bind, CHAOS text
|
||||||
|
record, when more than about five --servers= lines are
|
||||||
|
in the dnsmasq config. This causes memory corruption
|
||||||
|
which causes a crash later. Thanks to Matt Coddington for
|
||||||
|
sterling work chasing this down.
|
||||||
|
|
||||||
|
Fix crash on receipt of certain malformed DNS requests.
|
||||||
|
Thanks to Nick Sampanis for spotting the problem.
|
||||||
|
Note that this is could allow the dnsmasq process's
|
||||||
|
memory to be read by an attacker under certain
|
||||||
|
circumstances, so it has a CVE, CVE-2015-3294
|
||||||
|
|
||||||
|
Fix crash in authoritative DNS code, if a .arpa zone
|
||||||
|
is declared as authoritative, and then a PTR query which
|
||||||
|
is not to be treated as authoritative arrived. Normally,
|
||||||
|
directly declaring .arpa zone as authoritative is not
|
||||||
|
done, so this crash wouldn't be seen. Instead the
|
||||||
|
relevant .arpa zone should be specified as a subnet
|
||||||
|
in the auth-zone declaration. Thanks to Johnny S. Lee
|
||||||
|
for the bugreport and initial patch.
|
||||||
|
|
||||||
|
Fix authoritative DNS code to correctly reply to NS
|
||||||
|
and SOA queries for .arpa zones for which we are
|
||||||
|
declared authoritative by means of a subnet in auth-zone.
|
||||||
|
Previously we provided correct answers to PTR queries
|
||||||
|
in such zones (including NS and SOA) but not direct
|
||||||
|
NS and SOA queries. Thanks to Johnny S. Lee for
|
||||||
|
pointing out the problem.
|
||||||
|
|
||||||
|
Fix logging of DHCPREPLY which should be suppressed
|
||||||
|
by quiet-dhcp6. Thanks to J. Pablo Abonia for
|
||||||
|
spotting the problem.
|
||||||
|
|
||||||
|
Try and handle net connections with broken fragmentation
|
||||||
|
that lose large UDP packets. If a server times out,
|
||||||
|
reduce the maximum UDP packet size field in the EDNS0
|
||||||
|
header to 1280 bytes. If it then answers, make that
|
||||||
|
change permanent.
|
||||||
|
|
||||||
|
Check IPv4-mapped IPv6 addresses when --stop-rebind
|
||||||
|
is active. Thanks to Jordan Milne for spotting this.
|
||||||
|
|
||||||
|
Allow DHCPv4 options T1 and T2 to be set using --dhcp-option.
|
||||||
|
Thanks to Kevin Benton for patches and work on this.
|
||||||
|
|
||||||
|
Fix code for DHCPCONFIRM DHCPv6 messages to confirm addresses
|
||||||
|
in the correct subnet, even of not in dynamic address
|
||||||
|
allocation range. Thanks to Steve Hirsch for spotting
|
||||||
|
the problem.
|
||||||
|
|
||||||
|
Add AddDhcpLease and DeleteDhcpLease DBus methods. Thanks
|
||||||
|
to Nicolas Cavallari for the patch.
|
||||||
|
|
||||||
|
Allow configuration of router advertisements without the
|
||||||
|
"on-link" bit set. Thanks to Neil Jerram for the patch.
|
||||||
|
|
||||||
|
Extend --bridge-interface to DHCPv6 and router
|
||||||
|
advertisements. Thanks to Neil Jerram for the patch.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.72
|
||||||
|
Add ra-advrouter mode, for RFC-3775 mobile IPv6 support.
|
||||||
|
|
||||||
|
Add support for "ipsets" in *BSD, using pf. Thanks to
|
||||||
|
Sven Falempim for the patch.
|
||||||
|
|
||||||
|
Fix race condition which could lock up dnsmasq when an
|
||||||
|
interface goes down and up rapidly. Thanks to Conrad
|
||||||
|
Kostecki for helping to chase this down.
|
||||||
|
|
||||||
|
Add DBus methods SetFilterWin2KOption and SetBogusPrivOption
|
||||||
|
Thanks to the Smoothwall project for the patch.
|
||||||
|
|
||||||
|
Fix failure to build against Nettle-3.0. Thanks to Steven
|
||||||
|
Barth for spotting this and finding the fix.
|
||||||
|
|
||||||
|
When assigning existing DHCP leases to intefaces by comparing
|
||||||
|
networks, handle the case that two or more interfaces have the
|
||||||
|
same network part, but different prefix lengths (favour the
|
||||||
|
longer prefix length.) Thanks to Lung-Pin Chang for the
|
||||||
|
patch.
|
||||||
|
|
||||||
|
Add a mode which detects and removes DNS forwarding loops, ie
|
||||||
|
a query sent to an upstream server returns as a new query to
|
||||||
|
dnsmasq, and would therefore be forwarded again, resulting in
|
||||||
|
a query which loops many times before being dropped. Upstream
|
||||||
|
servers which loop back are disabled and this event is logged.
|
||||||
|
Thanks to Smoothwall for their sponsorship of this feature.
|
||||||
|
|
||||||
|
Extend --conf-dir to allow filtering of files. So
|
||||||
|
--conf-dir=/etc/dnsmasq.d,\*.conf
|
||||||
|
will load all the files in /etc/dnsmasq.d which end in .conf
|
||||||
|
|
||||||
|
Fix bug when resulted in NXDOMAIN answers instead of NODATA in
|
||||||
|
some circumstances.
|
||||||
|
|
||||||
|
Fix bug which caused dnsmasq to become unresponsive if it
|
||||||
|
failed to send packets due to a network interface disappearing.
|
||||||
|
Thanks to Niels Peen for spotting this.
|
||||||
|
|
||||||
|
Fix problem with --local-service option on big-endian platforms
|
||||||
|
Thanks to Richard Genoud for the patch.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.71
|
||||||
|
Subtle change to error handling to help DNSSEC validation
|
||||||
|
when servers fail to provide NODATA answers for
|
||||||
|
non-existent DS records.
|
||||||
|
|
||||||
|
Tweak code which removes DNSSEC records from answers when
|
||||||
|
not required. Fixes broken answers when additional section
|
||||||
|
has real records in it. Thanks to Marco Davids for the bug
|
||||||
|
report.
|
||||||
|
|
||||||
|
Fix DNSSEC validation of ANY queries. Thanks to Marco Davids
|
||||||
|
for spotting that too.
|
||||||
|
|
||||||
|
Fix total DNS failure and 100% CPU use if cachesize set to zero,
|
||||||
|
regression introduced in 2.69. Thanks to James Hunt and
|
||||||
|
the Ubuntu crowd for assistance in fixing this.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.70
|
||||||
|
Fix crash, introduced in 2.69, on TCP request when dnsmasq
|
||||||
|
compiled with DNSSEC support, but running without DNSSEC
|
||||||
|
enabled. Thanks to Manish Sing for spotting that one.
|
||||||
|
|
||||||
|
Fix regression which broke ipset functionality. Thanks to
|
||||||
|
Wang Jian for the bug report.
|
||||||
|
|
||||||
|
|
||||||
version 2.69
|
version 2.69
|
||||||
Implement dynamic interface discovery on *BSD. This allows
|
Implement dynamic interface discovery on *BSD. This allows
|
||||||
the contructor: syntax to be used in dhcp-range for DHCPv6
|
the contructor: syntax to be used in dhcp-range for DHCPv6
|
||||||
@@ -28,9 +245,9 @@ version 2.69
|
|||||||
|
|
||||||
make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
|
make dnsmasq COPTS='-DHAVE_DNSSEC -DHAVE_DNSSEC_STATIC'
|
||||||
|
|
||||||
which bloats the dnsmasq binary to over a megabyte, but
|
which bloats the dnsmasq binary, but saves the size of
|
||||||
saves the size of the shared libraries which are five
|
the shared libraries which are much bigger.
|
||||||
times that size.
|
|
||||||
To enable, DNSSEC, you will need a set of
|
To enable, DNSSEC, you will need a set of
|
||||||
trust-anchors. Now that the TLDs are signed, this can be
|
trust-anchors. Now that the TLDs are signed, this can be
|
||||||
the keys for the root zone, and for convenience they are
|
the keys for the root zone, and for convenience they are
|
||||||
@@ -56,13 +273,68 @@ version 2.69
|
|||||||
downstream validators. Setting --log-queries will show
|
downstream validators. Setting --log-queries will show
|
||||||
DNSSEC in action.
|
DNSSEC in action.
|
||||||
|
|
||||||
|
If a domain is returned from an upstream nameserver without
|
||||||
|
DNSSEC signature, dnsmasq by default trusts this. This
|
||||||
|
means that for unsigned zone (still the majority) there
|
||||||
|
is effectively no cost for having DNSSEC enabled. Of course
|
||||||
|
this allows an attacker to replace a signed record with a
|
||||||
|
false unsigned record. This is addressed by the
|
||||||
|
--dnssec-check-unsigned flag, which instructs dnsmasq
|
||||||
|
to prove that an unsigned record is legitimate, by finding
|
||||||
|
a secure proof that the zone containing the record is not
|
||||||
|
signed. Doing this has costs (typically one or two extra
|
||||||
|
upstream queries). It also has a nasty failure mode if
|
||||||
|
dnsmasq's upstream nameservers are not DNSSEC capable.
|
||||||
|
Without --dnssec-check-unsigned using such an upstream
|
||||||
|
server will simply result in not queries being validated;
|
||||||
|
with --dnssec-check-unsigned enabled and a
|
||||||
|
DNSSEC-ignorant upstream server, _all_ queries will fail.
|
||||||
|
|
||||||
|
Note that DNSSEC requires that the local time is valid and
|
||||||
|
accurate, if not then DNSSEC validation will fail. NTP
|
||||||
|
should be running. This presents a problem for routers
|
||||||
|
without a battery-backed clock. To set the time needs NTP
|
||||||
|
to do DNS lookups, but lookups will fail until NTP has run.
|
||||||
|
To address this, there's a flag, --dnssec-no-timecheck
|
||||||
|
which disables the time checks (only) in DNSSEC. When dnsmasq
|
||||||
|
is started and the clock is not synced, this flag should
|
||||||
|
be used. As soon as the clock is synced, SIGHUP dnsmasq.
|
||||||
|
The SIGHUP clears the cache of partially-validated data and
|
||||||
|
resets the no-timecheck flag, so that all DNSSEC checks
|
||||||
|
henceforward will be complete.
|
||||||
|
|
||||||
The development of DNSSEC in dnsmasq was started by
|
The development of DNSSEC in dnsmasq was started by
|
||||||
Giovanni Bajo, to whom huge thanks are owed. It has been
|
Giovanni Bajo, to whom huge thanks are owed. It has been
|
||||||
supported by Comcast, whose techfund grant has allowed for
|
supported by Comcast, whose techfund grant has allowed for
|
||||||
an invaluable period of full-time work to get it to
|
an invaluable period of full-time work to get it to
|
||||||
a workable state.
|
a workable state.
|
||||||
|
|
||||||
|
Add --rev-server. Thanks to Dave Taht for suggesting this.
|
||||||
|
|
||||||
|
Add --servers-file. Allows dynamic update of upstream servers
|
||||||
|
full access to configuration.
|
||||||
|
|
||||||
|
Add --local-service. 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
|
||||||
|
only has effect if there are no --interface --except-interface,
|
||||||
|
--listen-address or --auth-server 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.
|
||||||
|
|
||||||
|
Fix crashes in cache_get_cname_target() when dangling CNAMEs
|
||||||
|
encountered. Thanks to Andy and the rt-n56u project for
|
||||||
|
find this and helping to chase it down.
|
||||||
|
|
||||||
|
Fix wrong RCODE in authoritative DNS replies to PTR queries. The
|
||||||
|
correct answer was included, but the RCODE was set to NXDOMAIN.
|
||||||
|
Thanks to Craig McQueen for spotting this.
|
||||||
|
|
||||||
|
Make statistics available as DNS queries in the .bind TLD as
|
||||||
|
well as logging them.
|
||||||
|
|
||||||
|
|
||||||
version 2.68
|
version 2.68
|
||||||
Use random addresses for DHCPv6 temporary address
|
Use random addresses for DHCPv6 temporary address
|
||||||
allocations, instead of algorithmically determined stable
|
allocations, instead of algorithmically determined stable
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
# dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -61,14 +61,19 @@ lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CON
|
|||||||
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1`
|
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1`
|
||||||
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
|
nettle_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`
|
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`
|
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
|
||||||
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
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 ' '
|
||||||
|
copts_conf = .copts_$(sum)
|
||||||
|
|
||||||
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||||
domain.o dnssec.o blockdata.o
|
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o poll.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h ip6addr.h
|
dns-protocol.h radv-protocol.h ip6addr.h
|
||||||
@@ -77,12 +82,12 @@ all : $(BUILDDIR)
|
|||||||
@cd $(BUILDDIR) && $(MAKE) \
|
@cd $(BUILDDIR) && $(MAKE) \
|
||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||||
build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs)" \
|
build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||||
-f $(top)/Makefile dnsmasq
|
-f $(top)/Makefile dnsmasq
|
||||||
|
|
||||||
mostly_clean :
|
mostly_clean :
|
||||||
rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot
|
rm -f $(BUILDDIR)/*.mo $(BUILDDIR)/*.pot
|
||||||
rm -f $(BUILDDIR)/.configured $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
|
rm -f $(BUILDDIR)/.copts_* $(BUILDDIR)/*.o $(BUILDDIR)/dnsmasq.a $(BUILDDIR)/dnsmasq
|
||||||
|
|
||||||
clean : mostly_clean
|
clean : mostly_clean
|
||||||
rm -f $(BUILDDIR)/dnsmasq_baseline
|
rm -f $(BUILDDIR)/dnsmasq_baseline
|
||||||
@@ -101,7 +106,7 @@ all-i18n : $(BUILDDIR)
|
|||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
|
build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
|
||||||
build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) `$(PKG_CONFIG) --libs libidn`" \
|
build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) `$(PKG_CONFIG) --libs libidn`" \
|
||||||
-f $(top)/Makefile dnsmasq
|
-f $(top)/Makefile dnsmasq
|
||||||
for f in `cd $(PO); echo *.po`; do \
|
for f in `cd $(PO); echo *.po`; do \
|
||||||
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
||||||
@@ -112,7 +117,7 @@ install-i18n : all-i18n install-common
|
|||||||
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
|
cd $(MAN); ../bld/install-man $(DESTDIR)$(MANDIR) $(INSTALL)
|
||||||
|
|
||||||
merge :
|
merge :
|
||||||
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
|
@cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile dnsmasq.pot
|
||||||
for f in `cd $(PO); echo *.po`; do \
|
for f in `cd $(PO); echo *.po`; do \
|
||||||
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
|
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
|
||||||
done
|
done
|
||||||
@@ -138,17 +143,19 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
|
|||||||
|
|
||||||
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
|
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
|
||||||
|
|
||||||
.configured: $(hdrs)
|
$(copts_conf): $(hdrs)
|
||||||
@rm -f *.o
|
@rm -f *.o .copts_*
|
||||||
@touch $@
|
@touch $@
|
||||||
|
|
||||||
$(objs:.o=.c) $(hdrs):
|
$(objs:.o=.c) $(hdrs):
|
||||||
ln -s $(top)/$(SRC)/$@ .
|
ln -s $(top)/$(SRC)/$@ .
|
||||||
|
|
||||||
|
$(objs): $(copts_conf) $(hdrs)
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
|
$(CC) $(CFLAGS) $(COPTS) $(i18n) $(build_cflags) $(RPM_OPT_FLAGS) -c $<
|
||||||
|
|
||||||
dnsmasq : .configured $(hdrs) $(objs)
|
dnsmasq : $(objs)
|
||||||
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
|
$(CC) $(LDFLAGS) -o $@ $(objs) $(build_libs) $(LIBS)
|
||||||
|
|
||||||
dnsmasq.pot : $(objs:.o=.c) $(hdrs)
|
dnsmasq.pot : $(objs:.o=.c) $(hdrs)
|
||||||
|
|||||||
+2
-1
@@ -9,7 +9,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
|||||||
rfc2131.c tftp.c util.c conntrack.c \
|
rfc2131.c tftp.c util.c conntrack.c \
|
||||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||||
radv.c slaac.c auth.c ipset.c domain.c \
|
radv.c slaac.c auth.c ipset.c domain.c \
|
||||||
dnssec.c dnssec-openssl.c blockdata.c
|
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||||
|
loop.c inotify.c poll.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -11,8 +11,9 @@
|
|||||||
# If there is more than one v[0-9].* tag, sort them and use the
|
# If there is more than one v[0-9].* tag, sort them and use the
|
||||||
# first. This favours, eg v2.63 over 2.63rc6.
|
# first. This favours, eg v2.63 over 2.63rc6.
|
||||||
|
|
||||||
if which git >/dev/null 2>&1 && [ -d $1/.git ]; then
|
if which git >/dev/null 2>&1 && \
|
||||||
cd $1; git describe | sed 's/^v//'
|
([ -d $1/.git ] || grep '^gitdir:' $1/.git >/dev/null 2>&1); then
|
||||||
|
cd $1; git describe | sed 's/^v//'
|
||||||
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
||||||
# unsubstituted VERSION, but no git available.
|
# unsubstituted VERSION, but no git available.
|
||||||
echo UNKNOWN
|
echo UNKNOWN
|
||||||
@@ -20,7 +21,7 @@ else
|
|||||||
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
|
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
|
||||||
|
|
||||||
if [ $? -eq 0 ]; then
|
if [ $? -eq 0 ]; then
|
||||||
echo "${vers}" | sort | head -n 1 | sed 's/^v//'
|
echo "${vers}" | sort -r | head -n 1 | sed 's/^v//'
|
||||||
else
|
else
|
||||||
cat $1/VERSION
|
cat $1/VERSION
|
||||||
fi
|
fi
|
||||||
|
|||||||
+25
-12
@@ -9,19 +9,32 @@ shift
|
|||||||
|
|
||||||
in=`cat`
|
in=`cat`
|
||||||
|
|
||||||
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
|
||||||
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
|
||||||
if [ $op = "--libs" ]; then
|
|
||||||
pkg=`$pkg --static $op $*`
|
|
||||||
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
|
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
|
||||||
echo $in | grep $search >/dev/null 2>&1; then
|
echo $in | grep $search >/dev/null 2>&1; then
|
||||||
pkg=`$pkg $op $*`
|
# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP
|
||||||
echo "$pkg"
|
if [ $op = "--copy" ]; then
|
||||||
|
if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
|
||||||
|
echo $in | grep $pkg >/dev/null 2>&1; then
|
||||||
|
pkg=""
|
||||||
|
else
|
||||||
|
pkg="$*"
|
||||||
|
fi
|
||||||
|
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||||
|
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||||
|
pkg=`$pkg --static $op $*`
|
||||||
|
else
|
||||||
|
pkg=`$pkg $op $*`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||||
|
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||||
|
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
|
||||||
|
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
|
||||||
|
else
|
||||||
|
echo "$pkg"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "$pkg"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
The script reads stdin and replaces all IP addresses with names before
|
||||||
|
outputting it again. IPs from private networks are reverse looked up
|
||||||
|
via dns. Other IP adresses are searched for in the dnsmasq query log.
|
||||||
|
This gives names (CNAMEs if I understand DNS correctly) that are closer
|
||||||
|
to the name the client originally asked for then the names obtained by
|
||||||
|
reverse lookup. Just run
|
||||||
|
|
||||||
|
netstat -n -4 | ./reverse_replace.sh
|
||||||
|
|
||||||
|
to see what it does. It needs
|
||||||
|
|
||||||
|
log-queries
|
||||||
|
log-facility=/var/log/dnsmasq.log
|
||||||
|
|
||||||
|
in the dnsmasq configuration.
|
||||||
|
|
||||||
|
The script runs on debian (with ash installed) and on busybox.
|
||||||
|
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
#!/bin/ash
|
||||||
|
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
|
||||||
|
#
|
||||||
|
# Usage e.g.: netstat -n -4 | reverse_replace.sh
|
||||||
|
# Parses stdin for IP4 addresses and replaces them
|
||||||
|
# with names retrieved by parsing the dnsmasq log.
|
||||||
|
# This currently only gives CNAMEs. But these
|
||||||
|
# usually tell ou more than the mones from reverse
|
||||||
|
# lookups.
|
||||||
|
#
|
||||||
|
# This has been tested on debian and asuswrt. Plese
|
||||||
|
# report successful tests on other platforms.
|
||||||
|
#
|
||||||
|
# Author: Joachim Zobel <jz-2014@heute-morgen.de>
|
||||||
|
# License: Consider this MIT style licensed. You can
|
||||||
|
# do as you ike, but you must not remove my name.
|
||||||
|
#
|
||||||
|
|
||||||
|
LOG=/var/log/dnsmasq.log
|
||||||
|
MAX_LINES=15000
|
||||||
|
|
||||||
|
# sed regex do match IPs
|
||||||
|
IP_regex='[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}'
|
||||||
|
# private IP ranges
|
||||||
|
IP_private='\(^127\.\)\|\(^192\.168\.\)\|\(^10\.\)\|\(^172\.1[6-9]\.\)\|\(^172\.2[0-9]\.\)\|\(^172\.3[0-1]\.\)'
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Find Commands
|
||||||
|
|
||||||
|
HOST=nslookup
|
||||||
|
if type host > /dev/null 2>&1; then
|
||||||
|
# echo "No need for nslookup, host is there"
|
||||||
|
HOST=host
|
||||||
|
fi
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
# Use shell variables for an (IP) lookup table
|
||||||
|
create_lookup_table()
|
||||||
|
{
|
||||||
|
# Parse log into lookup table
|
||||||
|
local CMDS="$( tail -"$MAX_LINES" "$LOG" | \
|
||||||
|
grep " is $IP_regex" | \
|
||||||
|
sed "s#.* \([^ ]*\) is \($IP_regex\).*#set_val \2 \1;#" )"
|
||||||
|
|
||||||
|
local IFS='
|
||||||
|
'
|
||||||
|
for CMD in $CMDS
|
||||||
|
do
|
||||||
|
eval $CMD
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
set_val()
|
||||||
|
{
|
||||||
|
local _IP=$(echo $1 | tr . _)
|
||||||
|
local KEY="__IP__$_IP"
|
||||||
|
eval "$KEY"=$2
|
||||||
|
}
|
||||||
|
|
||||||
|
get_val()
|
||||||
|
{
|
||||||
|
local _IP=$(echo $1 | tr . _)
|
||||||
|
local KEY="__IP__$_IP"
|
||||||
|
eval echo -n '${'"$KEY"'}'
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_lookup()
|
||||||
|
{
|
||||||
|
local IP=$1
|
||||||
|
|
||||||
|
local RTN="$($HOST $IP | \
|
||||||
|
sed 's#\s\+#\n#g' | \
|
||||||
|
grep -v '^$' | \
|
||||||
|
tail -1 | tr -d '\n' | \
|
||||||
|
sed 's#\.$##')"
|
||||||
|
if echo $RTN | grep -q NXDOMAIN; then
|
||||||
|
echo -n $IP
|
||||||
|
else
|
||||||
|
echo -n "$RTN"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
reverse_dns()
|
||||||
|
{
|
||||||
|
local IP=$1
|
||||||
|
|
||||||
|
# Skip if it is not an IP
|
||||||
|
if ! echo $IP | grep -q "^$IP_regex$"; then
|
||||||
|
echo -n $IP
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Do a dns lookup, if it is a local IP
|
||||||
|
if echo $IP | grep -q $IP_private; then
|
||||||
|
dns_lookup $IP
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local NAME="$(get_val $IP)"
|
||||||
|
|
||||||
|
if [ -z "$NAME" ]; then
|
||||||
|
echo -n $IP
|
||||||
|
else
|
||||||
|
echo -n $NAME
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# Main
|
||||||
|
create_lookup_table
|
||||||
|
|
||||||
|
while read LINE; do
|
||||||
|
for IP in $(echo "$LINE" | \
|
||||||
|
sed "s#\b\($IP_regex\)\b#\n\1\n#g" | \
|
||||||
|
grep $IP_regex)
|
||||||
|
do
|
||||||
|
NAME=`reverse_dns $IP `
|
||||||
|
# echo "$NAME $IP"
|
||||||
|
LINE=`echo "$LINE" | sed "s#$IP#$NAME#" `
|
||||||
|
done
|
||||||
|
echo $LINE
|
||||||
|
done
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=A lightweight DHCP and caching DNS server
|
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=dbus
|
Type=dbus
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
From: Jesse Glick <jglick@cloudbees.com>
|
||||||
|
To: dnsmasq-discuss@lists.thekelleys.org.uk
|
||||||
|
Subject: Re: [Dnsmasq-discuss] Ability to delegate to one server but fall
|
||||||
|
back to another after NXDOMAIN?
|
||||||
|
|
||||||
|
|
||||||
|
On Wed, Jan 15, 2014 at 12:30 PM, Simon Kelley <simon@thekelleys.org.uk> wrote:
|
||||||
|
> > There's a (very old) patch in contrib/try-all-ns that would make a starting point
|
||||||
|
This does not apply against trunk, so I tried to rework it. The
|
||||||
|
following appears to do what I expect:
|
||||||
|
|
||||||
|
diff --git a/src/forward.c b/src/forward.c
|
||||||
|
index 8167229..76070b5 100644
|
||||||
|
--- a/src/forward.c
|
||||||
|
+++ b/src/forward.c
|
||||||
|
@@ -610,7 +610,11 @@ void reply_query(int fd, int family, time_t now)
|
||||||
|
|
||||||
|
if ((RCODE(header) == SERVFAIL || RCODE(header) == REFUSED) &&
|
||||||
|
!option_bool(OPT_ORDER) &&
|
||||||
|
- forward->forwardall == 0)
|
||||||
|
+ forward->forwardall == 0 ||
|
||||||
|
+ /* try each in turn */
|
||||||
|
+ RCODE(header) == NXDOMAIN &&
|
||||||
|
+ option_bool(OPT_ORDER) &&
|
||||||
|
+ server->next != NULL)
|
||||||
|
/* for broken servers, attempt to send to another one. */
|
||||||
|
{
|
||||||
|
unsigned char *pheader;
|
||||||
|
|
||||||
@@ -277,6 +277,11 @@ int main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inet_addr(argv[2]) == INADDR_NONE)
|
||||||
|
{
|
||||||
|
perror("invalid ip address");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
lease.s_addr = inet_addr(argv[2]);
|
lease.s_addr = inet_addr(argv[2]);
|
||||||
server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
server = find_interface(lease, nl, if_nametoindex(argv[1]));
|
||||||
|
|||||||
@@ -40,6 +40,14 @@ ClearCache
|
|||||||
Returns nothing. Clears the domain name cache and re-reads
|
Returns nothing. Clears the domain name cache and re-reads
|
||||||
/etc/hosts. The same as sending dnsmasq a HUP signal.
|
/etc/hosts. The same as sending dnsmasq a HUP signal.
|
||||||
|
|
||||||
|
SetFilterWin2KOption
|
||||||
|
--------------------
|
||||||
|
Takes boolean, sets or resets the --filterwin2k option.
|
||||||
|
|
||||||
|
SetBogusPrivOption
|
||||||
|
------------------
|
||||||
|
Takes boolean, sets or resets the --bogus-priv option.
|
||||||
|
|
||||||
SetServers
|
SetServers
|
||||||
----------
|
----------
|
||||||
Returns nothing. Takes a set of arguments representing the new
|
Returns nothing. Takes a set of arguments representing the new
|
||||||
@@ -152,6 +160,89 @@ for SetServersEx is represented as
|
|||||||
"/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0"
|
"/eng.mycorp.com/lab.mycorp.com/1003:1234:abcd::1%eth0"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
GetLoopServers
|
||||||
|
--------------
|
||||||
|
|
||||||
|
(Only available if dnsmasq compiled with HAVE_LOOP)
|
||||||
|
|
||||||
|
Return an array of strings, each string is the IP address of an upstream
|
||||||
|
server which has been found to loop queries back to this dnsmasq instance, and
|
||||||
|
it therefore not being used.
|
||||||
|
|
||||||
|
AddDhcpLease
|
||||||
|
------------
|
||||||
|
|
||||||
|
Returns nothing. Adds or updates a DHCP or DHCPv6 lease to the internal lease
|
||||||
|
database, as if a client requested and obtained a lease.
|
||||||
|
|
||||||
|
If a lease for the IPv4 or IPv6 address already exist, it is overwritten.
|
||||||
|
|
||||||
|
Note that this function will trigger the DhcpLeaseAdded or DhcpLeaseUpdated
|
||||||
|
D-Bus signal and will run the configured DHCP lease script accordingly.
|
||||||
|
|
||||||
|
This function takes many arguments which are the lease parameters:
|
||||||
|
- A string with the textual representation of the IPv4 or IPv6 address of the
|
||||||
|
client.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
"192.168.1.115"
|
||||||
|
"1003:1234:abcd::1%eth0"
|
||||||
|
"2001:db8:abcd::1"
|
||||||
|
|
||||||
|
- A string representing the hardware address of the client, using the same
|
||||||
|
format as the one used in the lease database.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
"00:23:45:67:89:ab"
|
||||||
|
"06-00:20:e0:3b:13:af" (token ring)
|
||||||
|
|
||||||
|
- The hostname of the client, as an array of bytes (so there is no problem
|
||||||
|
with non-ASCII character encoding). May be empty.
|
||||||
|
|
||||||
|
Example (for "hostname.or.fqdn"):
|
||||||
|
[104, 111, 115, 116, 110, 97, 109, 101, 46, 111, 114, 46, 102, 113, 100, 110]
|
||||||
|
|
||||||
|
- The client identifier (IPv4) or DUID (IPv6) as an array of bytes. May be
|
||||||
|
empty.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
DHCPv6 DUID:
|
||||||
|
[0, 3, 0, 1, 0, 35, 69, 103, 137, 171]
|
||||||
|
DHCPv4 client identifier:
|
||||||
|
[255, 12, 34, 56, 78, 0, 1, 0, 1, 29, 9, 99, 190, 35, 69, 103, 137, 171]
|
||||||
|
|
||||||
|
- The duration of the lease, in seconds. If the lease is updated, then
|
||||||
|
the duration replaces the previous duration.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
7200
|
||||||
|
|
||||||
|
- The IAID (Identity association identifier) of the DHCPv6 lease, as a network
|
||||||
|
byte-order unsigned integer. For DHCPv4 leases, this must be set to 0.
|
||||||
|
|
||||||
|
Example (for IPv6):
|
||||||
|
|
||||||
|
203569230
|
||||||
|
|
||||||
|
- A boolean which, if true, indicates that the DHCPv6 lease is for a temporary
|
||||||
|
address (IA_TA). If false, the DHCPv6 lease is for a non-temporary address
|
||||||
|
(IA_NA). For DHCPv4 leases, this must be set to false.
|
||||||
|
|
||||||
|
RemoveDhcpLease
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Returns nothing. Removes a DHCP or DHCPv6 lease to the internal lease
|
||||||
|
database, as if a client sent a release message to abandon a lease.
|
||||||
|
|
||||||
|
This function takes only one parameter: the text representation of the
|
||||||
|
IPv4 or IPv6 address of the lease to remove.
|
||||||
|
|
||||||
|
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
||||||
|
configured DHCP lease script will be run with the "del" action.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2. SIGNALS
|
2. SIGNALS
|
||||||
|
|||||||
Vendored
+99
-1
@@ -1,7 +1,105 @@
|
|||||||
|
dnsmasq (2.74-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:54:11 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.73-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fix behaviour of empty --conf-file (closes: #790341)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:46:42 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.73-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream. (closes: #786996)
|
||||||
|
* Tweak field width in cache dump to avoid truncating IPv6
|
||||||
|
addresses. (closes: #771557)
|
||||||
|
* Add newline at the end of example config file. (LP: #1416895)
|
||||||
|
* Make Debian package build reproducible. (closes: #777323)
|
||||||
|
* Add Requires=network.target to systemd unit.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 4 Jun 2015 22:31:42 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.72-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* debian/systemd.service: switch from Type=dbus to Type=forking.
|
||||||
|
dnsmasq does not depend on dbus, but Type=dbus systemd services cannot
|
||||||
|
work without it. (Closes: #769486, #776530)
|
||||||
|
- debian/init: when called with systemd-exec argument, let dnsmasq
|
||||||
|
go into the background, so Type=forking can detect when it is ready
|
||||||
|
* Remove line containing only whitespace in debian/contol.
|
||||||
|
(closes: #777571)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 11 Feb 2015 21:56:12 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.72-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fix build in Debian-kFreeBSD. (closes: #763693)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 02 Oct 2014 22:34:12 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.72-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
* If dns-root-data package is installed, use it to set the DNSSEC
|
||||||
|
trust anchor(s). Recommend dns-root-data. (closes: #760460)
|
||||||
|
* Handle AD bit correctly in replies from cache. (closes: #761654)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 20 May 2014 21:01:11 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.71-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
* Fix 100% CPU-usage bug when dnsmasq started with cachesize
|
||||||
|
set to zero. (LP: #1314697)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 16 May 2014 20:17:10 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.70-3) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Write a pid-file, even when being started using systemd, since
|
||||||
|
other components may wish to signal dnsmasq.
|
||||||
|
* Enable dnsmasq systemd unit on install. Otherwise dnsmasq does not run on
|
||||||
|
fresh installations (without administrator handholding) and even worse it
|
||||||
|
is disabled on systems switching from sysv to systemd. Modify
|
||||||
|
postinst/postrm exactly as dh_systemd would, add dependency on
|
||||||
|
init-system-helpers. Closes: #724602
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 11 May 2014 17:45:21 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.70-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Ensure daemon not stared if dnsmasq package has been removed,
|
||||||
|
even if dnsmasq-base is still installed. (closes: #746941)
|
||||||
|
* Tidy cruft in initscript. (closes: #746940)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 04 May 2014 21:34:11 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.70-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 23 Apr 2014 15:14:42 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.69-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
* Set --local-service. (closes: #732610)
|
||||||
|
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.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 4 Feb 2014 16:28:12 +0000
|
||||||
|
|
||||||
dnsmasq (2.68-1) unstable; urgency=low
|
dnsmasq (2.68-1) unstable; urgency=low
|
||||||
|
|
||||||
* New upstream. (closes: #730553)
|
* New upstream. (closes: #730553)
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 8 Dec 2013 15:57:32 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 8 Dec 2013 15:57:32 +0000
|
||||||
|
|
||||||
dnsmasq (2.67-1) unstable; urgency=low
|
dnsmasq (2.67-1) unstable; urgency=low
|
||||||
|
|||||||
Vendored
+7
-5
@@ -1,13 +1,16 @@
|
|||||||
Source: dnsmasq
|
Source: dnsmasq
|
||||||
Section: net
|
Section: net
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any], libidn11-dev, libdbus-1-dev (>=0.61)
|
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||||
|
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||||
|
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
|
||||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||||
Standards-Version: 3.9.3
|
Standards-Version: 3.9.5
|
||||||
|
|
||||||
Package: dnsmasq
|
Package: dnsmasq
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: netbase, dnsmasq-base(>= ${binary:Version})
|
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
|
||||||
|
init-system-helpers (>= 1.18~)
|
||||||
Suggests: resolvconf
|
Suggests: resolvconf
|
||||||
Conflicts: resolvconf (<<1.15)
|
Conflicts: resolvconf (<<1.15)
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
@@ -25,6 +28,7 @@ Architecture: any
|
|||||||
Depends: adduser, ${shlibs:Depends}
|
Depends: adduser, ${shlibs:Depends}
|
||||||
Breaks: dnsmasq (<< 2.63-1~)
|
Breaks: dnsmasq (<< 2.63-1~)
|
||||||
Replaces: dnsmasq (<< 2.63-1~)
|
Replaces: dnsmasq (<< 2.63-1~)
|
||||||
|
Recommends: dns-root-data
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
This package contains the dnsmasq executable and documentation, but
|
This package contains the dnsmasq executable and documentation, but
|
||||||
not the infrastructure required to run it as a system daemon. For
|
not the infrastructure required to run it as a system daemon. For
|
||||||
@@ -38,5 +42,3 @@ Description: Utilities for manipulating DHCP leases
|
|||||||
Small utilities to query a DHCP server's lease database and
|
Small utilities to query a DHCP server's lease database and
|
||||||
remove leases from it. These programs are distributed with dnsmasq
|
remove leases from it. These programs are distributed with dnsmasq
|
||||||
and may not work correctly with other DHCP servers.
|
and may not work correctly with other DHCP servers.
|
||||||
|
|
||||||
|
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
dnsmasq is Copyright (c) 2000-2013 Simon Kelley
|
dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -27,7 +27,7 @@ CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
|
|||||||
# If the resolvconf package is installed, dnsmasq will use its output
|
# If the resolvconf package is installed, dnsmasq will use its output
|
||||||
# rather than the contents of /etc/resolv.conf to find upstream
|
# rather than the contents of /etc/resolv.conf to find upstream
|
||||||
# nameservers. Uncommenting this line inhibits this behaviour.
|
# nameservers. Uncommenting this line inhibits this behaviour.
|
||||||
# Not that including a "resolv-file=<filename>" line in
|
# Note that including a "resolv-file=<filename>" line in
|
||||||
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
|
# /etc/dnsmasq.conf is not enough to override resolvconf if it is
|
||||||
# installed: the line below must be uncommented.
|
# installed: the line below must be uncommented.
|
||||||
#IGNORE_RESOLVCONF=yes
|
#IGNORE_RESOLVCONF=yes
|
||||||
Vendored
+31
-6
@@ -29,6 +29,12 @@ if [ -r /etc/default/locale ]; then
|
|||||||
export LANG
|
export LANG
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# /etc/dnsmasq.d/README is a non-conffile installed by the dnsmasq package.
|
||||||
|
# Should the dnsmasq package be removed, the following test ensures that
|
||||||
|
# the daemon is no longer started, even if the dnsmasq-base package is
|
||||||
|
# still in place.
|
||||||
|
test -e /etc/dnsmasq.d/README || exit 0
|
||||||
|
|
||||||
test -x $DAEMON || exit 0
|
test -x $DAEMON || exit 0
|
||||||
|
|
||||||
# Provide skeleton LSB log functions for backports which don't have LSB functions.
|
# Provide skeleton LSB log functions for backports which don't have LSB functions.
|
||||||
@@ -90,6 +96,24 @@ if [ ! "$DNSMASQ_USER" ]; then
|
|||||||
DNSMASQ_USER="dnsmasq"
|
DNSMASQ_USER="dnsmasq"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# This tells dnsmasq to ignore DNS requests that don't come from a local network.
|
||||||
|
# It's automatically ignored if --interface --except-interface, --listen-address
|
||||||
|
# or --auth-server exist in the configuration, so for most installations, it will
|
||||||
|
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
|
||||||
|
# from being vulnerable to DNS-reflection attacks.
|
||||||
|
|
||||||
|
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
|
||||||
|
|
||||||
|
# If the dns-root-data package is installed, then the trust anchors will be
|
||||||
|
# available in $ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
|
||||||
|
# --trust-anchor options.
|
||||||
|
|
||||||
|
ROOT_DS="/usr/share/dns/root.ds"
|
||||||
|
|
||||||
|
if [ -f $ROOT_DS ]; then
|
||||||
|
DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -e s/". IN DS "/--trust-anchor=.,/ -e s/" "/,/g $ROOT_DS | tr '\n' ' '`"
|
||||||
|
fi
|
||||||
|
|
||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
@@ -144,9 +168,6 @@ stop()
|
|||||||
# 2 if daemon could not be stopped
|
# 2 if daemon could not be stopped
|
||||||
# other if a failure occurred
|
# other if a failure occurred
|
||||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
|
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
|
||||||
RETVAL="$?"
|
|
||||||
[ "$RETVAL" = 2 ] && return 2
|
|
||||||
return "$RETVAL"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_resolvconf()
|
stop_resolvconf()
|
||||||
@@ -266,9 +287,13 @@ case "$1" in
|
|||||||
stop_resolvconf
|
stop_resolvconf
|
||||||
;;
|
;;
|
||||||
systemd-exec)
|
systemd-exec)
|
||||||
# --pid-file without argument disables writing a PIDfile, we don't need one with sytemd.
|
# /var/run may be volatile, so we need to ensure that
|
||||||
# Enable DBus by default because we use DBus activation with systemd.
|
# /var/run/dnsmasq exists here as well as in postinst
|
||||||
exec $DAEMON --keep-in-foreground --pid-file --enable-dbus \
|
if [ ! -d /var/run/dnsmasq ]; then
|
||||||
|
mkdir /var/run/dnsmasq || return 2
|
||||||
|
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
|
||||||
|
fi
|
||||||
|
exec $DAEMON -x /var/run/dnsmasq/$NAME.pid \
|
||||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||||
${MAILTARGET:+ -t $MAILTARGET} \
|
${MAILTARGET:+ -t $MAILTARGET} \
|
||||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||||
|
|||||||
Vendored
+16
@@ -1,6 +1,22 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Code copied from dh_systemd_enable ----------------------
|
||||||
|
# This will only remove masks created by d-s-h on package removal.
|
||||||
|
deb-systemd-helper unmask dnsmasq.service >/dev/null || true
|
||||||
|
|
||||||
|
# was-enabled defaults to true, so new installations run enable.
|
||||||
|
if deb-systemd-helper --quiet was-enabled dnsmasq.service; then
|
||||||
|
# Enables the unit on first installation, creates new
|
||||||
|
# symlinks on upgrades if the unit file has changed.
|
||||||
|
deb-systemd-helper enable dnsmasq.service >/dev/null || true
|
||||||
|
else
|
||||||
|
# Update the statefile to add new symlinks (if any), which need to be
|
||||||
|
# cleaned up on purge. Also remove old symlinks.
|
||||||
|
deb-systemd-helper update-state dnsmasq.service >/dev/null || true
|
||||||
|
fi
|
||||||
|
# End code copied from dh_systemd_enable ------------------
|
||||||
|
|
||||||
if [ -x /etc/init.d/dnsmasq ]; then
|
if [ -x /etc/init.d/dnsmasq ]; then
|
||||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||||
|
|
||||||
|
|||||||
Vendored
+16
@@ -4,3 +4,19 @@ set -e
|
|||||||
if [ purge = "$1" ]; then
|
if [ purge = "$1" ]; then
|
||||||
update-rc.d dnsmasq remove >/dev/null
|
update-rc.d dnsmasq remove >/dev/null
|
||||||
fi
|
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 ------------------
|
||||||
|
|
||||||
Vendored
+36
-21
@@ -11,17 +11,20 @@
|
|||||||
|
|
||||||
package=dnsmasq-base
|
package=dnsmasq-base
|
||||||
|
|
||||||
CFLAGS = $(shell export DEB_BUILD_OPTIONS=$(DEB_BUILD_OPTIONS); dpkg-buildflags --get CFLAGS)
|
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all" dpkg-buildflags
|
||||||
CFLAGS += $(shell dpkg-buildflags --get CPPFLAGS)
|
|
||||||
|
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
|
||||||
|
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
|
||||||
CFLAGS += -Wall -W
|
CFLAGS += -Wall -W
|
||||||
|
|
||||||
LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS)
|
LDFLAGS = $(shell $(dpkg_buildflags) --get LDFLAGS)
|
||||||
|
|
||||||
DEB_COPTS = $(COPTS)
|
DEB_COPTS = $(COPTS)
|
||||||
|
|
||||||
TARGET = install-i18n
|
TARGET = install-i18n
|
||||||
|
|
||||||
DEB_BUILD_ARCH_OS := $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS)
|
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
|
||||||
|
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
|
||||||
|
|
||||||
# Force package version based on git tags.
|
# Force package version based on git tags.
|
||||||
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
||||||
@@ -33,7 +36,7 @@ ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||||
ifeq ($(DEB_BUILD_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
DEB_COPTS += -DHAVE_CONNTRACK
|
DEB_COPTS += -DHAVE_CONNTRACK
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@@ -77,10 +80,15 @@ ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
|
|||||||
DEB_COPTS += -DHAVE_LUASCRIPT
|
DEB_COPTS += -DHAVE_LUASCRIPT
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter usednssec,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
|
||||||
DEB_COPTS += -DHAVE_DNSSEC
|
DEB_COPTS += -DHAVE_DNSSEC
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
|
# For strlcpy in FreeBSD
|
||||||
|
LDFLAGS += -lbsd
|
||||||
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
$(checkdir)
|
$(checkdir)
|
||||||
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
|
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||||
@@ -111,8 +119,9 @@ binary-indep: checkroot
|
|||||||
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
||||||
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
||||||
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
||||||
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/daemon
|
dpkg-gencontrol $(PACKAGE_VERSION) -T -pdnsmasq -Pdebian/daemon
|
||||||
|
find debian/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
chown -R root.root debian/daemon
|
chown -R root.root debian/daemon
|
||||||
chmod -R g-ws debian/daemon
|
chmod -R g-ws debian/daemon
|
||||||
dpkg --build debian/daemon ..
|
dpkg --build debian/daemon ..
|
||||||
@@ -126,46 +135,51 @@ binary-arch: checkroot
|
|||||||
-d debian/base/usr/share/doc/$(package) \
|
-d debian/base/usr/share/doc/$(package) \
|
||||||
-d debian/base/usr/share/doc/$(package)/examples \
|
-d debian/base/usr/share/doc/$(package)/examples \
|
||||||
-d debian/base/var/run \
|
-d debian/base/var/run \
|
||||||
|
-d debian/base/usr/share/$(package) \
|
||||||
-d debian/base/var/lib/misc
|
-d debian/base/var/lib/misc
|
||||||
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
||||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
||||||
install -m 644 doc.html debian/base/usr/share/doc/$(package)/.
|
# Need to remove paypal links in Debian Package for policy reasons.
|
||||||
|
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >debian/base/usr/share/doc/$(package)/doc.html
|
||||||
|
echo "</BODY>" >>debian/base/usr/share/doc/$(package)/doc.html
|
||||||
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
|
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
|
||||||
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
|
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
|
||||||
|
install -m 644 trust-anchors.conf debian/base/usr/share/$(package)/.
|
||||||
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
|
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/FAQ
|
gzip -9n debian/base/usr/share/doc/$(package)/FAQ
|
||||||
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
|
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/changelog
|
gzip -9n debian/base/usr/share/doc/$(package)/changelog
|
||||||
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
|
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/changelog.archive
|
gzip -9n debian/base/usr/share/doc/$(package)/changelog.archive
|
||||||
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/DBus-interface
|
gzip -9n debian/base/usr/share/doc/$(package)/DBus-interface
|
||||||
endif
|
endif
|
||||||
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
|
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
|
||||||
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
|
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
|
||||||
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
|
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
|
||||||
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
|
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
|
||||||
gzip -9 debian/base/usr/share/doc/$(package)/changelog.Debian
|
gzip -9n debian/base/usr/share/doc/$(package)/changelog.Debian
|
||||||
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
|
install -m 644 debian/readme debian/base/usr/share/doc/$(package)/README.Debian
|
||||||
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
|
install -m 644 debian/copyright debian/base/usr/share/doc/$(package)/copyright
|
||||||
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
|
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
|
||||||
gzip -9 debian/base/usr/share/man/man8/dnsmasq.8
|
gzip -9n debian/base/usr/share/man/man8/dnsmasq.8
|
||||||
for f in debian/base/usr/share/man/*; do \
|
for f in debian/base/usr/share/man/*; do \
|
||||||
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||||
gzip -9 $$f/man8/dnsmasq.8 ; \
|
gzip -9n $$f/man8/dnsmasq.8 ; \
|
||||||
fi \
|
fi \
|
||||||
done
|
done
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
||||||
endif
|
endif
|
||||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
|
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
|
||||||
|
find debian/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
chown -R root.root debian/base
|
chown -R root.root debian/base
|
||||||
chmod -R g-ws debian/base
|
chmod -R g-ws debian/base
|
||||||
dpkg --build debian/base ..
|
dpkg --build debian/base ..
|
||||||
|
|
||||||
ifeq ($(DEB_BUILD_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
rm -rf debian/utils
|
rm -rf debian/utils
|
||||||
install -m 755 -d debian/utils/DEBIAN \
|
install -m 755 -d debian/utils/DEBIAN \
|
||||||
-d debian/utils/usr/share/man/man1 \
|
-d debian/utils/usr/share/man/man1 \
|
||||||
@@ -174,20 +188,21 @@ ifeq ($(DEB_BUILD_ARCH_OS),linux)
|
|||||||
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
||||||
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
|
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
|
||||||
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
||||||
gzip -9 debian/utils/usr/share/man/man1/dhcp_release.1
|
gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
|
||||||
install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
||||||
install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
|
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||||
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
gzip -9 debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
gzip -9 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
gzip -9n debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
|
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
|
||||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
||||||
endif
|
endif
|
||||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | xargs -r0 md5sum > DEBIAN/md5sums
|
cd debian/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/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
|
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
|
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
|
||||||
|
find debian/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
chown -R root.root debian/utils
|
chown -R root.root debian/utils
|
||||||
chmod -R g-ws debian/utils
|
chmod -R g-ws debian/utils
|
||||||
dpkg --build debian/utils ..
|
dpkg --build debian/utils ..
|
||||||
|
|||||||
Vendored
+4
-9
@@ -1,9 +1,10 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=A lightweight DHCP and caching DNS server
|
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||||
|
Requires=network.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=dbus
|
Type=forking
|
||||||
BusName=uk.org.thekelleys.dnsmasq
|
PIDFile=/var/run/dnsmasq/dnsmasq.pid
|
||||||
|
|
||||||
# Test the config file and refuse starting if it is not valid.
|
# Test the config file and refuse starting if it is not valid.
|
||||||
ExecStartPre=/usr/sbin/dnsmasq --test
|
ExecStartPre=/usr/sbin/dnsmasq --test
|
||||||
@@ -11,12 +12,6 @@ ExecStartPre=/usr/sbin/dnsmasq --test
|
|||||||
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
||||||
# wrapper picking up extra configuration files and then execs dnsmasq
|
# wrapper picking up extra configuration files and then execs dnsmasq
|
||||||
# itself, when called with the "systemd-exec" function.
|
# itself, when called with the "systemd-exec" function.
|
||||||
#
|
|
||||||
# It also adds the command-line flags
|
|
||||||
# --keep-in-foreground --pid-file --enable-dbus
|
|
||||||
# to disable writing a pid-file (not needed with systemd) and
|
|
||||||
# enable DBus by default because we use DBus activation.
|
|
||||||
#
|
|
||||||
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
||||||
|
|
||||||
# The systemd-*-resolvconf functions configure (and deconfigure)
|
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||||
|
|||||||
@@ -20,6 +20,18 @@
|
|||||||
# Never forward addresses in the non-routed address spaces.
|
# Never forward addresses in the non-routed address spaces.
|
||||||
#bogus-priv
|
#bogus-priv
|
||||||
|
|
||||||
|
# Uncomment these to enable DNSSEC validation and caching:
|
||||||
|
# (Requires dnsmasq to be built with DNSSEC option.)
|
||||||
|
#conf-file=%%PREFIX%%/share/dnsmasq/trust-anchors.conf
|
||||||
|
#dnssec
|
||||||
|
|
||||||
|
# Replies which are not DNSSEC signed may be legitimate, because the domain
|
||||||
|
# is unsigned, or may be forgeries. Setting this option tells dnsmasq to
|
||||||
|
# check that an unsigned reply is OK, by finding a secure proof that a DS
|
||||||
|
# record somewhere between the root and the domain does not exist.
|
||||||
|
# The cost of setting this is that even queries in unsigned domains will need
|
||||||
|
# one or more extra DNS queries to verify.
|
||||||
|
#dnssec-check-unsigned
|
||||||
|
|
||||||
# Uncomment this to filter useless windows-originated DNS requests
|
# Uncomment this to filter useless windows-originated DNS requests
|
||||||
# which can trigger dial-on-demand links needlessly.
|
# which can trigger dial-on-demand links needlessly.
|
||||||
@@ -239,6 +251,13 @@
|
|||||||
# the IP address 192.168.0.60
|
# the IP address 192.168.0.60
|
||||||
#dhcp-host=id:01:02:02:04,192.168.0.60
|
#dhcp-host=id:01:02:02:04,192.168.0.60
|
||||||
|
|
||||||
|
# Always give the Infiniband interface with hardware address
|
||||||
|
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
|
||||||
|
# ip address 192.168.0.61. The client id is derived from the prefix
|
||||||
|
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
|
||||||
|
# hex digits of the hardware address.
|
||||||
|
#dhcp-host=id:ff:00:00:00:00:00:02:00:00:02:c9:00:f4:52:14:03:00:28:05:81,192.168.0.61
|
||||||
|
|
||||||
# Always give the host with client identifier "marjorie"
|
# Always give the host with client identifier "marjorie"
|
||||||
# the IP address 192.168.0.60
|
# the IP address 192.168.0.60
|
||||||
#dhcp-host=id:marjorie,192.168.0.60
|
#dhcp-host=id:marjorie,192.168.0.60
|
||||||
@@ -333,6 +352,14 @@
|
|||||||
# Ask client to poll for option changes every six hours. (RFC4242)
|
# Ask client to poll for option changes every six hours. (RFC4242)
|
||||||
#dhcp-option=option6:information-refresh-time,6h
|
#dhcp-option=option6:information-refresh-time,6h
|
||||||
|
|
||||||
|
# Set option 58 client renewal time (T1). Defaults to half of the
|
||||||
|
# lease time if not specified. (RFC2132)
|
||||||
|
#dhcp-option=option:T1:1m
|
||||||
|
|
||||||
|
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
||||||
|
# lease time if not specified. (RFC2132)
|
||||||
|
#dhcp-option=option:T2:2m
|
||||||
|
|
||||||
# Set the NTP time server address to be the same machine as
|
# Set the NTP time server address to be the same machine as
|
||||||
# is running dnsmasq
|
# is running dnsmasq
|
||||||
#dhcp-option=42,0.0.0.0
|
#dhcp-option=42,0.0.0.0
|
||||||
@@ -474,6 +501,9 @@
|
|||||||
# Set the root directory for files available via FTP.
|
# Set the root directory for files available via FTP.
|
||||||
#tftp-root=/var/ftpd
|
#tftp-root=/var/ftpd
|
||||||
|
|
||||||
|
# Do not abort if the tftp-root is unavailable
|
||||||
|
#tftp-no-fail
|
||||||
|
|
||||||
# Make the TFTP server more secure: with this set, only files owned by
|
# Make the TFTP server more secure: with this set, only files owned by
|
||||||
# the user dnsmasq is running as will be send over the net.
|
# the user dnsmasq is running as will be send over the net.
|
||||||
#tftp-secure
|
#tftp-secure
|
||||||
@@ -628,3 +658,9 @@
|
|||||||
# Include another lot of configuration options.
|
# Include another lot of configuration options.
|
||||||
#conf-file=/etc/dnsmasq.more.conf
|
#conf-file=/etc/dnsmasq.more.conf
|
||||||
#conf-dir=/etc/dnsmasq.d
|
#conf-dir=/etc/dnsmasq.d
|
||||||
|
|
||||||
|
# Include all the files in a directory except those ending in .bak
|
||||||
|
#conf-dir=/etc/dnsmasq.d,.bak
|
||||||
|
|
||||||
|
# Include all files in a directory which end in .conf
|
||||||
|
#conf-dir=/etc/dnsmasq.d/,*.conf
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
<HTML>
|
<HTML>
|
||||||
<HEAD>
|
<HEAD>
|
||||||
<TITLE> Dnsmasq - a DNS forwarder for NAT firewalls.</TITLE>
|
<TITLE> Dnsmasq - network services for small networks.</TITLE>
|
||||||
<link rel="icon"
|
<link rel="icon" href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
|
||||||
href="http://www.thekelleys.org.uk/dnsmasq/images/favicon.ico">
|
|
||||||
</HEAD>
|
</HEAD>
|
||||||
<BODY BGCOLOR="WHITE">
|
<BODY BGCOLOR="WHITE">
|
||||||
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||||
@@ -11,82 +10,48 @@
|
|||||||
<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
|
<td align="middle" valign="middle"><h1>Dnsmasq</h1></td>
|
||||||
<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
|
<td align="right" valign="middle"><img border="0" src="http://www.thekelleys.org.uk/dnsmasq/images/icon.png" /></td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
Dnsmasq provides network infrastructure for small networks: DNS, DHCP, router advertisement and network boot. It is designed to be
|
||||||
|
lightweight and have a small footprint, suitable for resource constrained routers and firewalls. It has also been widely used
|
||||||
|
for tethering on smartphones and portable hotspots, and to support virtual networking in virtualisation frameworks.
|
||||||
|
Supported platforms include Linux (with glibc and uclibc), Android, *BSD, and Mac OS X. Dnsmasq is included in most
|
||||||
|
Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmasq provides full IPv6 support.
|
||||||
|
|
||||||
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/PXE for network booting of diskless machines.
|
|
||||||
<P>
|
<P>
|
||||||
Dnsmasq is targeted at home networks using NAT and
|
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
|
||||||
connected to the internet via a modem, cable-modem or ADSL
|
cacheing of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
|
||||||
connection but would be a good choice for any smallish network (up to
|
|
||||||
1000 clients is known to work) where low
|
|
||||||
resource use and ease of configuration are important.
|
|
||||||
<P>
|
|
||||||
Supported platforms include Linux (with glibc and uclibc), Android, *BSD,
|
|
||||||
Solaris and Mac OS X.
|
|
||||||
Dnsmasq is included in at least the following Linux distributions:
|
|
||||||
Gentoo, Debian, Slackware, Suse, Fedora,
|
|
||||||
Smoothwall, IP-Cop, floppyfw, Firebox, LEAF, Freesco, fli4l,
|
|
||||||
CoyoteLinux, Endian Firewall and
|
|
||||||
Clarkconnect. It is also available as FreeBSD, OpenBSD and NetBSD ports and is used in
|
|
||||||
Linksys wireless routers (dd-wrt, openwrt and the stock firmware) and the m0n0wall project.
|
|
||||||
<P>
|
|
||||||
Dnsmasq provides the following features:
|
|
||||||
<DIR>
|
<DIR>
|
||||||
|
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
|
||||||
<LI>
|
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
|
||||||
The DNS configuration of machines behind the firewall is simple and
|
<LI>Authoritative DNS mode allows local DNS names may be exported to zone in the global DNS. Dnsmasq acts as authoritative server for this zone, and also provides
|
||||||
doesn't depend on the details of the ISP's dns servers
|
zone transfer to secondaries for the zone, if required.</LI>
|
||||||
<LI>
|
<LI>DNSSEC validation may be performed on DNS replies from upstream nameservers, providing security against spoofing and cache poisoning.</LI>
|
||||||
Clients which try to do DNS lookups while a modem link to the
|
<LI>Specified sub-domains can be directed to their own upstream DNS servers, making VPN configuration easy.</LI>
|
||||||
internet is down will time out immediately.
|
<LI>Internationalised domain names are supported.
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
Dnsmasq will serve names from the /etc/hosts file on the firewall
|
|
||||||
machine: If the names of local machines are there, then they can all
|
|
||||||
be addressed without having to maintain /etc/hosts on each machine.
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
The integrated DHCP server supports static and dynamic DHCP leases and
|
|
||||||
multiple networks and IP ranges. It works across BOOTP relays and
|
|
||||||
supports DHCP options including RFC3397 DNS search lists.
|
|
||||||
Machines which are configured by DHCP have their names automatically
|
|
||||||
included in the DNS and the names can specified by each machine or
|
|
||||||
centrally by associating a name with a MAC address in the dnsmasq
|
|
||||||
config file.
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
Dnsmasq caches internet addresses (A records and AAAA records) and address-to-name
|
|
||||||
mappings (PTR records), reducing the load on upstream servers and
|
|
||||||
improving performance (especially on modem connections).
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
Dnsmasq can be configured to automatically pick up the addresses of
|
|
||||||
its upstream nameservers from ppp or dhcp configuration. It will
|
|
||||||
automatically reload this information if it changes. This facility
|
|
||||||
will be of particular interest to maintainers of Linux firewall
|
|
||||||
distributions since it allows dns configuration to be made automatic.
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
On IPv6-enabled boxes, dnsmasq can both talk to upstream servers via IPv6
|
|
||||||
and offer DNS service via IPv6. On dual-stack (IPv4 and IPv6) boxes it talks
|
|
||||||
both protocols and can even act as IPv6-to-IPv4 or IPv4-to-IPv6 forwarder.
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
Dnsmasq can be configured to send queries for certain domains to
|
|
||||||
upstream servers handling only those domains. This makes integration
|
|
||||||
with private DNS systems easy.
|
|
||||||
</LI>
|
|
||||||
<LI>
|
|
||||||
Dnsmasq supports MX and SRV records and can be configured to return MX records
|
|
||||||
for any or all local machines.
|
|
||||||
</LI>
|
|
||||||
</DIR>
|
</DIR>
|
||||||
|
<P>
|
||||||
|
The DHCP subsystem supports DHCPv4, DHCPv6, BOOTP and PXE.
|
||||||
|
<DIR>
|
||||||
|
<LI> Both static and dynamic DHCP leases are supported, along with stateless mode in DHCPv6.</LI>
|
||||||
|
<LI> The PXE system is a full PXE server, supporting netboot menus and multiple architecture support. It
|
||||||
|
includes proxy-mode, where the PXE system co-operates with another DHCP server.</LI>
|
||||||
|
<LI> There is a built in read-only TFTP server to support netboot.</LI>
|
||||||
|
<LI> Machines which are configured by DHCP have their names automatically
|
||||||
|
included in the DNS and the names can specified by each machine or
|
||||||
|
centrally by associating a name with a MAC address or UID in the dnsmasq
|
||||||
|
configuration file.</LI>
|
||||||
|
</DIR>
|
||||||
|
<P>
|
||||||
|
The Router Advertisement subsystem provides basic autoconfiguration for IPv6 hosts. It can be used stand-alone or in conjunction with DHCPv6.
|
||||||
|
<DIR>
|
||||||
|
<LI> The M and O bits are configurable, to control hosts' use of DHCPv6.</LI>
|
||||||
|
<LI> Router advertisements can include the RDNSS option.</LI>
|
||||||
|
<LI> There is a mode which uses name information from DHCPv4 configuration to provide DNS entries
|
||||||
|
for autoconfigured IPv6 addresses which would otherwise be anonymous.</LI>
|
||||||
|
</DIR>
|
||||||
|
<P>
|
||||||
|
|
||||||
|
For extra compactness, unused features may be omitted at compile time.
|
||||||
|
|
||||||
|
|
||||||
<H2>Get code.</H2>
|
<H2>Get code.</H2>
|
||||||
|
|
||||||
@@ -102,15 +67,31 @@ the repo, or get a copy using git protocol with the command
|
|||||||
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
||||||
|
|
||||||
<H2>License.</H2>
|
<H2>License.</H2>
|
||||||
Dnsmasq is distributed under the GPL. See the file COPYING in the distribution
|
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
<H2>Contact.</H2>
|
<H2>Contact.</H2>
|
||||||
There is a dnsmasq mailing list at <A
|
There is a dnsmasq mailing list at <A
|
||||||
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
|
HREF="http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss">
|
||||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
|
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss</A> which should be the
|
||||||
first location for queries, bugreports, suggestions etc.
|
first location for queries, bugreports, suggestions etc. The list is mirrored, with a
|
||||||
Dnsmasq was written by Simon Kelley. You can contact me at <A
|
search facility, at <A HREF="https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/">
|
||||||
|
https://www.mail-archive.com/dnsmasq-discuss@lists.thekelleys.org.uk/</A>.
|
||||||
|
You can contact me at <A
|
||||||
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
|
HREF="mailto:simon@thekelleys.org.uk">simon@thekelleys.org.uk</A>.
|
||||||
|
|
||||||
|
<H2>Donations.</H2>
|
||||||
|
Dnsmasq is mainly written and maintained by Simon Kelley. For most of its life, dnsmasq has been a spare-time project.
|
||||||
|
These days I'm working on it as my main activity.
|
||||||
|
I don't have an employer or anyone who pays me regularly to work on dnsmasq. If you'd like to make
|
||||||
|
a contribution towards my expenses, please use the donation button below.
|
||||||
|
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
||||||
|
<input type="hidden" name="cmd" value="_s-xclick">
|
||||||
|
<input type="hidden" name="hosted_button_id" value="V3X9GVW5GX6DA">
|
||||||
|
<input type="image" src="https://www.paypalobjects.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online.">
|
||||||
|
<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
</BODY>
|
</BODY>
|
||||||
|
|
||||||
+168
-27
@@ -13,7 +13,10 @@ Dnsmasq accepts DNS queries and either answers them from a small, local,
|
|||||||
cache or forwards them to a real, recursive, DNS server. It loads the
|
cache or forwards them to a real, recursive, DNS server. It loads the
|
||||||
contents of /etc/hosts so that local hostnames
|
contents of /etc/hosts so that local hostnames
|
||||||
which do not appear in the global DNS can be resolved and also answers
|
which do not appear in the global DNS can be resolved and also answers
|
||||||
DNS queries for DHCP configured hosts. It can also act as the authoritative DNS server for one or more domains, allowing local names to appear in the global DNS.
|
DNS queries for DHCP configured hosts. It can also act as the
|
||||||
|
authoritative DNS server for one or more domains, allowing local names
|
||||||
|
to appear in the global DNS. It can be configured to do DNSSEC
|
||||||
|
validation.
|
||||||
.PP
|
.PP
|
||||||
The dnsmasq DHCP server supports static address assignments and multiple
|
The dnsmasq DHCP server supports static address assignments and multiple
|
||||||
networks. It automatically
|
networks. It automatically
|
||||||
@@ -47,6 +50,10 @@ Additional hosts file. Read the specified file as well as /etc/hosts. If -h is g
|
|||||||
only the specified file. This option may be repeated for more than one
|
only the specified file. This option may be repeated for more than one
|
||||||
additional hosts file. If a directory is given, then read all the files contained in that directory.
|
additional hosts file. If a directory is given, then read all the files contained in that directory.
|
||||||
.TP
|
.TP
|
||||||
|
.B --hostsdir=<path>
|
||||||
|
Read all the hosts files contained in the directory. New or changed files
|
||||||
|
are read automatically. See --dhcp-hostsdir for details.
|
||||||
|
.TP
|
||||||
.B \-E, --expand-hosts
|
.B \-E, --expand-hosts
|
||||||
Add the domain to simple names (without a period) in /etc/hosts
|
Add the domain to simple names (without a period) in /etc/hosts
|
||||||
in the same way as for DHCP-derived names. Note that this does not
|
in the same way as for DHCP-derived names. Note that this does not
|
||||||
@@ -78,6 +85,12 @@ the upstream DNS servers.
|
|||||||
.B --max-cache-ttl=<time>
|
.B --max-cache-ttl=<time>
|
||||||
Set a maximum TTL value for entries in the cache.
|
Set a maximum TTL value for entries in the cache.
|
||||||
.TP
|
.TP
|
||||||
|
.B --min-cache-ttl=<time>
|
||||||
|
Extend short TTL values to the time given when caching them. Note that
|
||||||
|
artificially extending TTL values is in general a bad idea, do not do it
|
||||||
|
unless you have a good reason, and understand what you are doing.
|
||||||
|
Dnsmasq limits the value of this option to one hour, unless recompiled.
|
||||||
|
.TP
|
||||||
.B --auth-ttl=<time>
|
.B --auth-ttl=<time>
|
||||||
Set the TTL value returned in answers from the authoritative server.
|
Set the TTL value returned in answers from the authoritative server.
|
||||||
.TP
|
.TP
|
||||||
@@ -95,7 +108,10 @@ only, to stop dnsmasq daemonising in production, use
|
|||||||
.B -k.
|
.B -k.
|
||||||
.TP
|
.TP
|
||||||
.B \-q, --log-queries
|
.B \-q, --log-queries
|
||||||
Log the results of DNS queries handled by dnsmasq. Enable a full cache dump on receipt of SIGUSR1.
|
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.
|
||||||
.TP
|
.TP
|
||||||
.B \-8, --log-facility=<facility>
|
.B \-8, --log-facility=<facility>
|
||||||
Set the facility to which dnsmasq will send syslog entries, this
|
Set the facility to which dnsmasq will send syslog entries, this
|
||||||
@@ -205,6 +221,14 @@ resolve in the global DNS to a A and/or AAAA record which points to
|
|||||||
the address dnsmasq is listening on. When an interface is specified,
|
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
|
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
||||||
addresses associated with the interface.
|
addresses associated with the interface.
|
||||||
|
.TP
|
||||||
|
.B --local-service
|
||||||
|
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
|
||||||
|
only has effect is there are no --interface --except-interface,
|
||||||
|
--listen-address or --auth-server 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>
|
.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 or TFTP on the specified interface, but do provide DNS service.
|
||||||
@@ -282,6 +306,12 @@ an advertising web page in response to queries for unregistered names,
|
|||||||
instead of the correct NXDOMAIN response. This option tells dnsmasq to
|
instead of the correct NXDOMAIN response. This option tells dnsmasq to
|
||||||
fake the correct response when it sees this behaviour. As at Sept 2003
|
fake the correct response when it sees this behaviour. As at Sept 2003
|
||||||
the IP address being returned by Verisign is 64.94.110.11
|
the IP address being returned by Verisign is 64.94.110.11
|
||||||
|
.TP
|
||||||
|
.B \-B, --ignore-address=<ipaddr>
|
||||||
|
Ignore replies to A-record queries which include the specified address.
|
||||||
|
No error is generated, dnsmasq simply continues to listen for another reply.
|
||||||
|
This is useful to defeat blocking strategies which rely on quickly supplying a
|
||||||
|
forged answer to a DNS request for certain domain, before the correct answer can arrive.
|
||||||
.TP
|
.TP
|
||||||
.B \-f, --filterwin2k
|
.B \-f, --filterwin2k
|
||||||
Later versions of windows make periodic DNS requests which don't get sensible answers from
|
Later versions of windows make periodic DNS requests which don't get sensible answers from
|
||||||
@@ -323,6 +353,16 @@ it will send queries to just one server. Setting this flag forces
|
|||||||
dnsmasq to send all queries to all available servers. The reply from
|
dnsmasq to send all queries to all available servers. The reply from
|
||||||
the server which answers first will be returned to the original requester.
|
the server which answers first will be returned to the original requester.
|
||||||
.TP
|
.TP
|
||||||
|
.B --dns-loop-detect
|
||||||
|
Enable code to detect DNS forwarding loops; ie the situation where a query sent to one
|
||||||
|
of the upstream server eventually returns as a new query to the dnsmasq instance. The
|
||||||
|
process works by generating TXT queries of the form <hex>.test and sending them to
|
||||||
|
each upstream server. The hex is a UID which encodes the instance of dnsmasq sending the query
|
||||||
|
and the upstream server to which it was sent. If the query returns to the server which sent it, then
|
||||||
|
the upstream server through which it was sent is disabled and this event is logged. Each time the
|
||||||
|
set of upstream servers changes, the test is re-run on all of them, including ones which
|
||||||
|
were previously disabled.
|
||||||
|
.TP
|
||||||
.B --stop-dns-rebind
|
.B --stop-dns-rebind
|
||||||
Reject (and log) addresses from upstream nameservers which are in the
|
Reject (and log) addresses from upstream nameservers which are in the
|
||||||
private IP ranges. This blocks an attack where a browser behind a
|
private IP ranges. This blocks an attack where a browser behind a
|
||||||
@@ -412,7 +452,15 @@ source address specified but the port may be specified directly as
|
|||||||
part of the source address. Forcing queries to an interface is not
|
part of the source address. Forcing queries to an interface is not
|
||||||
implemented on all platforms supported by dnsmasq.
|
implemented on all platforms supported by dnsmasq.
|
||||||
.TP
|
.TP
|
||||||
.B \-A, --address=/<domain>/[domain/]<ipaddr>
|
.B --rev-server=<ip-address>/<prefix-len>,<ipaddr>[#<port>][@<source-ip>|<interface>[#<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
|
||||||
|
.TP
|
||||||
|
.B \-A, --address=/<domain>/[domain/][<ipaddr>]
|
||||||
Specify an IP address to return for any host in the given domains.
|
Specify an IP address to return for any host in the given domains.
|
||||||
Queries in the domains are never forwarded and always replied to
|
Queries in the domains are never forwarded and always replied to
|
||||||
with the specified IP address which may be IPv4 or IPv6. To give
|
with the specified IP address which may be IPv4 or IPv6. To give
|
||||||
@@ -424,7 +472,10 @@ domain specification works in the same was as for --server, with the
|
|||||||
additional facility that /#/ matches any domain. Thus
|
additional facility that /#/ matches any domain. Thus
|
||||||
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
|
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
|
||||||
answered from /etc/hosts or DHCP and not sent to an upstream
|
answered from /etc/hosts or DHCP and not sent to an upstream
|
||||||
nameserver by a more specific --server directive.
|
nameserver by a more specific --server directive. As for --server,
|
||||||
|
one or more domains with no address returns a no-such-domain answer, so
|
||||||
|
--address=/example.com/ is equivalent to --server=/example.com/ and returns
|
||||||
|
NXDOMAIN for example.com and all its subdomains.
|
||||||
.TP
|
.TP
|
||||||
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
|
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
|
||||||
Places the resolved IP addresses of queries for the specified domains
|
Places the resolved IP addresses of queries for the specified domains
|
||||||
@@ -468,7 +519,7 @@ zone files: the port, weight and priority numbers are in a different
|
|||||||
order. More than one SRV record for a given service/domain is allowed,
|
order. More than one SRV record for a given service/domain is allowed,
|
||||||
all that match are returned.
|
all that match are returned.
|
||||||
.TP
|
.TP
|
||||||
.B --host-record=<name>[,<name>....][<IPv4-address>],[<IPv6-address>]
|
.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>]
|
||||||
Add A, AAAA and PTR records to the DNS. This adds one or more names to
|
Add A, AAAA and PTR records to the DNS. This adds one or more names to
|
||||||
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
|
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
|
||||||
appear in more than one
|
appear in more than one
|
||||||
@@ -587,12 +638,51 @@ validation by clients more efficient. Note that validation by clients is the mos
|
|||||||
clients unable to do validation, use of the AD bit set by dnsmasq is useful, provided that the network between
|
clients unable to do validation, use of the AD bit set by dnsmasq is useful, provided that the network between
|
||||||
the dnsmasq server and the client is trusted. Dnsmasq must be compiled with HAVE_DNSSEC enabled, and DNSSEC
|
the dnsmasq server and the client is trusted. Dnsmasq must be compiled with HAVE_DNSSEC enabled, and DNSSEC
|
||||||
trust anchors provided, see
|
trust anchors provided, see
|
||||||
.B --dnsskey.
|
.B --trust-anchor.
|
||||||
Because the DNSSEC validation process uses the cache, it is not permitted to reduce the cache size below the default when DNSSEC is enabled.
|
Because the DNSSEC validation process uses the cache, it is not
|
||||||
|
permitted to reduce the cache size below the default when DNSSEC is
|
||||||
|
enabled. The nameservers upstream of dnsmasq must be DNSSEC-capable,
|
||||||
|
ie capable of returning DNSSEC records with data. If they are not,
|
||||||
|
then dnsmasq will not be able to determine the trusted status of
|
||||||
|
answers. In the default mode, this menas that all replies will be
|
||||||
|
marked as untrusted. If
|
||||||
|
.B --dnssec-check-unsigned
|
||||||
|
is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
|
||||||
.TP
|
.TP
|
||||||
.B --dnskey=[<class>],<domain>,<flags>,<algorithm>,<base64-key>
|
.B --trust-anchor=[<class>],<domain>,<key-tag>,<algorithm>,<digest-type>,<digest>
|
||||||
Provide DNSKEY records to act a trust anchors for DNSSEC validation. Typically these will be the keys for root zone,
|
Provide DS records to act a trust anchors for DNSSEC
|
||||||
but trust anchors for limited domains are also possible.
|
validation. Typically these will be the DS record(s) for Zone Signing
|
||||||
|
key(s) of the root zone,
|
||||||
|
but trust anchors for limited domains are also possible. The current
|
||||||
|
root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||||
|
.TP
|
||||||
|
.B --dnssec-check-unsigned
|
||||||
|
As a default, dnsmasq does not check that unsigned DNS replies are
|
||||||
|
legitimate: they are assumed to be valid and passed on (without the
|
||||||
|
"authentic data" bit set, of course). This does not protect against an
|
||||||
|
attacker forging unsigned replies for signed DNS zones, but it is
|
||||||
|
fast. If this flag is set, dnsmasq will check the zones of unsigned
|
||||||
|
replies, to ensure that unsigned replies are allowed in those
|
||||||
|
zones. The cost of this is more upstream queries and slower
|
||||||
|
performance. See also the warning about upstream servers in the
|
||||||
|
section on
|
||||||
|
.B --dnssec
|
||||||
|
.TP
|
||||||
|
.B --dnssec-no-timecheck
|
||||||
|
DNSSEC signatures are only valid for specified time windows, and should be rejected outside those windows. This generates an
|
||||||
|
interesting chicken-and-egg problem for machines which don't have a hardware real time clock. For these machines to determine the correct
|
||||||
|
time typically requires use of NTP and therefore DNS, but validating DNS requires that the correct time is already known. Setting this flag
|
||||||
|
removes the time-window checks (but not other DNSSEC validation.) only until the dnsmasq process receives SIGHUP. The intention is
|
||||||
|
that dnsmasq should be started with this flag when the platform determines that reliable time is not currently available. As soon as
|
||||||
|
reliable time is established, a SIGHUP should be sent to dnsmasq, which enables time checking, and purges the cache of DNS records
|
||||||
|
which have not been throughly checked.
|
||||||
|
.TP
|
||||||
|
.B --dnssec-timestamp=<path>
|
||||||
|
Enables an alternative way of checking the validity of the system time for DNSSEC (see --dnssec-no-timecheck). In this case, the
|
||||||
|
system time is considered to be valid once it becomes later than the timestamp on the specified file. The file is created and
|
||||||
|
its timestamp set automatically by dnsmasq. The file must be stored on a persistent filesystem, so that it and its mtime are carried
|
||||||
|
over system restarts. The timestamp file is created after dnsmasq has dropped root, so it must be in a location writable by the
|
||||||
|
unprivileged user that dnsmasq runs as.
|
||||||
.TP
|
.TP
|
||||||
.B --proxy-dnssec
|
.B --proxy-dnssec
|
||||||
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
|
Copy the DNSSEC Authenticated Data bit from upstream servers to downstream clients and cache it. This is an
|
||||||
@@ -601,7 +691,10 @@ dnsmasq and the upstream servers, and the trustworthiness of the upstream server
|
|||||||
.TP
|
.TP
|
||||||
.B --dnssec-debug
|
.B --dnssec-debug
|
||||||
Set debugging mode for the DNSSEC validation, set the Checking Disabled bit on upstream queries,
|
Set debugging mode for the DNSSEC validation, set the Checking Disabled bit on upstream queries,
|
||||||
and don't convert BOGUS replies to SERVFAIL responses.
|
and don't convert replies which do not validate to responses with
|
||||||
|
a return code of SERVFAIL. Note that
|
||||||
|
setting this may affect DNS behaviour in bad ways, it is not an
|
||||||
|
extra-logging flag and should not be set in production.
|
||||||
.TP
|
.TP
|
||||||
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
|
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
|
||||||
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
||||||
@@ -621,7 +714,7 @@ Interface-name and address-literal subnet specifications may be used
|
|||||||
freely in the same --auth-zone declaration.
|
freely in the same --auth-zone declaration.
|
||||||
|
|
||||||
The subnet(s) are also used to define in-addr.arpa and
|
The subnet(s) are also used to define in-addr.arpa and
|
||||||
ipv6.arpa domains which are served for reverse-DNS queries. If not
|
ip6.arpa domains which are served for reverse-DNS queries. If not
|
||||||
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
|
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
|
||||||
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
|
For IPv4 subnets, the prefix length should be have the value 8, 16 or 24
|
||||||
unless you are familiar with RFC 2317 and have arranged the
|
unless you are familiar with RFC 2317 and have arranged the
|
||||||
@@ -728,7 +821,7 @@ or from /etc/ethers will be served. A static-only subnet with address
|
|||||||
all zeros may be used as a "catch-all" address to enable replies to all
|
all zeros may be used as a "catch-all" address to enable replies to all
|
||||||
Information-request packets on a subnet which is provided with
|
Information-request packets on a subnet which is provided with
|
||||||
stateless DHCPv6, ie
|
stateless DHCPv6, ie
|
||||||
.B --dhcp=range=::,static
|
.B --dhcp-range=::,static
|
||||||
|
|
||||||
For IPv4, the <mode> may be
|
For IPv4, the <mode> may be
|
||||||
.B proxy
|
.B proxy
|
||||||
@@ -740,7 +833,7 @@ and
|
|||||||
for details.)
|
for details.)
|
||||||
|
|
||||||
For IPv6, the mode may be some combination of
|
For IPv6, the mode may be some combination of
|
||||||
.B ra-only, slaac, ra-names, ra-stateless.
|
.B ra-only, slaac, ra-names, ra-stateless, ra-advrouter, off-link.
|
||||||
|
|
||||||
.B ra-only
|
.B ra-only
|
||||||
tells dnsmasq to offer Router Advertisement only on this subnet,
|
tells dnsmasq to offer Router Advertisement only on this subnet,
|
||||||
@@ -775,6 +868,14 @@ can be combined with
|
|||||||
and
|
and
|
||||||
.B slaac.
|
.B slaac.
|
||||||
|
|
||||||
|
.B ra-advrouter
|
||||||
|
enables a mode where router address(es) rather than prefix(es) are included in the advertisements.
|
||||||
|
This is described in RFC-3775 section 7.2 and is used in mobile IPv6. In this mode the interval option
|
||||||
|
is also included, as described in RFC-3775 section 7.3.
|
||||||
|
|
||||||
|
.B off-link
|
||||||
|
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||||
Specify per host parameters for the DHCP server. This allows a machine
|
Specify per host parameters for the DHCP server. This allows a machine
|
||||||
@@ -893,6 +994,18 @@ is given, then read all the files contained in that directory. The advantage of
|
|||||||
using this option is the same as for --dhcp-hostsfile: the
|
using this option is the same as for --dhcp-hostsfile: the
|
||||||
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
|
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
|
||||||
it is possible to encode the information in a
|
it is possible to encode the information in a
|
||||||
|
.TP
|
||||||
|
.B --dhcp-hostsdir=<path>
|
||||||
|
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
|
||||||
|
directory, and not an individual file. Changed or new files within
|
||||||
|
the directory are read automatically, without the need to send SIGHUP.
|
||||||
|
If a file is deleted for changed after it has been read by dnsmasq, then the
|
||||||
|
host record it contained will remain until dnsmasq recieves a SIGHUP, or
|
||||||
|
is restarted; ie host records are only added dynamically.
|
||||||
|
.TP
|
||||||
|
.B --dhcp-optsdir=<path>
|
||||||
|
This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
|
||||||
|
.TP
|
||||||
.B --dhcp-boot
|
.B --dhcp-boot
|
||||||
flag as DHCP options, using the options names bootfile-name,
|
flag as DHCP options, using the options names bootfile-name,
|
||||||
server-ip-address and tftp-server. This allows these to be included
|
server-ip-address and tftp-server. This allows these to be included
|
||||||
@@ -1278,7 +1391,7 @@ enables dynamic allocation. With tags, only when the tags are all
|
|||||||
set. It may be repeated with different tag sets.
|
set. It may be repeated with different tag sets.
|
||||||
.TP
|
.TP
|
||||||
.B \-5, --no-ping
|
.B \-5, --no-ping
|
||||||
(IPv4 only) By default, the DHCP server will attempt to ensure that an address in
|
(IPv4 only) By default, the DHCP server will attempt to ensure that an address is
|
||||||
not in use before allocating it to a host. It does this by sending an
|
not in use before allocating it to a host. It does this by sending an
|
||||||
ICMP echo request (aka "ping") to the address in question. If it gets
|
ICMP echo request (aka "ping") to the address in question. If it gets
|
||||||
a reply, then the address must already be in use, and another is
|
a reply, then the address must already be in use, and another is
|
||||||
@@ -1487,10 +1600,13 @@ option also forces the leasechange script to be called on changes
|
|||||||
to the client-id and lease length and expiry time.
|
to the client-id and lease length and expiry time.
|
||||||
.TP
|
.TP
|
||||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||||
Treat DHCP request packets arriving at any of the <alias> interfaces
|
Treat DHCP (v4 and v6) request and IPv6 Router Solicit packets
|
||||||
as if they had arrived at <interface>. This option is necessary when
|
arriving at any of the <alias> interfaces as if they had arrived at
|
||||||
using "old style" bridging on BSD platforms, since
|
<interface>. This option allows dnsmasq to provide DHCP and RA
|
||||||
packets arrive at tap interfaces which don't have an IP address.
|
service over unaddressed and unbridged Ethernet interfaces, e.g. on an
|
||||||
|
OpenStack compute host where each such interface is a TAP interface to
|
||||||
|
a VM, or as in "old style bridging" on BSD platforms. A trailing '*'
|
||||||
|
wildcard can be used in each <alias>.
|
||||||
.TP
|
.TP
|
||||||
.B \-s, --domain=<domain>[,<address range>[,local]]
|
.B \-s, --domain=<domain>[,<address range>[,local]]
|
||||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||||
@@ -1600,6 +1716,9 @@ Absolute paths (starting with /) are allowed, but they must be within
|
|||||||
the tftp-root. If the optional interface argument is given, the
|
the tftp-root. If the optional interface argument is given, the
|
||||||
directory is only used for TFTP requests via that interface.
|
directory is only used for TFTP requests via that interface.
|
||||||
.TP
|
.TP
|
||||||
|
.B --tftp-no-fail
|
||||||
|
Do not abort startup if specified tftp root directories are inaccessible.
|
||||||
|
.TP
|
||||||
.B --tftp-unique-root
|
.B --tftp-unique-root
|
||||||
Add the IP address of the TFTP client as a path component on the end
|
Add the IP address of the TFTP client as a path component on the end
|
||||||
of the TFTP-root (in standard dotted-quad format). Only valid if a
|
of the TFTP-root (in standard dotted-quad format). Only valid if a
|
||||||
@@ -1655,12 +1774,23 @@ Specify a different configuration file. The conf-file option is also allowed in
|
|||||||
configuration files, to include multiple configuration files. A
|
configuration files, to include multiple configuration files. A
|
||||||
filename of "-" causes dnsmasq to read configuration from stdin.
|
filename of "-" causes dnsmasq to read configuration from stdin.
|
||||||
.TP
|
.TP
|
||||||
.B \-7, --conf-dir=<directory>[,<file-extension>......]
|
.B \-7, --conf-dir=<directory>[,<file-extension>......],
|
||||||
Read all the files in the given directory as configuration
|
Read all the files in the given directory as configuration
|
||||||
files. If extension(s) are given, any files which end in those
|
files. If extension(s) are given, any files which end in those
|
||||||
extensions are skipped. Any files whose names end in ~ or start with . or start and end
|
extensions are skipped. Any files whose names end in ~ or start with . or start and end
|
||||||
with # are always skipped. This flag may be given on the command
|
with # are always skipped. If the extension starts with * then only files
|
||||||
line or in a configuration file.
|
which have that extension are loaded. So
|
||||||
|
.B --conf-dir=/path/to/dir,*.conf
|
||||||
|
loads all files with the suffix .conf in /path/to/dir. This flag may be given on the command
|
||||||
|
line or in a configuration file. If giving it on the command line, be sure to
|
||||||
|
escape * characters.
|
||||||
|
.TP
|
||||||
|
.B --servers-file=<file>
|
||||||
|
A special case of
|
||||||
|
.B --conf-file
|
||||||
|
which differs in two respects. Firstly, only --server and --rev-server are allowed
|
||||||
|
in the configuration file included. Secondly, the file is re-read and the configuration
|
||||||
|
therein is updated when dnsmasq recieves SIGHUP.
|
||||||
.SH CONFIG FILE
|
.SH CONFIG FILE
|
||||||
At startup, dnsmasq reads
|
At startup, dnsmasq reads
|
||||||
.I /etc/dnsmasq.conf,
|
.I /etc/dnsmasq.conf,
|
||||||
@@ -1686,7 +1816,8 @@ clears its cache and then re-loads
|
|||||||
.I /etc/hosts
|
.I /etc/hosts
|
||||||
and
|
and
|
||||||
.I /etc/ethers
|
.I /etc/ethers
|
||||||
and any file given by --dhcp-hostsfile, --dhcp-optsfile or --addn-hosts.
|
and any file given by --dhcp-hostsfile, --dhcp-hostsdir, --dhcp-optsfile,
|
||||||
|
--dhcp-optsdir, --addn-hosts or --hostsdir.
|
||||||
The dhcp lease change script is called for all
|
The dhcp lease change script is called for all
|
||||||
existing DHCP leases. If
|
existing DHCP leases. If
|
||||||
.B
|
.B
|
||||||
@@ -1701,12 +1832,22 @@ When it receives a SIGUSR1,
|
|||||||
writes statistics to the system log. It writes the cache size,
|
writes statistics to the system log. It writes the cache size,
|
||||||
the number of names which have had to removed from the cache before
|
the number of names which have had to removed from the cache before
|
||||||
they expired in order to make room for new names and the total number
|
they expired in order to make room for new names and the total number
|
||||||
of names that have been inserted into the cache. For each upstream
|
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
|
server it gives the number of queries sent, and the number which
|
||||||
resulted in an error. In
|
resulted in an error. In
|
||||||
.B --no-daemon
|
.B --no-daemon
|
||||||
mode or when full logging is enabled (-q), a complete dump of the
|
mode or when full logging is enabled (-q), a complete dump of the
|
||||||
contents of the cache is made.
|
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
|
.PP
|
||||||
When it receives SIGUSR2 and it is logging direct to a file (see
|
When it receives SIGUSR2 and it is logging direct to a file (see
|
||||||
.B --log-facility
|
.B --log-facility
|
||||||
@@ -1810,7 +1951,7 @@ which has tags will be used in preference to an untagged
|
|||||||
.B dhcp-option,
|
.B dhcp-option,
|
||||||
provided that _all_ the tags match somewhere in the
|
provided that _all_ the tags match somewhere in the
|
||||||
set collected as described above. The prefix '!' on a tag means 'not'
|
set collected as described above. The prefix '!' on a tag means 'not'
|
||||||
so --dhcp=option=tag:!purple,3,1.2.3.4 sends the option when the
|
so --dhcp-option=tag:!purple,3,1.2.3.4 sends the option when the
|
||||||
tag purple is not in the set of valid tags. (If using this in a
|
tag purple is not in the set of valid tags. (If using this in a
|
||||||
command line rather than a configuration file, be sure to escape !,
|
command line rather than a configuration file, be sure to escape !,
|
||||||
which is a shell metacharacter)
|
which is a shell metacharacter)
|
||||||
@@ -1962,7 +2103,7 @@ to particular hosts then
|
|||||||
will do so.
|
will do so.
|
||||||
|
|
||||||
Dnsmasq acts as an authoritative server for in-addr.arpa and
|
Dnsmasq acts as an authoritative server for in-addr.arpa and
|
||||||
ipv6.arpa domains associated with the subnets given in auth-zone
|
ip6.arpa domains associated with the subnets given in auth-zone
|
||||||
declarations, so reverse (address to name) lookups can be simply
|
declarations, so reverse (address to name) lookups can be simply
|
||||||
configured with a suitable NS record, for instance in this example,
|
configured with a suitable NS record, for instance in this example,
|
||||||
where we allow 1.2.3.0/24 addresses.
|
where we allow 1.2.3.0/24 addresses.
|
||||||
|
|||||||
+8
-4
@@ -1062,10 +1062,14 @@ esta opci
|
|||||||
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
|
cuando hay cambios hechos a el client-id y tiempos de arriendo y vencimiento.
|
||||||
.TP
|
.TP
|
||||||
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
|
.B --bridge-interface=<nombre de interface>,<alias>[,<alias>]
|
||||||
Tratar paquetes de pedidos DHCP que llegan a cualquiera de las interfaces <alias>
|
Tratar paquetes de pedidos DHCP (v4 y v6) y de IPv6 Router Solicit que
|
||||||
como si hubieran llegado a la interface <nombre de interface>. Esta opción
|
llegan a cualquiera de las interfaces <alias> como si hubieran llegado
|
||||||
es necesaria al usar bridging estilo viejo en plataformas BSD, dado a que
|
a la interface <nombre de interface>. Esta opción permite que dnsmasq
|
||||||
los paquetes llegan a interfaces tap que no tienen una dirección IP.
|
puede proporcionar los servicios DHCP y RA a través de interfaces
|
||||||
|
ethernet sin dirección y sin puente; por ejemplo en un nodo de cálculo
|
||||||
|
de OpenStack, donde cada una de esas interfaces es una interfaz TAP
|
||||||
|
para una máquina virtual, o al usar bridging estilo viejo en
|
||||||
|
plataformas BSD.
|
||||||
.TP
|
.TP
|
||||||
.B \-s, --domain=<dominio>[,<rango de IPs>]
|
.B \-s, --domain=<dominio>[,<rango de IPs>]
|
||||||
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
|
Especifica los dominios DNS para el servidor DHCP. Dominios pueden ser
|
||||||
|
|||||||
+14
-8
@@ -706,7 +706,7 @@ l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage D
|
|||||||
(ce comportement peut-être désactivé par
|
(ce comportement peut-être désactivé par
|
||||||
.B constructor-noauth:
|
.B constructor-noauth:
|
||||||
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
|
). Le ou les sous-réseaux sont également utilisé(s) pour définir les domaines
|
||||||
in-addr.arpa et ipv6.arpa servant à l'interrogation DNS inverse. Si la longueur
|
in-addr.arpa et ip6.arpa servant à l'interrogation DNS inverse. Si la longueur
|
||||||
de préfixe n'est pas spécifiée, elle sera par défaut de 24 pour IPv4 et 64 pour
|
de préfixe n'est pas spécifiée, elle sera par défaut de 24 pour IPv4 et 64 pour
|
||||||
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait-être de 8, 16
|
IPv6. Dans le cas d'IPv4, la longueur du masque de réseau devrait-être de 8, 16
|
||||||
ou 24, sauf si en cas de mise en place d'une délégation de la zone in-addr.arpa
|
ou 24, sauf si en cas de mise en place d'une délégation de la zone in-addr.arpa
|
||||||
@@ -852,7 +852,7 @@ et
|
|||||||
pour plus de détails).
|
pour plus de détails).
|
||||||
|
|
||||||
Pour IPv6, le mode peut-être une combinaison des valeurs
|
Pour IPv6, le mode peut-être une combinaison des valeurs
|
||||||
.B ra-only, slaac, ra-names, ra-stateless.
|
.B ra-only, slaac, ra-names, ra-stateless, off-link.
|
||||||
|
|
||||||
.B ra-only
|
.B ra-only
|
||||||
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
|
indique à dnsmasq de n'effectuer que des annonces de routeur (Router
|
||||||
@@ -888,6 +888,9 @@ peut-être combiné avec
|
|||||||
et
|
et
|
||||||
.B slaac.
|
.B slaac.
|
||||||
|
|
||||||
|
.B off-link
|
||||||
|
indique à dnsmasq d'annoncer le préfixe sans le bit L (sur lien).
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
|
.B \-G, --dhcp-host=[<adresse matérielle>][,id:<identifiant client>|*][,set:<label>][,<adresse IP>][,<nom d'hôte>][,<durée de bail>][,ignore]
|
||||||
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
|
Spécifie les paramètres DHCP relatifs à un hôte. Cela permet à une machine
|
||||||
@@ -1655,11 +1658,14 @@ changement d'état de bail à chaque changement de l'identifiant de client, de
|
|||||||
longueur de bail ou de date d'expiration.
|
longueur de bail ou de date d'expiration.
|
||||||
.TP
|
.TP
|
||||||
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
.B --bridge-interface=<interface>,<alias>[,<alias>]
|
||||||
Traiter les requêtes DHCP arrivant sur n'importe laquelle des interfaces <alias>
|
Traiter les requêtes DHCP (v4 et v6) et IPv6 Router Solicit arrivant
|
||||||
comme si elles arrivaient de l'interface <interface>. Cette option est
|
sur n'importe laquelle des interfaces <alias> comme si elles
|
||||||
nécessaire lors de l'utilisation de pont ethernet "ancien mode" sur plate-forme
|
arrivaient de l'interface <interface>. Cette option permet à dnsmasq
|
||||||
BSD, puisque dans ce cas les paquets arrivent sur des interfaces "tap" n'ont
|
de fournir les service DHCP et RA sur les interfaces ethernet non
|
||||||
pas d'adresse IP.
|
adressés et non pontés; par exemple sur un hôte de calcul d'OpenStack
|
||||||
|
où chaque telle interface est une interface TAP à une machine
|
||||||
|
virtuelle, ou lors de l'utilisation de pont ethernet "ancien mode" sur
|
||||||
|
plate-forme BSD. Chaque <alias> peut finir avec un simple '*' joker.
|
||||||
.TP
|
.TP
|
||||||
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
|
.B \-s, --domain=<domaine>[,<gamme d'adresses>[,local]]
|
||||||
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
|
Spécifie le domaine du serveur DHCP. Le domaine peut être donné de manière
|
||||||
@@ -2186,7 +2192,7 @@ spécifiques, vous pouvez le faire via :
|
|||||||
.fi
|
.fi
|
||||||
|
|
||||||
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
|
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
|
||||||
et ipv6.arpa associés aux sous-réseaux définis dans la déclaration de zone
|
et ip6.arpa associés aux sous-réseaux définis dans la déclaration de zone
|
||||||
auth-zone, ce qui fait que les requêtes DNS inversées (de l'adresse vers
|
auth-zone, ce qui fait que les requêtes DNS inversées (de l'adresse vers
|
||||||
le nom) peuvent-simplement être configurées avec un enregistrement NS
|
le nom) peuvent-simplement être configurées avec un enregistrement NS
|
||||||
adéquat. Par exemple, comme nous définissons plus haut les adresses
|
adéquat. Par exemple, comme nous définissons plus haut les adresses
|
||||||
|
|||||||
+763
-508
File diff suppressed because it is too large.
Load diff
+51
-30
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,7 +31,7 @@ static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all
|
|||||||
if (!(flag & F_IPV4))
|
if (!(flag & F_IPV4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
netmask.s_addr = htonl(~((1 << (32 - subnet->prefixlen)) - 1));
|
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));
|
||||||
|
|
||||||
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
|
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
|
||||||
return subnet;
|
return subnet;
|
||||||
@@ -131,24 +131,27 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_PTR)
|
if ((qtype == T_PTR || qtype == T_SOA || qtype == T_NS) &&
|
||||||
|
(flag = in_arpa_name_2_addr(name, &addr)) &&
|
||||||
|
!local_query)
|
||||||
{
|
{
|
||||||
if (!(flag = in_arpa_name_2_addr(name, &addr)))
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
continue;
|
if ((subnet = find_subnet(zone, flag, &addr)))
|
||||||
|
break;
|
||||||
if (!local_query)
|
|
||||||
|
if (!zone)
|
||||||
{
|
{
|
||||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
auth = 0;
|
||||||
if ((subnet = find_subnet(zone, flag, &addr)))
|
continue;
|
||||||
break;
|
|
||||||
|
|
||||||
if (!zone)
|
|
||||||
{
|
|
||||||
auth = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else if (qtype == T_SOA)
|
||||||
|
soa = 1, found = 1;
|
||||||
|
else if (qtype == T_NS)
|
||||||
|
ns = 1, found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype == T_PTR && flag)
|
||||||
|
{
|
||||||
intr = NULL;
|
intr = NULL;
|
||||||
|
|
||||||
if (flag == F_IPV4)
|
if (flag == F_IPV4)
|
||||||
@@ -186,7 +189,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (intr)
|
if (intr)
|
||||||
{
|
{
|
||||||
if (in_zone(zone, intr->name, NULL))
|
if (local_query || in_zone(zone, intr->name, NULL))
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
log_query(flag | F_REVERSE | F_CONFIG, intr->name, &addr, NULL);
|
||||||
@@ -208,8 +211,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
*p = 0; /* must be bare name */
|
*p = 0; /* must be bare name */
|
||||||
|
|
||||||
/* add external domain */
|
/* add external domain */
|
||||||
strcat(name, ".");
|
if (zone)
|
||||||
strcat(name, zone->domain);
|
{
|
||||||
|
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));
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -217,7 +223,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
T_PTR, C_IN, "d", name))
|
T_PTR, C_IN, "d", name))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
else if (crecp->flags & (F_DHCP | F_HOSTS) && in_zone(zone, name, NULL))
|
else if (crecp->flags & (F_DHCP | F_HOSTS) && (local_query || in_zone(zone, name, NULL)))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
log_query(crecp->flags & ~F_FORWARD, name, &addr, record_source(crecp->uid));
|
||||||
found = 1;
|
found = 1;
|
||||||
@@ -231,21 +237,29 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
} while ((crecp = cache_find_by_addr(crecp, &addr, now, flag)));
|
||||||
|
|
||||||
if (!found)
|
if (found)
|
||||||
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | F_AUTH, NULL, &addr, NULL);
|
nxdomain = 0;
|
||||||
|
else
|
||||||
|
log_query(flag | F_NEG | F_NXDOMAIN | F_REVERSE | (auth ? F_AUTH : 0), NULL, &addr, NULL);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cname_restart:
|
cname_restart:
|
||||||
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
if (found)
|
||||||
if (in_zone(zone, name, &cut))
|
/* NS and SOA .arpa requests have set found above. */
|
||||||
break;
|
cut = NULL;
|
||||||
|
else
|
||||||
if (!zone)
|
|
||||||
{
|
{
|
||||||
auth = 0;
|
for (zone = daemon->auth_zones; zone; zone = zone->next)
|
||||||
continue;
|
if (in_zone(zone, name, &cut))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!zone)
|
||||||
|
{
|
||||||
|
auth = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
@@ -361,6 +375,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
|
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
|
||||||
(local_query || filter_zone(zone, flag, &addrlist->addr)))
|
(local_query || filter_zone(zone, flag, &addrlist->addr)))
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (addrlist->flags & ADDRLIST_REVONLY)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -407,7 +425,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
peer_addr->in.sin_port = 0;
|
peer_addr->in.sin_port = 0;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
peer_addr->in6.sin6_port = 0;
|
{
|
||||||
|
peer_addr->in6.sin6_port = 0;
|
||||||
|
peer_addr->in6.sin6_scope_id = 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
||||||
|
|||||||
+11
-6
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -25,7 +25,7 @@ static void blockdata_expand(int n)
|
|||||||
{
|
{
|
||||||
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
struct blockdata *new = whine_malloc(n * sizeof(struct blockdata));
|
||||||
|
|
||||||
if (new)
|
if (n > 0 && new)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -46,14 +46,19 @@ void blockdata_init(void)
|
|||||||
blockdata_alloced = 0;
|
blockdata_alloced = 0;
|
||||||
blockdata_count = 0;
|
blockdata_count = 0;
|
||||||
blockdata_hwm = 0;
|
blockdata_hwm = 0;
|
||||||
|
|
||||||
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
|
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
|
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockdata_report(void)
|
void blockdata_report(void)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
blockdata_count * sizeof(struct blockdata), blockdata_hwm * sizeof(struct blockdata), blockdata_alloced * sizeof(struct blockdata));
|
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
|
||||||
|
blockdata_count * sizeof(struct blockdata),
|
||||||
|
blockdata_hwm * sizeof(struct blockdata),
|
||||||
|
blockdata_alloced * sizeof(struct blockdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct blockdata *blockdata_alloc(char *data, size_t len)
|
struct blockdata *blockdata_alloc(char *data, size_t len)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -359,7 +359,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
|||||||
iov[3].iov_base = mess;
|
iov[3].iov_base = mess;
|
||||||
iov[3].iov_len = len;
|
iov[3].iov_len = len;
|
||||||
|
|
||||||
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
|
while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
|
#endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
|
||||||
@@ -376,7 +376,7 @@ void route_init(void)
|
|||||||
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
die(_("cannot create PF_ROUTE socket: %s"), NULL, EC_BADNET);
|
||||||
}
|
}
|
||||||
|
|
||||||
void route_sock(time_t now)
|
void route_sock(void)
|
||||||
{
|
{
|
||||||
struct if_msghdr *msg;
|
struct if_msghdr *msg;
|
||||||
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
int rc = recv(daemon->routefd, daemon->packet, daemon->packet_buff_sz, 0);
|
||||||
@@ -401,7 +401,7 @@ void route_sock(time_t now)
|
|||||||
else if (msg->ifm_type == RTM_NEWADDR)
|
else if (msg->ifm_type == RTM_NEWADDR)
|
||||||
{
|
{
|
||||||
del_family = 0;
|
del_family = 0;
|
||||||
newaddress(now);
|
queue_event(EVENT_NEWADDR);
|
||||||
}
|
}
|
||||||
else if (msg->ifm_type == RTM_DELADDR)
|
else if (msg->ifm_type == RTM_DELADDR)
|
||||||
{
|
{
|
||||||
@@ -439,7 +439,7 @@ void route_sock(time_t now)
|
|||||||
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
of += sizeof(long) - (diff & (sizeof(long) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
newaddress(now);
|
queue_event(EVENT_NEWADDR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+327
-105
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,7 +24,6 @@ static struct crec *new_chain = NULL;
|
|||||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||||
static union bigname *big_free = NULL;
|
static union bigname *big_free = NULL;
|
||||||
static int bignames_left, hash_size;
|
static int bignames_left, hash_size;
|
||||||
static int uid = 1;
|
|
||||||
|
|
||||||
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -55,7 +54,9 @@ static const struct {
|
|||||||
{ 41, "OPT" },
|
{ 41, "OPT" },
|
||||||
{ 43, "DS" },
|
{ 43, "DS" },
|
||||||
{ 46, "RRSIG" },
|
{ 46, "RRSIG" },
|
||||||
|
{ 47, "NSEC" },
|
||||||
{ 48, "DNSKEY" },
|
{ 48, "DNSKEY" },
|
||||||
|
{ 50, "NSEC3" },
|
||||||
{ 249, "TKEY" },
|
{ 249, "TKEY" },
|
||||||
{ 250, "TSIG" },
|
{ 250, "TSIG" },
|
||||||
{ 251, "IXFR" },
|
{ 251, "IXFR" },
|
||||||
@@ -71,6 +72,19 @@ static void cache_link(struct crec *crecp);
|
|||||||
static void rehash(int size);
|
static void rehash(int size);
|
||||||
static void cache_hash(struct crec *crecp);
|
static void cache_hash(struct crec *crecp);
|
||||||
|
|
||||||
|
static unsigned int next_uid(void)
|
||||||
|
{
|
||||||
|
static unsigned int uid = 0;
|
||||||
|
|
||||||
|
uid++;
|
||||||
|
|
||||||
|
/* uid == 0 used to indicate CNAME to interface name. */
|
||||||
|
if (uid == SRC_INTERFACE)
|
||||||
|
uid++;
|
||||||
|
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
void cache_init(void)
|
void cache_init(void)
|
||||||
{
|
{
|
||||||
struct crec *crecp;
|
struct crec *crecp;
|
||||||
@@ -86,7 +100,7 @@ void cache_init(void)
|
|||||||
{
|
{
|
||||||
cache_link(crecp);
|
cache_link(crecp);
|
||||||
crecp->flags = 0;
|
crecp->flags = 0;
|
||||||
crecp->uid = uid++;
|
crecp->uid = next_uid();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +195,7 @@ static void cache_blockdata_free(struct crec *crecp)
|
|||||||
else
|
else
|
||||||
blockdata_free(crecp->addr.key.keydata);
|
blockdata_free(crecp->addr.key.keydata);
|
||||||
}
|
}
|
||||||
else if (crecp->flags & F_DS)
|
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
|
||||||
blockdata_free(crecp->addr.ds.keydata);
|
blockdata_free(crecp->addr.ds.keydata);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -190,10 +204,7 @@ static void cache_free(struct crec *crecp)
|
|||||||
{
|
{
|
||||||
crecp->flags &= ~F_FORWARD;
|
crecp->flags &= ~F_FORWARD;
|
||||||
crecp->flags &= ~F_REVERSE;
|
crecp->flags &= ~F_REVERSE;
|
||||||
crecp->uid = uid++; /* invalidate CNAMES pointing to this. */
|
crecp->uid = next_uid(); /* invalidate CNAMES pointing to this. */
|
||||||
|
|
||||||
if (uid == -1)
|
|
||||||
uid++;
|
|
||||||
|
|
||||||
if (cache_tail)
|
if (cache_tail)
|
||||||
cache_tail->next = crecp;
|
cache_tail->next = crecp;
|
||||||
@@ -254,7 +265,7 @@ char *cache_get_name(struct crec *crecp)
|
|||||||
|
|
||||||
char *cache_get_cname_target(struct crec *crecp)
|
char *cache_get_cname_target(struct crec *crecp)
|
||||||
{
|
{
|
||||||
if (crecp->addr.cname.uid != -1)
|
if (crecp->addr.cname.uid != SRC_INTERFACE)
|
||||||
return cache_get_name(crecp->addr.cname.target.cache);
|
return cache_get_name(crecp->addr.cname.target.cache);
|
||||||
|
|
||||||
return crecp->addr.cname.target.int_name->name;
|
return crecp->addr.cname.target.int_name->name;
|
||||||
@@ -287,7 +298,7 @@ struct crec *cache_enumerate(int init)
|
|||||||
|
|
||||||
static int is_outdated_cname_pointer(struct crec *crecp)
|
static int is_outdated_cname_pointer(struct crec *crecp)
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == -1)
|
if (!(crecp->flags & F_CNAME) || crecp->addr.cname.uid == SRC_INTERFACE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* NB. record may be reused as DS or DNSKEY, where uid is
|
/* NB. record may be reused as DS or DNSKEY, where uid is
|
||||||
@@ -311,7 +322,7 @@ static int is_expired(time_t now, struct crec *crecp)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
|
static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags)
|
||||||
{
|
{
|
||||||
/* Scan and remove old entries.
|
/* Scan and remove old entries.
|
||||||
If (flags & F_FORWARD) then remove any forward entries for name and any expired
|
If (flags & F_FORWARD) then remove any forward entries for name and any expired
|
||||||
@@ -320,8 +331,8 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
|||||||
entries in the whole cache.
|
entries in the whole cache.
|
||||||
If (flags == 0) remove any expired entries in the whole cache.
|
If (flags == 0) remove any expired entries in the whole cache.
|
||||||
|
|
||||||
In the flags & F_FORWARD case, the return code is valid, and returns zero if the
|
In the flags & F_FORWARD case, the return code is valid, and returns a non-NULL pointer
|
||||||
name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
|
to a cache entry if the name exists in the cache as a HOSTS or DHCP entry (these are never deleted)
|
||||||
|
|
||||||
We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
|
We take advantage of the fact that hash chains have stuff in the order <reverse>,<other>,<immortal>
|
||||||
so that when we hit an entry which isn't reverse and is immortal, we're done. */
|
so that when we hit an entry which isn't reverse and is immortal, we're done. */
|
||||||
@@ -350,7 +361,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
|||||||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
||||||
{
|
{
|
||||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||||
return 0;
|
return crecp;
|
||||||
*up = crecp->hash_next;
|
*up = crecp->hash_next;
|
||||||
cache_unlink(crecp);
|
cache_unlink(crecp);
|
||||||
cache_free(crecp);
|
cache_free(crecp);
|
||||||
@@ -367,7 +378,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
|||||||
crecp->addr.sig.type_covered == addr->addr.dnssec.type))
|
crecp->addr.sig.type_covered == addr->addr.dnssec.type))
|
||||||
{
|
{
|
||||||
if (crecp->flags & F_CONFIG)
|
if (crecp->flags & F_CONFIG)
|
||||||
return 0;
|
return crecp;
|
||||||
*up = crecp->hash_next;
|
*up = crecp->hash_next;
|
||||||
cache_unlink(crecp);
|
cache_unlink(crecp);
|
||||||
cache_free(crecp);
|
cache_free(crecp);
|
||||||
@@ -412,7 +423,7 @@ static int cache_scan_free(char *name, struct all_addr *addr, time_t now, unsign
|
|||||||
up = &crecp->hash_next;
|
up = &crecp->hash_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note: The normal calling sequence is
|
/* Note: The normal calling sequence is
|
||||||
@@ -446,22 +457,42 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
|||||||
int freed_all = flags & F_REVERSE;
|
int freed_all = flags & F_REVERSE;
|
||||||
int free_avail = 0;
|
int free_avail = 0;
|
||||||
|
|
||||||
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
/* Don't log DNSSEC records here, done elsewhere */
|
||||||
ttl = daemon->max_cache_ttl;
|
|
||||||
|
|
||||||
/* Don't log keys here, done elsewhere */
|
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
|
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
|
||||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
{
|
||||||
|
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
||||||
|
/* Don't mess with TTL for DNSSEC records. */
|
||||||
|
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
|
||||||
|
ttl = daemon->max_cache_ttl;
|
||||||
|
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
|
||||||
|
ttl = daemon->min_cache_ttl;
|
||||||
|
}
|
||||||
|
|
||||||
/* if previous insertion failed give up now. */
|
/* if previous insertion failed give up now. */
|
||||||
if (insert_error)
|
if (insert_error)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* First remove any expired entries and entries for the name/address we
|
/* First remove any expired entries and entries for the name/address we
|
||||||
are currently inserting. Fail is we attempt to delete a name from
|
are currently inserting. */
|
||||||
/etc/hosts or DHCP. */
|
if ((new = cache_scan_free(name, addr, now, flags)))
|
||||||
if (!cache_scan_free(name, addr, now, flags))
|
|
||||||
{
|
{
|
||||||
|
/* We're trying to insert a record over one from
|
||||||
|
/etc/hosts or DHCP, or other config. If the
|
||||||
|
existing record is for an A or AAAA and
|
||||||
|
the record we're trying to insert is the same,
|
||||||
|
just drop the insert, but don't error the whole process. */
|
||||||
|
if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD))
|
||||||
|
{
|
||||||
|
if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
|
||||||
|
new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
|
||||||
|
return new;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else if ((flags & F_IPV6) && (new->flags & F_IPV6) &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&new->addr.addr.addr.addr6, &addr->addr.addr6))
|
||||||
|
return new;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
insert_error = 1;
|
insert_error = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -560,7 +591,14 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
|||||||
*cache_get_name(new) = 0;
|
*cache_get_name(new) = 0;
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
new->addr.addr = *addr;
|
{
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (flags & (F_DS | F_DNSKEY))
|
||||||
|
new->uid = addr->addr.dnssec.class;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
new->addr.addr = *addr;
|
||||||
|
}
|
||||||
|
|
||||||
new->ttd = now + (time_t)ttl;
|
new->ttd = now + (time_t)ttl;
|
||||||
new->next = new_chain;
|
new->next = new_chain;
|
||||||
@@ -592,10 +630,13 @@ void cache_end_insert(void)
|
|||||||
new_chain = NULL;
|
new_chain = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned short prot)
|
struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
|
||||||
{
|
{
|
||||||
struct crec *ans;
|
struct crec *ans;
|
||||||
|
int no_rr = prot & F_NO_RR;
|
||||||
|
|
||||||
|
prot &= ~F_NO_RR;
|
||||||
|
|
||||||
if (crecp) /* iterating */
|
if (crecp) /* iterating */
|
||||||
ans = crecp->next;
|
ans = crecp->next;
|
||||||
else
|
else
|
||||||
@@ -613,7 +654,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
|||||||
{
|
{
|
||||||
if ((crecp->flags & F_FORWARD) &&
|
if ((crecp->flags & F_FORWARD) &&
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) &&
|
(((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
|
||||||
#endif
|
#endif
|
||||||
(crecp->flags & prot) &&
|
(crecp->flags & prot) &&
|
||||||
hostname_isequal(cache_get_name(crecp), name))
|
hostname_isequal(cache_get_name(crecp), name))
|
||||||
@@ -643,7 +684,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!insert)
|
if (!insert && !no_rr)
|
||||||
{
|
{
|
||||||
insert = up;
|
insert = up;
|
||||||
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
ins_flags = crecp->flags & (F_REVERSE | F_IMMORTAL);
|
||||||
@@ -673,7 +714,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
|||||||
if (ans &&
|
if (ans &&
|
||||||
(ans->flags & F_FORWARD) &&
|
(ans->flags & F_FORWARD) &&
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) &&
|
(((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
|
||||||
#endif
|
#endif
|
||||||
(ans->flags & prot) &&
|
(ans->flags & prot) &&
|
||||||
hostname_isequal(cache_get_name(ans), name))
|
hostname_isequal(cache_get_name(ans), name))
|
||||||
@@ -683,7 +724,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
struct crec *cache_find_by_addr(struct crec *crecp, struct all_addr *addr,
|
||||||
time_t now, unsigned short prot)
|
time_t now, unsigned int prot)
|
||||||
{
|
{
|
||||||
struct crec *ans;
|
struct crec *ans;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
@@ -760,13 +801,14 @@ static void add_hosts_cname(struct crec *target)
|
|||||||
crec->name.namep = a->alias;
|
crec->name.namep = a->alias;
|
||||||
crec->addr.cname.target.cache = target;
|
crec->addr.cname.target.cache = target;
|
||||||
crec->addr.cname.uid = target->uid;
|
crec->addr.cname.uid = target->uid;
|
||||||
|
crec->uid = next_uid();
|
||||||
cache_hash(crec);
|
cache_hash(crec);
|
||||||
add_hosts_cname(crec); /* handle chains */
|
add_hosts_cname(crec); /* handle chains */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrlen,
|
||||||
int index, struct crec **rhash, int hashsz)
|
unsigned int index, struct crec **rhash, int hashsz)
|
||||||
{
|
{
|
||||||
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
struct crec *lookup = cache_find_by_name(NULL, cache_get_name(cache), 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||||
int i, nameexists = 0;
|
int i, nameexists = 0;
|
||||||
@@ -793,27 +835,42 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
|||||||
Only insert each unique address once into this hashing structure.
|
Only insert each unique address once into this hashing structure.
|
||||||
|
|
||||||
This complexity avoids O(n^2) divergent CPU use whilst reading
|
This complexity avoids O(n^2) divergent CPU use whilst reading
|
||||||
large (10000 entry) hosts files. */
|
large (10000 entry) hosts files.
|
||||||
|
|
||||||
|
Note that we only do this process when bulk-reading hosts files,
|
||||||
|
for incremental reads, rhash is NULL, and we use cache lookups
|
||||||
|
instead.
|
||||||
|
*/
|
||||||
|
|
||||||
/* hash address */
|
if (rhash)
|
||||||
for (j = 0, i = 0; i < addrlen; i++)
|
|
||||||
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
|
|
||||||
|
|
||||||
for (lookup = rhash[j]; lookup; lookup = lookup->next)
|
|
||||||
if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
|
|
||||||
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
|
||||||
{
|
|
||||||
cache->flags &= ~F_REVERSE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* maintain address hash chain, insert new unique address */
|
|
||||||
if (!lookup)
|
|
||||||
{
|
{
|
||||||
cache->next = rhash[j];
|
/* hash address */
|
||||||
rhash[j] = cache;
|
for (j = 0, i = 0; i < addrlen; i++)
|
||||||
|
j = (j*2 +((unsigned char *)addr)[i]) % hashsz;
|
||||||
|
|
||||||
|
for (lookup = rhash[j]; lookup; lookup = lookup->next)
|
||||||
|
if ((lookup->flags & cache->flags & (F_IPV4 | F_IPV6)) &&
|
||||||
|
memcmp(&lookup->addr.addr, addr, addrlen) == 0)
|
||||||
|
{
|
||||||
|
cache->flags &= ~F_REVERSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* maintain address hash chain, insert new unique address */
|
||||||
|
if (!lookup)
|
||||||
|
{
|
||||||
|
cache->next = rhash[j];
|
||||||
|
rhash[j] = cache;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* incremental read, lookup in cache */
|
||||||
|
lookup = cache_find_by_addr(NULL, addr, 0, cache->flags & (F_IPV4 | F_IPV6));
|
||||||
|
if (lookup && lookup->flags & F_HOSTS)
|
||||||
|
cache->flags &= ~F_REVERSE;
|
||||||
|
}
|
||||||
|
|
||||||
cache->uid = index;
|
cache->uid = index;
|
||||||
memcpy(&cache->addr.addr, addr, addrlen);
|
memcpy(&cache->addr.addr, addr, addrlen);
|
||||||
cache_hash(cache);
|
cache_hash(cache);
|
||||||
@@ -870,7 +927,7 @@ static int gettok(FILE *f, char *token)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int read_hostsfile(char *filename, int index, int cache_size, struct crec **rhash, int hashsz)
|
int read_hostsfile(char *filename, unsigned int index, int cache_size, struct crec **rhash, int hashsz)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
char *token = daemon->namebuff, *domain_suffix = NULL;
|
char *token = daemon->namebuff, *domain_suffix = NULL;
|
||||||
@@ -916,7 +973,7 @@ static int read_hostsfile(char *filename, int index, int cache_size, struct crec
|
|||||||
addr_count++;
|
addr_count++;
|
||||||
|
|
||||||
/* rehash every 1000 names. */
|
/* rehash every 1000 names. */
|
||||||
if ((name_count - cache_size) > 1000)
|
if (rhash && ((name_count - cache_size) > 1000))
|
||||||
{
|
{
|
||||||
rehash(name_count);
|
rehash(name_count);
|
||||||
cache_size = name_count;
|
cache_size = name_count;
|
||||||
@@ -963,7 +1020,9 @@ static int read_hostsfile(char *filename, int index, int cache_size, struct crec
|
|||||||
}
|
}
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
rehash(name_count);
|
|
||||||
|
if (rhash)
|
||||||
|
rehash(name_count);
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
|
my_syslog(LOG_INFO, _("read %s - %d addresses"), filename, addr_count);
|
||||||
|
|
||||||
@@ -980,7 +1039,7 @@ void cache_reload(void)
|
|||||||
struct cname *a;
|
struct cname *a;
|
||||||
struct interface_name *intr;
|
struct interface_name *intr;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
struct dnskey *key;
|
struct ds_config *ds;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
cache_inserted = cache_live_freed = 0;
|
cache_inserted = cache_live_freed = 0;
|
||||||
@@ -1020,23 +1079,24 @@ void cache_reload(void)
|
|||||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||||
cache->name.namep = a->alias;
|
cache->name.namep = a->alias;
|
||||||
cache->addr.cname.target.int_name = intr;
|
cache->addr.cname.target.int_name = intr;
|
||||||
cache->addr.cname.uid = -1;
|
cache->addr.cname.uid = SRC_INTERFACE;
|
||||||
|
cache->uid = next_uid();
|
||||||
cache_hash(cache);
|
cache_hash(cache);
|
||||||
add_hosts_cname(cache); /* handle chains */
|
add_hosts_cname(cache); /* handle chains */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
for (key = daemon->dnskeys; key; key = key->next)
|
for (ds = daemon->ds; ds; ds = ds->next)
|
||||||
if ((cache = whine_malloc(sizeof(struct crec))) &&
|
if ((cache = whine_malloc(sizeof(struct crec))) &&
|
||||||
(cache->addr.key.keydata = blockdata_alloc(key->key, key->keylen)))
|
(cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
|
||||||
{
|
{
|
||||||
cache->flags = F_FORWARD | F_IMMORTAL | F_DNSKEY | F_CONFIG | F_NAMEP;
|
cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
|
||||||
cache->name.namep = key->name;
|
cache->name.namep = ds->name;
|
||||||
cache->addr.key.keylen = key->keylen;
|
cache->addr.ds.keylen = ds->digestlen;
|
||||||
cache->addr.key.algo = key->algo;
|
cache->addr.ds.algo = ds->algo;
|
||||||
cache->addr.key.flags = key->flags;
|
cache->addr.ds.keytag = ds->keytag;
|
||||||
cache->addr.key.keytag = dnskey_keytag(key->algo, key->flags, (unsigned char *)key->key, key->keylen);
|
cache->addr.ds.digest = ds->digest_type;
|
||||||
cache->uid = key->class;
|
cache->uid = ds->class;
|
||||||
cache_hash(cache);
|
cache_hash(cache);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1056,7 +1116,7 @@ void cache_reload(void)
|
|||||||
{
|
{
|
||||||
cache->name.namep = nl->name;
|
cache->name.namep = nl->name;
|
||||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
|
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
|
||||||
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
|
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
||||||
@@ -1064,7 +1124,7 @@ void cache_reload(void)
|
|||||||
{
|
{
|
||||||
cache->name.namep = nl->name;
|
cache->name.namep = nl->name;
|
||||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
|
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
|
||||||
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, 0, (struct crec **)daemon->packet, revhashsz);
|
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1073,16 +1133,22 @@ void cache_reload(void)
|
|||||||
{
|
{
|
||||||
if (daemon->cachesize > 0)
|
if (daemon->cachesize > 0)
|
||||||
my_syslog(LOG_INFO, _("cleared cache"));
|
my_syslog(LOG_INFO, _("cleared cache"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!option_bool(OPT_NO_HOSTS))
|
{
|
||||||
total_size = read_hostsfile(HOSTSFILE, 0, total_size, (struct crec **)daemon->packet, revhashsz);
|
if (!option_bool(OPT_NO_HOSTS))
|
||||||
|
total_size = read_hostsfile(HOSTSFILE, SRC_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
|
||||||
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
|
|
||||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
daemon->addn_hosts = expand_filelist(daemon->addn_hosts);
|
||||||
if (!(ah->flags & AH_INACTIVE))
|
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||||
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
|
if (!(ah->flags & AH_INACTIVE))
|
||||||
|
total_size = read_hostsfile(ah->fname, ah->index, total_size, (struct crec **)daemon->packet, revhashsz);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
set_dynamic_inotify(AH_HOSTS, total_size, (struct crec **)daemon->packet, revhashsz);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
@@ -1141,6 +1207,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
|||||||
aliasc->name.namep = a->alias;
|
aliasc->name.namep = a->alias;
|
||||||
aliasc->addr.cname.target.cache = target;
|
aliasc->addr.cname.target.cache = target;
|
||||||
aliasc->addr.cname.uid = target->uid;
|
aliasc->addr.cname.uid = target->uid;
|
||||||
|
aliasc->uid = next_uid();
|
||||||
cache_hash(aliasc);
|
cache_hash(aliasc);
|
||||||
add_dhcp_cname(aliasc, ttd);
|
add_dhcp_cname(aliasc, ttd);
|
||||||
}
|
}
|
||||||
@@ -1228,7 +1295,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
crec->ttd = ttd;
|
crec->ttd = ttd;
|
||||||
crec->addr.addr = *host_address;
|
crec->addr.addr = *host_address;
|
||||||
crec->name.namep = host_name;
|
crec->name.namep = host_name;
|
||||||
crec->uid = uid++;
|
crec->uid = next_uid();
|
||||||
cache_hash(crec);
|
cache_hash(crec);
|
||||||
|
|
||||||
add_dhcp_cname(crec, ttd);
|
add_dhcp_cname(crec, ttd);
|
||||||
@@ -1236,6 +1303,115 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
int cache_make_stat(struct txt_record *t)
|
||||||
|
{
|
||||||
|
static char *buff = NULL;
|
||||||
|
static int bufflen = 60;
|
||||||
|
int len;
|
||||||
|
struct server *serv, *serv1;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
if (!buff && !(buff = whine_malloc(60)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
p = buff;
|
||||||
|
|
||||||
|
switch (t->stat)
|
||||||
|
{
|
||||||
|
case TXT_STAT_CACHESIZE:
|
||||||
|
sprintf(buff+1, "%d", daemon->cachesize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_INSERTS:
|
||||||
|
sprintf(buff+1, "%d", cache_inserted);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_EVICTIONS:
|
||||||
|
sprintf(buff+1, "%d", cache_live_freed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_MISSES:
|
||||||
|
sprintf(buff+1, "%u", daemon->queries_forwarded);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TXT_STAT_HITS:
|
||||||
|
sprintf(buff+1, "%u", daemon->local_answer);
|
||||||
|
break;
|
||||||
|
|
||||||
|
#ifdef HAVE_AUTH
|
||||||
|
case TXT_STAT_AUTH:
|
||||||
|
sprintf(buff+1, "%u", daemon->auth_answer);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case TXT_STAT_SERVERS:
|
||||||
|
/* sum counts from different records for same server */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
serv->flags &= ~SERV_COUNTED;
|
||||||
|
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (!(serv->flags &
|
||||||
|
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||||
|
{
|
||||||
|
char *new, *lenp;
|
||||||
|
int port, newlen, bytes_avail, bytes_needed;
|
||||||
|
unsigned int queries = 0, failed_queries = 0;
|
||||||
|
for (serv1 = serv; serv1; serv1 = serv1->next)
|
||||||
|
if (!(serv1->flags &
|
||||||
|
(SERV_NO_ADDR | SERV_LITERAL_ADDRESS | SERV_COUNTED | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
|
||||||
|
sockaddr_isequal(&serv->addr, &serv1->addr))
|
||||||
|
{
|
||||||
|
serv1->flags |= SERV_COUNTED;
|
||||||
|
queries += serv1->queries;
|
||||||
|
failed_queries += serv1->failed_queries;
|
||||||
|
}
|
||||||
|
port = prettyprint_addr(&serv->addr, daemon->addrbuff);
|
||||||
|
lenp = p++; /* length */
|
||||||
|
bytes_avail = bufflen - (p - buff );
|
||||||
|
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
|
||||||
|
if (bytes_needed >= bytes_avail)
|
||||||
|
{
|
||||||
|
/* expand buffer if necessary */
|
||||||
|
newlen = bytes_needed + 1 + bufflen - bytes_avail;
|
||||||
|
if (!(new = whine_malloc(newlen)))
|
||||||
|
return 0;
|
||||||
|
memcpy(new, buff, bufflen);
|
||||||
|
free(buff);
|
||||||
|
p = new + (p - buff);
|
||||||
|
lenp = p - 1;
|
||||||
|
buff = new;
|
||||||
|
bufflen = newlen;
|
||||||
|
bytes_avail = bufflen - (p - buff );
|
||||||
|
bytes_needed = snprintf(p, bytes_avail, "%s#%d %u %u", daemon->addrbuff, port, queries, failed_queries);
|
||||||
|
}
|
||||||
|
*lenp = bytes_needed;
|
||||||
|
p += bytes_needed;
|
||||||
|
}
|
||||||
|
t->txt = (unsigned char *)buff;
|
||||||
|
t->len = p - buff;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = strlen(buff+1);
|
||||||
|
t->txt = (unsigned char *)buff;
|
||||||
|
t->len = len + 1;
|
||||||
|
*buff = len;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* There can be names in the cache containing control chars, don't
|
||||||
|
mess up logging or open security holes. */
|
||||||
|
static char *sanitise(char *name)
|
||||||
|
{
|
||||||
|
unsigned char *r;
|
||||||
|
if (name)
|
||||||
|
for (r = (unsigned char *)name; *r; r++)
|
||||||
|
if (!isprint((int)*r))
|
||||||
|
return "<name unprintable>";
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dump_cache(time_t now)
|
void dump_cache(time_t now)
|
||||||
{
|
{
|
||||||
@@ -1290,34 +1466,23 @@ void dump_cache(time_t now)
|
|||||||
*a = 0;
|
*a = 0;
|
||||||
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
|
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
|
||||||
n = "<Root>";
|
n = "<Root>";
|
||||||
p += sprintf(p, "%-40.40s ", n);
|
p += sprintf(p, "%-30.30s ", sanitise(n));
|
||||||
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
||||||
a = cache_get_cname_target(cache);
|
a = sanitise(cache_get_cname_target(cache));
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else if (cache->flags & F_DS)
|
else if (cache->flags & F_DS)
|
||||||
{
|
{
|
||||||
if (cache->flags & F_DNSKEY)
|
if (cache->flags & F_DNSKEY)
|
||||||
{
|
/* RRSIG */
|
||||||
char tp[20];
|
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
|
||||||
/* RRSIG */
|
cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
|
||||||
querystr("", tp, cache->addr.sig.type_covered);
|
else if (!(cache->flags & F_NEG))
|
||||||
a = daemon->addrbuff;
|
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
|
||||||
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
|
cache->addr.ds.algo, cache->addr.ds.digest);
|
||||||
cache->addr.sig.algo, tp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
a = daemon->addrbuff;
|
|
||||||
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
|
|
||||||
cache->addr.ds.algo, cache->addr.ds.digest);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (cache->flags & F_DNSKEY)
|
else if (cache->flags & F_DNSKEY)
|
||||||
{
|
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
|
||||||
a = daemon->addrbuff;
|
cache->addr.key.algo, cache->addr.key.flags);
|
||||||
sprintf(a, "%5u %3u %3u", cache->addr.key.keytag,
|
|
||||||
cache->addr.key.algo, cache->addr.key.flags);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
|
else if (!(cache->flags & F_NEG) || !(cache->flags & F_FORWARD))
|
||||||
{
|
{
|
||||||
@@ -1344,7 +1509,7 @@ void dump_cache(time_t now)
|
|||||||
else if (cache->flags & F_DNSKEY)
|
else if (cache->flags & F_DNSKEY)
|
||||||
t = "K";
|
t = "K";
|
||||||
#endif
|
#endif
|
||||||
p += sprintf(p, "%-30.30s %s%s%s%s%s%s%s%s%s ", a, t,
|
p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
|
||||||
cache->flags & F_FORWARD ? "F" : " ",
|
cache->flags & F_FORWARD ? "F" : " ",
|
||||||
cache->flags & F_REVERSE ? "R" : " ",
|
cache->flags & F_REVERSE ? "R" : " ",
|
||||||
cache->flags & F_IMMORTAL ? "I" : " ",
|
cache->flags & F_IMMORTAL ? "I" : " ",
|
||||||
@@ -1365,28 +1530,67 @@ void dump_cache(time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *record_source(int index)
|
char *record_source(unsigned int index)
|
||||||
{
|
{
|
||||||
struct hostsfile *ah;
|
struct hostsfile *ah;
|
||||||
|
|
||||||
if (index == 0)
|
if (index == SRC_CONFIG)
|
||||||
|
return "config";
|
||||||
|
else if (index == SRC_HOSTS)
|
||||||
return HOSTSFILE;
|
return HOSTSFILE;
|
||||||
|
|
||||||
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
for (ah = daemon->addn_hosts; ah; ah = ah->next)
|
||||||
if (ah->index == index)
|
if (ah->index == index)
|
||||||
return ah->fname;
|
return ah->fname;
|
||||||
|
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||||
|
if (ah->index == index)
|
||||||
|
return ah->fname;
|
||||||
|
#endif
|
||||||
|
|
||||||
return "<unknown>";
|
return "<unknown>";
|
||||||
}
|
}
|
||||||
|
|
||||||
void querystr(char *desc, char *str, unsigned short type)
|
char *querystr(char *desc, unsigned short type)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int len = 10; /* strlen("type=xxxxx") */
|
||||||
sprintf(str, "%s[type=%d]", desc, type);
|
const char *types = NULL;
|
||||||
|
static char *buff = NULL;
|
||||||
|
static int bufflen = 0;
|
||||||
|
|
||||||
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
for (i = 0; i < (sizeof(typestr)/sizeof(typestr[0])); i++)
|
||||||
if (typestr[i].type == type)
|
if (typestr[i].type == type)
|
||||||
sprintf(str,"%s[%s]", desc, typestr[i].name);
|
{
|
||||||
|
types = typestr[i].name;
|
||||||
|
len = strlen(types);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += 3; /* braces, terminator */
|
||||||
|
len += strlen(desc);
|
||||||
|
|
||||||
|
if (!buff || bufflen < len)
|
||||||
|
{
|
||||||
|
if (buff)
|
||||||
|
free(buff);
|
||||||
|
else if (len < 20)
|
||||||
|
len = 20;
|
||||||
|
|
||||||
|
buff = whine_malloc(len);
|
||||||
|
bufflen = len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buff)
|
||||||
|
{
|
||||||
|
if (types)
|
||||||
|
sprintf(buff, "%s[%s]", desc, types);
|
||||||
|
else
|
||||||
|
sprintf(buff, "%s[type=%d]", desc, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return buff ? buff : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
||||||
@@ -1397,6 +1601,8 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
|||||||
if (!option_bool(OPT_LOG))
|
if (!option_bool(OPT_LOG))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
name = sanitise(name);
|
||||||
|
|
||||||
if (addr)
|
if (addr)
|
||||||
{
|
{
|
||||||
if (flags & F_KEYTAG)
|
if (flags & F_KEYTAG)
|
||||||
@@ -1466,13 +1672,29 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
|||||||
source = arg;
|
source = arg;
|
||||||
verb = "to";
|
verb = "to";
|
||||||
}
|
}
|
||||||
|
else if (flags & F_IPSET)
|
||||||
|
{
|
||||||
|
source = "ipset add";
|
||||||
|
dest = name;
|
||||||
|
name = arg;
|
||||||
|
verb = daemon->addrbuff;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
source = "cached";
|
source = "cached";
|
||||||
|
|
||||||
if (strlen(name) == 0)
|
if (strlen(name) == 0)
|
||||||
name = ".";
|
name = ".";
|
||||||
|
|
||||||
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
|
if (option_bool(OPT_EXTRALOG))
|
||||||
|
{
|
||||||
|
int port = prettyprint_addr(daemon->log_source_addr, daemon->addrbuff2);
|
||||||
|
if (flags & F_NOEXTRA)
|
||||||
|
my_syslog(LOG_INFO, "* %s/%u %s %s %s %s", daemon->addrbuff2, port, source, name, verb, dest);
|
||||||
|
else
|
||||||
|
my_syslog(LOG_INFO, "%u %s/%u %s %s %s %s", daemon->log_display_id, daemon->addrbuff2, port, source, name, verb, dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
my_syslog(LOG_INFO, "%s %s %s %s", source, name, verb, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
+44
-5
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -17,20 +17,25 @@
|
|||||||
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
#define FTABSIZ 150 /* max number of outstanding requests (default) */
|
||||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||||
|
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||||
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||||
#define KEYBLOCK_LEN 35 /* choose to mininise fragmentation when storing DNSSEC keys */
|
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||||
|
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
|
||||||
|
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||||
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
||||||
#define CACHESIZ 150 /* default cache size */
|
#define CACHESIZ 150 /* default cache size */
|
||||||
|
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
|
||||||
#define MAXLEASES 1000 /* maximum number of DHCP leases */
|
#define MAXLEASES 1000 /* maximum number of DHCP leases */
|
||||||
#define PING_WAIT 3 /* wait for ping address-in-use test */
|
#define PING_WAIT 3 /* wait for ping address-in-use test */
|
||||||
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
|
#define PING_CACHE_TIME 30 /* Ping test assumed to be valid this long. */
|
||||||
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
|
#define DECLINE_BACKOFF 600 /* disable DECLINEd static addresses for this long */
|
||||||
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
||||||
#define SMALLDNAME 40 /* most domain names are smaller than this */
|
#define SMALLDNAME 50 /* most domain names are smaller than this */
|
||||||
|
#define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
|
||||||
#define HOSTSFILE "/etc/hosts"
|
#define HOSTSFILE "/etc/hosts"
|
||||||
#define ETHERSFILE "/etc/ethers"
|
#define ETHERSFILE "/etc/ethers"
|
||||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||||
@@ -45,6 +50,8 @@
|
|||||||
#define SOA_REFRESH 1200 /* SOA refresh default */
|
#define SOA_REFRESH 1200 /* SOA refresh default */
|
||||||
#define SOA_RETRY 180 /* SOA retry default */
|
#define SOA_RETRY 180 /* SOA retry default */
|
||||||
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
#define SOA_EXPIRY 1209600 /* SOA expiry default */
|
||||||
|
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
|
||||||
|
#define LOOP_TEST_TYPE T_TXT
|
||||||
|
|
||||||
/* compile-time options: uncomment below to enable or do eg.
|
/* compile-time options: uncomment below to enable or do eg.
|
||||||
make COPTS=-DHAVE_BROKEN_RTC
|
make COPTS=-DHAVE_BROKEN_RTC
|
||||||
@@ -103,6 +110,14 @@ HAVE_AUTH
|
|||||||
define this to include the facility to act as an authoritative DNS
|
define this to include the facility to act as an authoritative DNS
|
||||||
server for one or more zones.
|
server for one or more zones.
|
||||||
|
|
||||||
|
HAVE_DNSSEC
|
||||||
|
include DNSSEC validator.
|
||||||
|
|
||||||
|
HAVE_LOOP
|
||||||
|
include functionality to probe for and remove DNS forwarding loops.
|
||||||
|
|
||||||
|
HAVE_INOTIFY
|
||||||
|
use the Linux inotify facility to efficiently re-read configuration files.
|
||||||
|
|
||||||
NO_IPV6
|
NO_IPV6
|
||||||
NO_TFTP
|
NO_TFTP
|
||||||
@@ -111,11 +126,17 @@ NO_DHCP6
|
|||||||
NO_SCRIPT
|
NO_SCRIPT
|
||||||
NO_LARGEFILE
|
NO_LARGEFILE
|
||||||
NO_AUTH
|
NO_AUTH
|
||||||
|
NO_INOTIFY
|
||||||
these are avilable to explictly disable compile time options which would
|
these are avilable to explictly disable compile time options which would
|
||||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
||||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||||
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
|
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
|
||||||
|
|
||||||
|
NO_NETTLE_ECC
|
||||||
|
Don't include the ECDSA cypher in DNSSEC validation. Needed for older Nettle versions.
|
||||||
|
NO_GMP
|
||||||
|
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
||||||
|
|
||||||
LEASEFILE
|
LEASEFILE
|
||||||
CONFFILE
|
CONFFILE
|
||||||
RESOLVFILE
|
RESOLVFILE
|
||||||
@@ -139,6 +160,7 @@ RESOLVFILE
|
|||||||
#define HAVE_SCRIPT
|
#define HAVE_SCRIPT
|
||||||
#define HAVE_AUTH
|
#define HAVE_AUTH
|
||||||
#define HAVE_IPSET
|
#define HAVE_IPSET
|
||||||
|
#define HAVE_LOOP
|
||||||
|
|
||||||
/* Build options which require external libraries.
|
/* Build options which require external libraries.
|
||||||
|
|
||||||
@@ -259,6 +281,7 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
/* Select the RFC_3542 version of the IPv6 socket API.
|
/* Select the RFC_3542 version of the IPv6 socket API.
|
||||||
Define before netinet6/in6.h is included. */
|
Define before netinet6/in6.h is included. */
|
||||||
#define __APPLE_USE_RFC_3542
|
#define __APPLE_USE_RFC_3542
|
||||||
|
#define NO_IPSET
|
||||||
|
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
#define HAVE_BSD_NETWORK
|
#define HAVE_BSD_NETWORK
|
||||||
@@ -328,10 +351,18 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#undef HAVE_AUTH
|
#undef HAVE_AUTH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NO_IPSET) || !defined(HAVE_LINUX_NETWORK)
|
#if defined(NO_IPSET)
|
||||||
#undef HAVE_IPSET
|
#undef HAVE_IPSET
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_LOOP
|
||||||
|
#undef HAVE_LOOP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
|
||||||
|
#define HAVE_INOTIFY
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Define a string indicating which options are in use.
|
/* Define a string indicating which options are in use.
|
||||||
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||||
|
|
||||||
@@ -401,7 +432,15 @@ static char *compile_opts =
|
|||||||
#ifndef HAVE_DNSSEC
|
#ifndef HAVE_DNSSEC
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"DNSSEC";
|
"DNSSEC "
|
||||||
|
#ifndef HAVE_LOOP
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"loop-detect "
|
||||||
|
#ifndef HAVE_INOTIFY
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"inotify";
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+295
-130
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -35,6 +35,11 @@ const char* introspection_xml_template =
|
|||||||
" <method name=\"GetVersion\">\n"
|
" <method name=\"GetVersion\">\n"
|
||||||
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
|
" <arg name=\"version\" direction=\"out\" type=\"s\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
" <method name=\"GetLoopServers\">\n"
|
||||||
|
" <arg name=\"server\" direction=\"out\" type=\"as\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
|
#endif
|
||||||
" <method name=\"SetServers\">\n"
|
" <method name=\"SetServers\">\n"
|
||||||
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
" <arg name=\"servers\" direction=\"in\" type=\"av\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
@@ -44,6 +49,12 @@ const char* introspection_xml_template =
|
|||||||
" <method name=\"SetServersEx\">\n"
|
" <method name=\"SetServersEx\">\n"
|
||||||
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
" <arg name=\"servers\" direction=\"in\" type=\"aas\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
|
" <method name=\"SetFilterWin2KOption\">\n"
|
||||||
|
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
|
" <method name=\"SetBogusPrivOption\">\n"
|
||||||
|
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
" <signal name=\"DhcpLeaseAdded\">\n"
|
" <signal name=\"DhcpLeaseAdded\">\n"
|
||||||
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||||
@@ -59,6 +70,21 @@ const char* introspection_xml_template =
|
|||||||
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||||
" <arg name=\"hostname\" type=\"s\"/>\n"
|
" <arg name=\"hostname\" type=\"s\"/>\n"
|
||||||
" </signal>\n"
|
" </signal>\n"
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
" <method name=\"AddDhcpLease\">\n"
|
||||||
|
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||||
|
" <arg name=\"hwaddr\" type=\"s\"/>\n"
|
||||||
|
" <arg name=\"hostname\" type=\"ay\"/>\n"
|
||||||
|
" <arg name=\"clid\" type=\"ay\"/>\n"
|
||||||
|
" <arg name=\"lease_duration\" type=\"u\"/>\n"
|
||||||
|
" <arg name=\"ia_id\" type=\"u\"/>\n"
|
||||||
|
" <arg name=\"is_temporary\" type=\"b\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
|
" <method name=\"DeleteDhcpLease\">\n"
|
||||||
|
" <arg name=\"ipaddr\" type=\"s\"/>\n"
|
||||||
|
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
|
#endif
|
||||||
" </interface>\n"
|
" </interface>\n"
|
||||||
"</node>\n";
|
"</node>\n";
|
||||||
|
|
||||||
@@ -108,108 +134,6 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|||||||
w = data; /* no warning */
|
w = data; /* no warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_update_server(union mysockaddr *addr,
|
|
||||||
union mysockaddr *source_addr,
|
|
||||||
const char *interface,
|
|
||||||
const char *domain)
|
|
||||||
{
|
|
||||||
struct server *serv;
|
|
||||||
|
|
||||||
/* See if there is a suitable candidate, and unmark */
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
if ((serv->flags & SERV_FROM_DBUS) &&
|
|
||||||
(serv->flags & SERV_MARK))
|
|
||||||
{
|
|
||||||
if (domain)
|
|
||||||
{
|
|
||||||
if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (serv->flags & SERV_HAS_DOMAIN)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
serv->flags &= ~SERV_MARK;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!serv && (serv = whine_malloc(sizeof (struct server))))
|
|
||||||
{
|
|
||||||
/* Not found, create a new one. */
|
|
||||||
memset(serv, 0, sizeof(struct server));
|
|
||||||
|
|
||||||
if (domain && !(serv->domain = whine_malloc(strlen(domain)+1)))
|
|
||||||
{
|
|
||||||
free(serv);
|
|
||||||
serv = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serv->next = daemon->servers;
|
|
||||||
daemon->servers = serv;
|
|
||||||
serv->flags = SERV_FROM_DBUS;
|
|
||||||
if (domain)
|
|
||||||
{
|
|
||||||
strcpy(serv->domain, domain);
|
|
||||||
serv->flags |= SERV_HAS_DOMAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (serv)
|
|
||||||
{
|
|
||||||
if (interface)
|
|
||||||
strcpy(serv->interface, interface);
|
|
||||||
else
|
|
||||||
serv->interface[0] = 0;
|
|
||||||
|
|
||||||
if (source_addr->in.sin_family == AF_INET &&
|
|
||||||
addr->in.sin_addr.s_addr == 0 &&
|
|
||||||
serv->domain)
|
|
||||||
serv->flags |= SERV_NO_ADDR;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serv->flags &= ~SERV_NO_ADDR;
|
|
||||||
serv->addr = *addr;
|
|
||||||
serv->source_addr = *source_addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mark_dbus(void)
|
|
||||||
{
|
|
||||||
struct server *serv;
|
|
||||||
|
|
||||||
/* mark everything from DBUS */
|
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
if (serv->flags & SERV_FROM_DBUS)
|
|
||||||
serv->flags |= SERV_MARK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void cleanup_dbus()
|
|
||||||
{
|
|
||||||
struct server *serv, *tmp, **up;
|
|
||||||
|
|
||||||
/* unlink and free anything still marked. */
|
|
||||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
|
||||||
{
|
|
||||||
tmp = serv->next;
|
|
||||||
if (serv->flags & SERV_MARK)
|
|
||||||
{
|
|
||||||
server_gone(serv);
|
|
||||||
*up = serv->next;
|
|
||||||
if (serv->domain)
|
|
||||||
free(serv->domain);
|
|
||||||
free(serv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
up = &serv->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dbus_read_servers(DBusMessage *message)
|
static void dbus_read_servers(DBusMessage *message)
|
||||||
{
|
{
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
@@ -218,8 +142,8 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
|
|
||||||
dbus_message_iter_init(message, &iter);
|
dbus_message_iter_init(message, &iter);
|
||||||
|
|
||||||
mark_dbus();
|
mark_servers(SERV_FROM_DBUS);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
@@ -252,13 +176,16 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
dbus_message_iter_get_basic(&iter, &p[i]);
|
dbus_message_iter_get_basic(&iter, &p[i]);
|
||||||
dbus_message_iter_next (&iter);
|
dbus_message_iter_next (&iter);
|
||||||
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BYTE)
|
||||||
break;
|
{
|
||||||
|
i++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_IPV6
|
#ifndef HAVE_IPV6
|
||||||
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
|
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
|
||||||
#else
|
#else
|
||||||
if (i == sizeof(struct in6_addr)-1)
|
if (i == sizeof(struct in6_addr))
|
||||||
{
|
{
|
||||||
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
|
memcpy(&addr.in6.sin6_addr, p, sizeof(struct in6_addr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
@@ -289,15 +216,38 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
domain = NULL;
|
domain = NULL;
|
||||||
|
|
||||||
if (!skip)
|
if (!skip)
|
||||||
add_update_server(&addr, &source_addr, NULL, domain);
|
add_update_server(SERV_FROM_DBUS, &addr, &source_addr, NULL, domain);
|
||||||
|
|
||||||
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
} while (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unlink and free anything still marked. */
|
/* unlink and free anything still marked. */
|
||||||
cleanup_dbus();
|
cleanup_servers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
|
||||||
|
{
|
||||||
|
DBusMessageIter args, args_iter;
|
||||||
|
struct server *serv;
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||||
|
|
||||||
|
dbus_message_iter_init_append (reply, &args);
|
||||||
|
dbus_message_iter_open_container (&args, DBUS_TYPE_ARRAY,DBUS_TYPE_STRING_AS_STRING, &args_iter);
|
||||||
|
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (serv->flags & SERV_LOOP)
|
||||||
|
{
|
||||||
|
prettyprint_addr(&serv->addr, daemon->addrbuff);
|
||||||
|
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_close_container (&args, &args_iter);
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
||||||
{
|
{
|
||||||
DBusMessageIter iter, array_iter, string_iter;
|
DBusMessageIter iter, array_iter, string_iter;
|
||||||
@@ -319,7 +269,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
strings ? "Expected array of string" : "Expected array of string arrays");
|
strings ? "Expected array of string" : "Expected array of string arrays");
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_dbus();
|
mark_servers(SERV_FROM_DBUS);
|
||||||
|
|
||||||
/* array_iter points to each "as" element in the outer array */
|
/* array_iter points to each "as" element in the outer array */
|
||||||
dbus_message_iter_recurse(&iter, &array_iter);
|
dbus_message_iter_recurse(&iter, &array_iter);
|
||||||
@@ -327,6 +277,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
{
|
{
|
||||||
const char *str = NULL;
|
const char *str = NULL;
|
||||||
union mysockaddr addr, source_addr;
|
union mysockaddr addr, source_addr;
|
||||||
|
int flags = 0;
|
||||||
char interface[IF_NAMESIZE];
|
char interface[IF_NAMESIZE];
|
||||||
char *str_addr, *str_domain = NULL;
|
char *str_addr, *str_domain = NULL;
|
||||||
|
|
||||||
@@ -416,16 +367,19 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
memset(&interface, 0, sizeof(interface));
|
memset(&interface, 0, sizeof(interface));
|
||||||
|
|
||||||
/* parse the IP address */
|
/* parse the IP address */
|
||||||
addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, NULL);
|
if ((addr_err = parse_server(str_addr, &addr, &source_addr, (char *) &interface, &flags)))
|
||||||
|
{
|
||||||
if (addr_err)
|
|
||||||
{
|
|
||||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
"Invalid IP address '%s': %s",
|
"Invalid IP address '%s': %s",
|
||||||
str, addr_err);
|
str, addr_err);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 0.0.0.0 for server address == NULL, for Dbus */
|
||||||
|
if (addr.in.sin_family == AF_INET &&
|
||||||
|
addr.in.sin_addr.s_addr == 0)
|
||||||
|
flags |= SERV_NO_ADDR;
|
||||||
|
|
||||||
if (strings)
|
if (strings)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
@@ -439,7 +393,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
else
|
else
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
|
||||||
add_update_server(&addr, &source_addr, interface, str_domain);
|
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain);
|
||||||
} while ((str_domain = p));
|
} while ((str_domain = p));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -454,7 +408,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
dbus_message_iter_get_basic(&string_iter, &str);
|
dbus_message_iter_get_basic(&string_iter, &str);
|
||||||
dbus_message_iter_next (&string_iter);
|
dbus_message_iter_next (&string_iter);
|
||||||
|
|
||||||
add_update_server(&addr, &source_addr, interface, str);
|
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str);
|
||||||
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,7 +416,7 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
dbus_message_iter_next(&array_iter);
|
dbus_message_iter_next(&array_iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup_dbus();
|
cleanup_servers();
|
||||||
|
|
||||||
if (dup)
|
if (dup)
|
||||||
free(dup);
|
free(dup);
|
||||||
@@ -470,6 +424,196 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DBusMessage *dbus_set_bool(DBusMessage *message, int flag, 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);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_syslog(LOG_INFO, _("Disabling --%s option from D-Bus"), name);
|
||||||
|
reset_option_bool(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
static DBusMessage *dbus_add_lease(DBusMessage* message)
|
||||||
|
{
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
const char *ipaddr, *hwaddr, *hostname, *tmp;
|
||||||
|
const unsigned char* clid;
|
||||||
|
int clid_len, hostname_len, hw_len, hw_type;
|
||||||
|
dbus_uint32_t expires, ia_id;
|
||||||
|
dbus_bool_t is_temporary;
|
||||||
|
struct all_addr addr;
|
||||||
|
time_t now = dnsmasq_time();
|
||||||
|
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
|
||||||
|
|
||||||
|
DBusMessageIter iter, array_iter;
|
||||||
|
if (!dbus_message_iter_init(message, &iter))
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Failed to initialize dbus message iter");
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected string as first argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected string as second argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &hwaddr);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||||
|
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected byte array as third argument");
|
||||||
|
|
||||||
|
dbus_message_iter_recurse(&iter, &array_iter);
|
||||||
|
dbus_message_iter_get_fixed_array(&array_iter, &hostname, &hostname_len);
|
||||||
|
tmp = memchr(hostname, '\0', hostname_len);
|
||||||
|
if (tmp)
|
||||||
|
{
|
||||||
|
if (tmp == &hostname[hostname_len - 1])
|
||||||
|
hostname_len--;
|
||||||
|
else
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Hostname contains an embedded NUL character");
|
||||||
|
}
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if ((dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) ||
|
||||||
|
(dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE))
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected byte array as fourth argument");
|
||||||
|
|
||||||
|
dbus_message_iter_recurse(&iter, &array_iter);
|
||||||
|
dbus_message_iter_get_fixed_array(&array_iter, &clid, &clid_len);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected uint32 as fifth argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &expires);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected uint32 as sixth argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &ia_id);
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected uint32 as sixth argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &is_temporary);
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||||
|
{
|
||||||
|
if (ia_id != 0 || is_temporary)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"ia_id and is_temporary must be zero for IPv4 lease");
|
||||||
|
|
||||||
|
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
|
||||||
|
lease = lease4_allocate(addr.addr.addr4);
|
||||||
|
}
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||||
|
{
|
||||||
|
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
|
||||||
|
lease = lease6_allocate(&addr.addr.addr6,
|
||||||
|
is_temporary ? LEASE_TA : LEASE_NA);
|
||||||
|
lease_set_iaid(lease, ia_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s'", ipaddr);
|
||||||
|
|
||||||
|
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
|
||||||
|
&hw_type);
|
||||||
|
if (hw_type == 0 && hw_len != 0)
|
||||||
|
hw_type = ARPHRD_ETHER;
|
||||||
|
|
||||||
|
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
|
||||||
|
clid_len, now, 0);
|
||||||
|
lease_set_expires(lease, expires, now);
|
||||||
|
if (hostname_len != 0)
|
||||||
|
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
|
||||||
|
|
||||||
|
lease_update_file(now);
|
||||||
|
lease_update_dns(0);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DBusMessage *dbus_del_lease(DBusMessage* message)
|
||||||
|
{
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
DBusMessageIter iter;
|
||||||
|
const char *ipaddr;
|
||||||
|
DBusMessage *reply;
|
||||||
|
struct all_addr addr;
|
||||||
|
dbus_bool_t ret = 1;
|
||||||
|
time_t now = dnsmasq_time();
|
||||||
|
|
||||||
|
if (!dbus_message_iter_init(message, &iter))
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Failed to initialize dbus message iter");
|
||||||
|
|
||||||
|
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Expected string as first argument");
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
||||||
|
lease = lease_find_by_addr(addr.addr.addr4);
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
||||||
|
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
|
||||||
|
#endif
|
||||||
|
else
|
||||||
|
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s'", ipaddr);
|
||||||
|
|
||||||
|
if (lease)
|
||||||
|
{
|
||||||
|
lease_prune(lease, now);
|
||||||
|
lease_update_file(now);
|
||||||
|
lease_update_dns(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if ((reply = dbus_message_new_method_return(message)))
|
||||||
|
dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &ret,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||||
DBusMessage *message,
|
DBusMessage *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
@@ -498,6 +642,12 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
|
|
||||||
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
dbus_message_append_args(reply, DBUS_TYPE_STRING, &v, DBUS_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
else if (strcmp(method, "GetLoopServers") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_reply_server_loop(message);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (strcmp(method, "SetServers") == 0)
|
else if (strcmp(method, "SetServers") == 0)
|
||||||
{
|
{
|
||||||
dbus_read_servers(message);
|
dbus_read_servers(message);
|
||||||
@@ -513,6 +663,24 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
reply = dbus_read_servers_ex(message, 1);
|
reply = dbus_read_servers_ex(message, 1);
|
||||||
new_servers = 1;
|
new_servers = 1;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(method, "SetFilterWin2KOption") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
|
||||||
|
}
|
||||||
|
else if (strcmp(method, "SetBogusPrivOption") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||||
|
}
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
else if (strcmp(method, "AddDhcpLease") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_add_lease(message);
|
||||||
|
}
|
||||||
|
else if (strcmp(method, "DeleteDhcpLease") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_del_lease(message);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
else if (strcmp(method, "ClearCache") == 0)
|
else if (strcmp(method, "ClearCache") == 0)
|
||||||
clear_cache = 1;
|
clear_cache = 1;
|
||||||
else
|
else
|
||||||
@@ -581,8 +749,7 @@ char *dbus_init(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void set_dbus_listeners(int *maxfdp,
|
void set_dbus_listeners(void)
|
||||||
fd_set *rset, fd_set *wset, fd_set *eset)
|
|
||||||
{
|
{
|
||||||
struct watch *w;
|
struct watch *w;
|
||||||
|
|
||||||
@@ -592,19 +759,17 @@ void set_dbus_listeners(int *maxfdp,
|
|||||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||||
|
|
||||||
bump_maxfd(fd, maxfdp);
|
|
||||||
|
|
||||||
if (flags & DBUS_WATCH_READABLE)
|
if (flags & DBUS_WATCH_READABLE)
|
||||||
FD_SET(fd, rset);
|
poll_listen(fd, POLLIN);
|
||||||
|
|
||||||
if (flags & DBUS_WATCH_WRITABLE)
|
if (flags & DBUS_WATCH_WRITABLE)
|
||||||
FD_SET(fd, wset);
|
poll_listen(fd, POLLOUT);
|
||||||
|
|
||||||
FD_SET(fd, eset);
|
poll_listen(fd, POLLERR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
void check_dbus_listeners()
|
||||||
{
|
{
|
||||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||||
struct watch *w;
|
struct watch *w;
|
||||||
@@ -615,13 +780,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
|||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||||
|
|
||||||
if (FD_ISSET(fd, rset))
|
if (poll_check(fd, POLLIN))
|
||||||
flags |= DBUS_WATCH_READABLE;
|
flags |= DBUS_WATCH_READABLE;
|
||||||
|
|
||||||
if (FD_ISSET(fd, wset))
|
if (poll_check(fd, POLLOUT))
|
||||||
flags |= DBUS_WATCH_WRITABLE;
|
flags |= DBUS_WATCH_WRITABLE;
|
||||||
|
|
||||||
if (FD_ISSET(fd, eset))
|
if (poll_check(fd, POLLERR))
|
||||||
flags |= DBUS_WATCH_ERROR;
|
flags |= DBUS_WATCH_ERROR;
|
||||||
|
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
@@ -656,7 +821,7 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname)
|
|||||||
if (lease->flags & (LEASE_TA | LEASE_NA))
|
if (lease->flags & (LEASE_TA | LEASE_NA))
|
||||||
{
|
{
|
||||||
print_mac(mac, lease->clid, lease->clid_len);
|
print_mac(mac, lease->clid, lease->clid_len);
|
||||||
inet_ntop(AF_INET6, lease->hwaddr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, &lease->addr6, daemon->addrbuff, ADDRSTRLEN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -545,8 +545,8 @@ static const struct opttab_t {
|
|||||||
{ "parameter-request", 55, OT_INTERNAL },
|
{ "parameter-request", 55, OT_INTERNAL },
|
||||||
{ "message", 56, OT_INTERNAL },
|
{ "message", 56, OT_INTERNAL },
|
||||||
{ "max-message-size", 57, OT_INTERNAL },
|
{ "max-message-size", 57, OT_INTERNAL },
|
||||||
{ "T1", 58, OT_INTERNAL | OT_TIME},
|
{ "T1", 58, OT_TIME},
|
||||||
{ "T2", 59, OT_INTERNAL | OT_TIME},
|
{ "T2", 59, OT_TIME},
|
||||||
{ "vendor-class", 60, 0 },
|
{ "vendor-class", 60, 0 },
|
||||||
{ "client-id", 61, OT_INTERNAL },
|
{ "client-id", 61, OT_INTERNAL },
|
||||||
{ "nis+-domain", 64, OT_NAME },
|
{ "nis+-domain", 64, OT_NAME },
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+36
-27
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -225,18 +225,21 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* One form of bridging on BSD has the property that packets
|
/* If the interface on which the DHCP request was received is an
|
||||||
can be recieved on bridge interfaces which do not have an IP address.
|
alias of some other interface (as specified by the
|
||||||
We allow these to be treated as aliases of another interface which does have
|
--bridge-interface option), change ifr.ifr_name so that we look
|
||||||
an IP address with --dhcp-bridge=interface,alias,alias */
|
for DHCP contexts associated with the aliased interface instead
|
||||||
|
of with the aliasing one. */
|
||||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||||
{
|
{
|
||||||
for (alias = bridge->alias; alias; alias = alias->next)
|
for (alias = bridge->alias; alias; alias = alias->next)
|
||||||
if (strncmp(ifr.ifr_name, alias->iface, IF_NAMESIZE) == 0)
|
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
|
||||||
{
|
{
|
||||||
if (!(iface_index = if_nametoindex(bridge->iface)))
|
if (!(iface_index = if_nametoindex(bridge->iface)))
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING, _("unknown interface %s in bridge-interface"), ifr.ifr_name);
|
my_syslog(MS_DHCP | LOG_WARNING,
|
||||||
|
_("unknown interface %s in bridge-interface"),
|
||||||
|
bridge->iface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -376,10 +379,9 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
|
else
|
||||||
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
|
|
||||||
{
|
{
|
||||||
/* broadcast to 255.255.255.255 (or mac address invalid) */
|
/* fill cmsg for outbound interface (both broadcast & unicast) */
|
||||||
struct in_pktinfo *pkt;
|
struct in_pktinfo *pkt;
|
||||||
msg.msg_control = control_u.control;
|
msg.msg_control = control_u.control;
|
||||||
msg.msg_controllen = sizeof(control_u);
|
msg.msg_controllen = sizeof(control_u);
|
||||||
@@ -389,22 +391,29 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
pkt->ipi_spec_dst.s_addr = 0;
|
pkt->ipi_spec_dst.s_addr = 0;
|
||||||
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||||
cmptr->cmsg_level = IPPROTO_IP;
|
cmptr->cmsg_level = IPPROTO_IP;
|
||||||
cmptr->cmsg_type = IP_PKTINFO;
|
cmptr->cmsg_type = IP_PKTINFO;
|
||||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
|
||||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
|
||||||
}
|
mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
|
||||||
else
|
{
|
||||||
{
|
/* broadcast to 255.255.255.255 (or mac address invalid) */
|
||||||
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
|
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||||
struct sockaddr limits size to 14 bytes. */
|
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||||
dest.sin_addr = mess->yiaddr;
|
}
|
||||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
else
|
||||||
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
|
{
|
||||||
arp_req.arp_ha.sa_family = mess->htype;
|
/* unicast to unconfigured client. Inject mac address direct into ARP cache.
|
||||||
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
struct sockaddr limits size to 14 bytes. */
|
||||||
/* interface name already copied in */
|
dest.sin_addr = mess->yiaddr;
|
||||||
arp_req.arp_flags = ATF_COM;
|
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||||
ioctl(daemon->dhcpfd, SIOCSARP, &arp_req);
|
memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
|
||||||
|
arp_req.arp_ha.sa_family = mess->htype;
|
||||||
|
memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
|
||||||
|
/* interface name already copied in */
|
||||||
|
arp_req.arp_flags = ATF_COM;
|
||||||
|
if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
|
||||||
|
my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||||
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
|
else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
|
||||||
@@ -442,7 +451,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while(sendmsg(fd, &msg, 0) == -1 && retry_send());
|
while(retry_send(sendmsg(fd, &msg, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check against secondary interface addresses */
|
/* check against secondary interface addresses */
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+35
-8
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -144,6 +144,8 @@ void dhcp6_packet(time_t now)
|
|||||||
|
|
||||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
|
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
|
||||||
{
|
{
|
||||||
|
struct dhcp_bridge *bridge, *alias;
|
||||||
|
|
||||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||||
return;
|
return;
|
||||||
@@ -160,6 +162,30 @@ void dhcp6_packet(time_t now)
|
|||||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||||
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
||||||
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
||||||
|
|
||||||
|
/* If the interface on which the DHCPv6 request was received is
|
||||||
|
an alias of some other interface (as specified by the
|
||||||
|
--bridge-interface option), change parm.ind so that we look
|
||||||
|
for DHCPv6 contexts associated with the aliased interface
|
||||||
|
instead of with the aliasing one. */
|
||||||
|
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||||
|
{
|
||||||
|
for (alias = bridge->alias; alias; alias = alias->next)
|
||||||
|
if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
|
||||||
|
{
|
||||||
|
parm.ind = if_nametoindex(bridge->iface);
|
||||||
|
if (!parm.ind)
|
||||||
|
{
|
||||||
|
my_syslog(MS_DHCP | LOG_WARNING,
|
||||||
|
_("unknown interface %s in bridge-interface"),
|
||||||
|
bridge->iface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (alias)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
|
if (IN6_IS_ADDR_UNSPECIFIED(&context->start6) && context->prefix == 0)
|
||||||
@@ -208,7 +234,7 @@ void dhcp6_packet(time_t now)
|
|||||||
/* May have configured relay, but not DHCP server */
|
/* May have configured relay, but not DHCP server */
|
||||||
if (!daemon->doing_dhcp6)
|
if (!daemon->doing_dhcp6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
lease_prune(NULL, now); /* lose any expired leases */
|
lease_prune(NULL, now); /* lose any expired leases */
|
||||||
|
|
||||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||||
@@ -225,9 +251,9 @@ void dhcp6_packet(time_t now)
|
|||||||
if (port != 0)
|
if (port != 0)
|
||||||
{
|
{
|
||||||
from.sin6_port = htons(port);
|
from.sin6_port = htons(port);
|
||||||
while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
|
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||||
0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
|
save_counter(0), 0, (struct sockaddr *)&from,
|
||||||
retry_send());
|
sizeof(from))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +272,9 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
|
|||||||
neigh.code = 0;
|
neigh.code = 0;
|
||||||
neigh.reserved = 0;
|
neigh.reserved = 0;
|
||||||
neigh.target = *client;
|
neigh.target = *client;
|
||||||
|
/* RFC4443 section-2.3: checksum has to be zero to be calculated */
|
||||||
|
neigh.checksum = 0;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
addr.sin6_len = sizeof(struct sockaddr_in6);
|
addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
@@ -727,8 +755,7 @@ void dhcp_construct_contexts(time_t now)
|
|||||||
|
|
||||||
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
|
if (context->flags & CONTEXT_GC && !(context->flags & CONTEXT_OLD))
|
||||||
{
|
{
|
||||||
if ((context->flags & (CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)) ||
|
if ((context->flags & CONTEXT_RA) || option_bool(OPT_RA))
|
||||||
option_bool(OPT_RA))
|
|
||||||
{
|
{
|
||||||
/* previously constructed context has gone. advertise it's demise */
|
/* previously constructed context has gone. advertise it's demise */
|
||||||
context->flags |= CONTEXT_OLD;
|
context->flags |= CONTEXT_OLD;
|
||||||
|
|||||||
+17
-8
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -68,6 +68,7 @@
|
|||||||
#define T_RRSIG 46
|
#define T_RRSIG 46
|
||||||
#define T_NSEC 47
|
#define T_NSEC 47
|
||||||
#define T_DNSKEY 48
|
#define T_DNSKEY 48
|
||||||
|
#define T_NSEC3 50
|
||||||
#define T_TKEY 249
|
#define T_TKEY 249
|
||||||
#define T_TSIG 250
|
#define T_TSIG 250
|
||||||
#define T_AXFR 252
|
#define T_AXFR 252
|
||||||
@@ -83,15 +84,15 @@ struct dns_header {
|
|||||||
u16 qdcount,ancount,nscount,arcount;
|
u16 qdcount,ancount,nscount,arcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HB3_QR 0x80
|
#define HB3_QR 0x80 /* Query */
|
||||||
#define HB3_OPCODE 0x78
|
#define HB3_OPCODE 0x78
|
||||||
#define HB3_AA 0x04
|
#define HB3_AA 0x04 /* Authoritative Answer */
|
||||||
#define HB3_TC 0x02
|
#define HB3_TC 0x02 /* TrunCated */
|
||||||
#define HB3_RD 0x01
|
#define HB3_RD 0x01 /* Recursion Desired */
|
||||||
|
|
||||||
#define HB4_RA 0x80
|
#define HB4_RA 0x80 /* Recursion Available */
|
||||||
#define HB4_AD 0x20
|
#define HB4_AD 0x20 /* Authenticated Data */
|
||||||
#define HB4_CD 0x10
|
#define HB4_CD 0x10 /* Checking Disabled */
|
||||||
#define HB4_RCODE 0x0f
|
#define HB4_RCODE 0x0f
|
||||||
|
|
||||||
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
|
#define OPCODE(x) (((x)->hb3 & HB3_OPCODE) >> 3)
|
||||||
@@ -141,3 +142,11 @@ struct dns_header {
|
|||||||
|
|
||||||
#define ADD_RDLEN(header, pp, plen, len) \
|
#define ADD_RDLEN(header, pp, plen, len) \
|
||||||
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
(!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
|
||||||
|
|
||||||
|
/* Escape character in our presentation format for names.
|
||||||
|
Cannot be '.' or /000 and must be !isprint().
|
||||||
|
Note that escaped chars are stored as
|
||||||
|
<NAME_ESCAPE> <orig-char+1>
|
||||||
|
to ensure that the escaped form of /000 doesn't include /000
|
||||||
|
*/
|
||||||
|
#define NAME_ESCAPE 1
|
||||||
+280
-189
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,12 +24,13 @@ struct daemon *daemon;
|
|||||||
static volatile pid_t pid = 0;
|
static volatile pid_t pid = 0;
|
||||||
static volatile int pipewrite;
|
static volatile int pipewrite;
|
||||||
|
|
||||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
|
static int set_dns_listeners(time_t now);
|
||||||
static void check_dns_listeners(fd_set *set, time_t now);
|
static void check_dns_listeners(time_t now);
|
||||||
static void sig_handler(int sig);
|
static void sig_handler(int sig);
|
||||||
static void async_event(int pipe, time_t now);
|
static void async_event(int pipe, time_t now);
|
||||||
static void fatal_event(struct event_desc *ev, char *msg);
|
static void fatal_event(struct event_desc *ev, char *msg);
|
||||||
static int read_event(int fd, struct event_desc *evp, char **msg);
|
static int read_event(int fd, struct event_desc *evp, char **msg);
|
||||||
|
static void poll_resolv(int force, int do_reload, time_t now);
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -57,6 +58,9 @@ int main (int argc, char **argv)
|
|||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct dhcp_relay *relay;
|
struct dhcp_relay *relay;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_TFTP
|
||||||
|
int tftp_prefix_missing = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef LOCALEDIR
|
#ifdef LOCALEDIR
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@@ -79,26 +83,39 @@ int main (int argc, char **argv)
|
|||||||
sigaction(SIGPIPE, &sigact, NULL);
|
sigaction(SIGPIPE, &sigact, NULL);
|
||||||
|
|
||||||
umask(022); /* known umask, create leases and pid files as 0644 */
|
umask(022); /* known umask, create leases and pid files as 0644 */
|
||||||
|
|
||||||
|
rand_init(); /* Must precede read_opts() */
|
||||||
|
|
||||||
read_opts(argc, argv, compile_opts);
|
read_opts(argc, argv, compile_opts);
|
||||||
|
|
||||||
if (daemon->edns_pktsz < PACKETSZ)
|
if (daemon->edns_pktsz < PACKETSZ)
|
||||||
daemon->edns_pktsz = PACKETSZ;
|
daemon->edns_pktsz = PACKETSZ;
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
/* Enforce min packet big enough for DNSSEC */
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && daemon->edns_pktsz < EDNS_PKTSZ)
|
|
||||||
daemon->edns_pktsz = EDNS_PKTSZ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
|
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
|
||||||
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
|
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
|
||||||
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
||||||
|
|
||||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||||
|
if (option_bool(OPT_EXTRALOG))
|
||||||
|
daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
daemon->keyname = safe_malloc(MAXDNAME);
|
{
|
||||||
|
/* Note that both /000 and '.' are allowed within labels. These get
|
||||||
|
represented in presentation format using NAME_ESCAPE as an escape
|
||||||
|
character when in DNSSEC mode.
|
||||||
|
In theory, if all the characters in a name were /000 or
|
||||||
|
'.' or NAME_ESCAPE then all would have to be escaped, so the
|
||||||
|
presentation format would be twice as long as the spec.
|
||||||
|
|
||||||
|
daemon->namebuff was previously allocated by the option-reading
|
||||||
|
code before we knew if we're in DNSSEC mode, so reallocate here. */
|
||||||
|
free(daemon->namebuff);
|
||||||
|
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
||||||
|
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
||||||
|
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
@@ -140,15 +157,20 @@ int main (int argc, char **argv)
|
|||||||
reset_option_bool(OPT_CLEVERBIND);
|
reset_option_bool(OPT_CLEVERBIND);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_INOTIFY
|
||||||
|
if (daemon->dynamic_dirs)
|
||||||
|
die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (!daemon->dnskeys)
|
if (!daemon->ds)
|
||||||
die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
|
die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
if (daemon->cachesize < CACHESIZ)
|
if (daemon->cachesize < CACHESIZ)
|
||||||
die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
|
die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
|
||||||
#else
|
#else
|
||||||
die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
|
die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
@@ -161,10 +183,10 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
|
if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
|
||||||
die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
|
die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
|
||||||
#else
|
#else
|
||||||
if (option_bool(OPT_CONNTRACK))
|
if (option_bool(OPT_CONNTRACK))
|
||||||
die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
|
die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SOLARIS_NETWORK
|
#ifdef HAVE_SOLARIS_NETWORK
|
||||||
@@ -182,7 +204,10 @@ int main (int argc, char **argv)
|
|||||||
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
|
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rand_init();
|
#ifndef HAVE_LOOP
|
||||||
|
if (option_bool(OPT_LOOP_DETECT))
|
||||||
|
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
@@ -306,11 +331,19 @@ int main (int argc, char **argv)
|
|||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
{
|
{
|
||||||
cache_init();
|
cache_init();
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
blockdata_init();
|
blockdata_init();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
inotify_dnsmasq_init();
|
||||||
|
else
|
||||||
|
daemon->inotifyfd = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (option_bool(OPT_DBUS))
|
if (option_bool(OPT_DBUS))
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
{
|
{
|
||||||
@@ -323,7 +356,7 @@ int main (int argc, char **argv)
|
|||||||
#else
|
#else
|
||||||
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
|
die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
pre_allocate_sfds();
|
pre_allocate_sfds();
|
||||||
|
|
||||||
@@ -350,7 +383,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (baduser)
|
if (baduser)
|
||||||
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
|
die(_("unknown user or group: %s"), baduser, EC_BADCONF);
|
||||||
|
|
||||||
/* implement group defaults, "dip" if available, or group associated with uid */
|
/* implement group defaults, "dip" if available, or group associated with uid */
|
||||||
if (!daemon->group_set && !gp)
|
if (!daemon->group_set && !gp)
|
||||||
{
|
{
|
||||||
@@ -394,7 +427,7 @@ int main (int argc, char **argv)
|
|||||||
piperead = pipefd[0];
|
piperead = pipefd[0];
|
||||||
pipewrite = pipefd[1];
|
pipewrite = pipefd[1];
|
||||||
/* prime the pipe to load stuff first time. */
|
/* prime the pipe to load stuff first time. */
|
||||||
send_event(pipewrite, EVENT_RELOAD, 0, NULL);
|
send_event(pipewrite, EVENT_INIT, 0, NULL);
|
||||||
|
|
||||||
err_pipe[1] = -1;
|
err_pipe[1] = -1;
|
||||||
|
|
||||||
@@ -425,7 +458,7 @@ int main (int argc, char **argv)
|
|||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
/* close our copy of write-end */
|
/* close our copy of write-end */
|
||||||
close(err_pipe[1]);
|
while (retry_send(close(err_pipe[1])));
|
||||||
|
|
||||||
/* check for errors after the fork */
|
/* check for errors after the fork */
|
||||||
if (read_event(err_pipe[0], &ev, &msg))
|
if (read_event(err_pipe[0], &ev, &msg))
|
||||||
@@ -434,7 +467,7 @@ int main (int argc, char **argv)
|
|||||||
_exit(EC_GOOD);
|
_exit(EC_GOOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(err_pipe[0]);
|
while (retry_send(close(err_pipe[0])));
|
||||||
|
|
||||||
/* NO calls to die() from here on. */
|
/* NO calls to die() from here on. */
|
||||||
|
|
||||||
@@ -486,10 +519,12 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
||||||
err = 1;
|
err = 1;
|
||||||
|
else
|
||||||
while (!err && close(fd) == -1)
|
{
|
||||||
if (!retry_send())
|
while (retry_send(close(fd)));
|
||||||
err = 1;
|
if (errno != 0)
|
||||||
|
err = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
@@ -608,12 +643,14 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
free(hdr);
|
||||||
|
free(data);
|
||||||
if (option_bool(OPT_DEBUG))
|
if (option_bool(OPT_DEBUG))
|
||||||
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (option_bool(OPT_TFTP))
|
if (option_bool(OPT_TFTP))
|
||||||
{
|
{
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
struct tftp_prefix *p;
|
struct tftp_prefix *p;
|
||||||
@@ -622,20 +659,31 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
if (!((dir = opendir(daemon->tftp_prefix))))
|
if (!((dir = opendir(daemon->tftp_prefix))))
|
||||||
{
|
{
|
||||||
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
|
tftp_prefix_missing = 1;
|
||||||
_exit(0);
|
if (!option_bool(OPT_TFTP_NO_FAIL))
|
||||||
|
{
|
||||||
|
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
closedir(dir);
|
else
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (p = daemon->if_prefix; p; p = p->next)
|
for (p = daemon->if_prefix; p; p = p->next)
|
||||||
{
|
{
|
||||||
|
p->missing = 0;
|
||||||
if (!((dir = opendir(p->prefix))))
|
if (!((dir = opendir(p->prefix))))
|
||||||
{
|
{
|
||||||
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
|
p->missing = 1;
|
||||||
_exit(0);
|
if (!option_bool(OPT_TFTP_NO_FAIL))
|
||||||
}
|
{
|
||||||
closedir(dir);
|
send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -658,10 +706,32 @@ int main (int argc, char **argv)
|
|||||||
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
|
my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (option_bool(OPT_LOCAL_SERVICE))
|
||||||
|
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Delay creating the timestamp file until here, after we've changed user, so that
|
||||||
|
it has the correct owner to allow updating the mtime later.
|
||||||
|
This means we have to report fatal errors via the pipe. */
|
||||||
|
if ((rc = setup_timestamp()) == -1)
|
||||||
|
{
|
||||||
|
send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
|
||||||
|
_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
|
||||||
|
|
||||||
|
if (option_bool(OPT_DNSSEC_TIME))
|
||||||
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
|
||||||
|
|
||||||
|
if (rc == 1)
|
||||||
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (log_err != 0)
|
if (log_err != 0)
|
||||||
@@ -726,18 +796,22 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (option_bool(OPT_TFTP))
|
if (option_bool(OPT_TFTP))
|
||||||
{
|
{
|
||||||
#ifdef FD_SETSIZE
|
struct tftp_prefix *p;
|
||||||
if (FD_SETSIZE < (unsigned)max_fd)
|
|
||||||
max_fd = FD_SETSIZE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
|
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
|
||||||
daemon->tftp_prefix ? _("root is ") : _("enabled"),
|
daemon->tftp_prefix ? _("root is ") : _("enabled"),
|
||||||
daemon->tftp_prefix ? daemon->tftp_prefix: "",
|
daemon->tftp_prefix ? daemon->tftp_prefix: "",
|
||||||
option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
|
option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
|
||||||
|
|
||||||
|
if (tftp_prefix_missing)
|
||||||
|
my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
|
||||||
|
|
||||||
|
for (p = daemon->if_prefix; p; p = p->next)
|
||||||
|
if (p->missing)
|
||||||
|
my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
|
||||||
|
|
||||||
/* This is a guess, it assumes that for small limits,
|
/* This is a guess, it assumes that for small limits,
|
||||||
disjoint files might be served, but for large limits,
|
disjoint files might be served, but for large limits,
|
||||||
a single file will be sent to may clients (the file only needs
|
a single file will be sent to may clients (the file only needs
|
||||||
@@ -770,89 +844,72 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
/* finished start-up - release original process */
|
/* finished start-up - release original process */
|
||||||
if (err_pipe[1] != -1)
|
if (err_pipe[1] != -1)
|
||||||
close(err_pipe[1]);
|
while (retry_send(close(err_pipe[1])));
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
check_servers();
|
check_servers();
|
||||||
|
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
/* Using inotify, have to select a resolv file at startup */
|
||||||
|
poll_resolv(1, 0, now);
|
||||||
|
#endif
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
int maxfd = -1;
|
int t, timeout = -1;
|
||||||
struct timeval t, *tp = NULL;
|
|
||||||
fd_set rset, wset, eset;
|
|
||||||
|
|
||||||
FD_ZERO(&rset);
|
poll_reset();
|
||||||
FD_ZERO(&wset);
|
|
||||||
FD_ZERO(&eset);
|
|
||||||
|
|
||||||
/* if we are out of resources, find how long we have to wait
|
/* if we are out of resources, find how long we have to wait
|
||||||
for some to come free, we'll loop around then and restart
|
for some to come free, we'll loop around then and restart
|
||||||
listening for queries */
|
listening for queries */
|
||||||
if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
|
if ((t = set_dns_listeners(now)) != 0)
|
||||||
{
|
timeout = t * 1000;
|
||||||
t.tv_usec = 0;
|
|
||||||
tp = &t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
|
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
|
||||||
if (daemon->tftp_trans ||
|
if (daemon->tftp_trans ||
|
||||||
(option_bool(OPT_DBUS) && !daemon->dbus))
|
(option_bool(OPT_DBUS) && !daemon->dbus))
|
||||||
{
|
timeout = 250;
|
||||||
t.tv_sec = 0;
|
|
||||||
t.tv_usec = 250000;
|
|
||||||
tp = &t;
|
|
||||||
}
|
|
||||||
/* Wake every second whilst waiting for DAD to complete */
|
/* Wake every second whilst waiting for DAD to complete */
|
||||||
else if (is_dad_listeners())
|
else if (is_dad_listeners())
|
||||||
{
|
timeout = 1000;
|
||||||
t.tv_sec = 1;
|
|
||||||
t.tv_usec = 0;
|
|
||||||
tp = &t;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
set_dbus_listeners(&maxfd, &rset, &wset, &eset);
|
set_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->relay4)
|
if (daemon->dhcp || daemon->relay4)
|
||||||
{
|
{
|
||||||
FD_SET(daemon->dhcpfd, &rset);
|
poll_listen(daemon->dhcpfd, POLLIN);
|
||||||
bump_maxfd(daemon->dhcpfd, &maxfd);
|
|
||||||
if (daemon->pxefd != -1)
|
if (daemon->pxefd != -1)
|
||||||
{
|
poll_listen(daemon->pxefd, POLLIN);
|
||||||
FD_SET(daemon->pxefd, &rset);
|
|
||||||
bump_maxfd(daemon->pxefd, &maxfd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->doing_dhcp6 || daemon->relay6)
|
if (daemon->doing_dhcp6 || daemon->relay6)
|
||||||
{
|
poll_listen(daemon->dhcp6fd, POLLIN);
|
||||||
FD_SET(daemon->dhcp6fd, &rset);
|
|
||||||
bump_maxfd(daemon->dhcp6fd, &maxfd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->doing_ra)
|
if (daemon->doing_ra)
|
||||||
{
|
poll_listen(daemon->icmp6fd, POLLIN);
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
#endif
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
|
||||||
}
|
#ifdef HAVE_INOTIFY
|
||||||
|
if (daemon->inotifyfd != -1)
|
||||||
|
poll_listen(daemon->inotifyfd, POLLIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
FD_SET(daemon->netlinkfd, &rset);
|
poll_listen(daemon->netlinkfd, POLLIN);
|
||||||
bump_maxfd(daemon->netlinkfd, &maxfd);
|
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
FD_SET(daemon->routefd, &rset);
|
poll_listen(daemon->routefd, POLLIN);
|
||||||
bump_maxfd(daemon->routefd, &maxfd);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FD_SET(piperead, &rset);
|
poll_listen(piperead, POLLIN);
|
||||||
bump_maxfd(piperead, &maxfd);
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
# ifdef HAVE_SCRIPT
|
# ifdef HAVE_SCRIPT
|
||||||
@@ -863,10 +920,7 @@ int main (int argc, char **argv)
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (!helper_buf_empty())
|
if (!helper_buf_empty())
|
||||||
{
|
poll_listen(daemon->helperfd, POLLOUT);
|
||||||
FD_SET(daemon->helperfd, &wset);
|
|
||||||
bump_maxfd(daemon->helperfd, &maxfd);
|
|
||||||
}
|
|
||||||
# else
|
# else
|
||||||
/* need this for other side-effects */
|
/* need this for other side-effects */
|
||||||
while (do_script_run(now));
|
while (do_script_run(now));
|
||||||
@@ -880,17 +934,14 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
/* must do this just before select(), when we know no
|
/* must do this just before select(), when we know no
|
||||||
more calls to my_syslog() can occur */
|
more calls to my_syslog() can occur */
|
||||||
set_log_writer(&wset, &maxfd);
|
set_log_writer();
|
||||||
|
|
||||||
|
if (do_poll(timeout) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
|
|
||||||
{
|
|
||||||
/* otherwise undefined after error */
|
|
||||||
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
|
|
||||||
}
|
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
check_log_writer(&wset);
|
check_log_writer(0);
|
||||||
|
|
||||||
/* prime. */
|
/* prime. */
|
||||||
enumerate_interfaces(1);
|
enumerate_interfaces(1);
|
||||||
@@ -906,13 +957,20 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
if (poll_check(daemon->netlinkfd, POLLIN))
|
||||||
netlink_multicast(now);
|
netlink_multicast();
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
if (FD_ISSET(daemon->routefd, &rset))
|
if (poll_check(daemon->routefd, POLLIN))
|
||||||
route_sock(now);
|
route_sock();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
|
||||||
|
{
|
||||||
|
if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
|
||||||
|
poll_resolv(1, 1, now);
|
||||||
|
}
|
||||||
|
#else
|
||||||
/* Check for changes to resolv files once per second max. */
|
/* Check for changes to resolv files once per second max. */
|
||||||
/* Don't go silent for long periods if the clock goes backwards. */
|
/* Don't go silent for long periods if the clock goes backwards. */
|
||||||
if (daemon->last_resolv == 0 ||
|
if (daemon->last_resolv == 0 ||
|
||||||
@@ -925,8 +983,9 @@ int main (int argc, char **argv)
|
|||||||
poll_resolv(0, daemon->last_resolv != 0, now);
|
poll_resolv(0, daemon->last_resolv != 0, now);
|
||||||
daemon->last_resolv = now;
|
daemon->last_resolv = now;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (FD_ISSET(piperead, &rset))
|
|
||||||
|
if (poll_check(piperead, POLLIN))
|
||||||
async_event(piperead, now);
|
async_event(piperead, now);
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
@@ -939,34 +998,34 @@ int main (int argc, char **argv)
|
|||||||
if (daemon->dbus)
|
if (daemon->dbus)
|
||||||
my_syslog(LOG_INFO, _("connected to system DBus"));
|
my_syslog(LOG_INFO, _("connected to system DBus"));
|
||||||
}
|
}
|
||||||
check_dbus_listeners(&rset, &wset, &eset);
|
check_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
check_dns_listeners(&rset, now);
|
check_dns_listeners(now);
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
check_tftp_listeners(&rset, now);
|
check_tftp_listeners(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->relay4)
|
if (daemon->dhcp || daemon->relay4)
|
||||||
{
|
{
|
||||||
if (FD_ISSET(daemon->dhcpfd, &rset))
|
if (poll_check(daemon->dhcpfd, POLLIN))
|
||||||
dhcp_packet(now, 0);
|
dhcp_packet(now, 0);
|
||||||
if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
|
if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
|
||||||
dhcp_packet(now, 1);
|
dhcp_packet(now, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset))
|
if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
|
||||||
dhcp6_packet(now);
|
dhcp6_packet(now);
|
||||||
|
|
||||||
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||||
icmp6_packet(now);
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
# ifdef HAVE_SCRIPT
|
# ifdef HAVE_SCRIPT
|
||||||
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
|
if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLIN))
|
||||||
helper_write();
|
helper_write();
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
@@ -1027,6 +1086,11 @@ void send_alarm(time_t event, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void queue_event(int event)
|
||||||
|
{
|
||||||
|
send_event(pipewrite, event, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void send_event(int fd, int event, int data, char *msg)
|
void send_event(int fd, int event, int data, char *msg)
|
||||||
{
|
{
|
||||||
struct event_desc ev;
|
struct event_desc ev;
|
||||||
@@ -1107,6 +1171,9 @@ static void fatal_event(struct event_desc *ev, char *msg)
|
|||||||
|
|
||||||
case EVENT_TFTP_ERR:
|
case EVENT_TFTP_ERR:
|
||||||
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
|
die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
case EVENT_TIME_ERR:
|
||||||
|
die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1114,7 +1181,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
{
|
{
|
||||||
pid_t p;
|
pid_t p;
|
||||||
struct event_desc ev;
|
struct event_desc ev;
|
||||||
int i;
|
int i, check = 0;
|
||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
/* NOTE: the memory used to return msg is leaked: use msgs in events only
|
/* NOTE: the memory used to return msg is leaked: use msgs in events only
|
||||||
@@ -1124,12 +1191,36 @@ static void async_event(int pipe, time_t now)
|
|||||||
switch (ev.event)
|
switch (ev.event)
|
||||||
{
|
{
|
||||||
case EVENT_RELOAD:
|
case EVENT_RELOAD:
|
||||||
clear_cache_and_reload(now);
|
#ifdef HAVE_DNSSEC
|
||||||
if (daemon->port != 0 && daemon->resolv_files && option_bool(OPT_NO_POLL))
|
if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
|
||||||
{
|
{
|
||||||
reload_servers(daemon->resolv_files->name);
|
my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
|
||||||
check_servers();
|
reset_option_bool(OPT_DNSSEC_TIME);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case EVENT_INIT:
|
||||||
|
clear_cache_and_reload(now);
|
||||||
|
|
||||||
|
if (daemon->port != 0)
|
||||||
|
{
|
||||||
|
if (daemon->resolv_files && option_bool(OPT_NO_POLL))
|
||||||
|
{
|
||||||
|
reload_servers(daemon->resolv_files->name);
|
||||||
|
check = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemon->servers_file)
|
||||||
|
{
|
||||||
|
read_servers_file();
|
||||||
|
check = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check)
|
||||||
|
check_servers();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
rerun_scripts();
|
rerun_scripts();
|
||||||
#endif
|
#endif
|
||||||
@@ -1196,7 +1287,17 @@ static void async_event(int pipe, time_t now)
|
|||||||
if (daemon->log_file != NULL)
|
if (daemon->log_file != NULL)
|
||||||
log_reopen(daemon->log_file);
|
log_reopen(daemon->log_file);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EVENT_NEWADDR:
|
||||||
|
newaddress(now);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EVENT_NEWROUTE:
|
||||||
|
resend_query();
|
||||||
|
/* Force re-reading resolv file right now, for luck. */
|
||||||
|
poll_resolv(0, 1, now);
|
||||||
|
break;
|
||||||
|
|
||||||
case EVENT_TERM:
|
case EVENT_TERM:
|
||||||
/* Knock all our children on the head. */
|
/* Knock all our children on the head. */
|
||||||
for (i = 0; i < MAX_PROCS; i++)
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
@@ -1213,7 +1314,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
do {
|
do {
|
||||||
helper_write();
|
helper_write();
|
||||||
} while (!helper_buf_empty() || do_script_run(now));
|
} while (!helper_buf_empty() || do_script_run(now));
|
||||||
close(daemon->helperfd);
|
while (retry_send(close(daemon->helperfd)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1229,7 +1330,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void poll_resolv(int force, int do_reload, time_t now)
|
static void poll_resolv(int force, int do_reload, time_t now)
|
||||||
{
|
{
|
||||||
struct resolvc *res, *latest;
|
struct resolvc *res, *latest;
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
@@ -1312,6 +1413,9 @@ void clear_cache_and_reload(time_t now)
|
|||||||
if (option_bool(OPT_ETHERS))
|
if (option_bool(OPT_ETHERS))
|
||||||
dhcp_read_ethers();
|
dhcp_read_ethers();
|
||||||
reread_dhcp();
|
reread_dhcp();
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
|
||||||
|
#endif
|
||||||
dhcp_update_configs(daemon->dhcp_conf);
|
dhcp_update_configs(daemon->dhcp_conf);
|
||||||
lease_update_from_configs();
|
lease_update_from_configs();
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
@@ -1326,7 +1430,7 @@ void clear_cache_and_reload(time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
static int set_dns_listeners(time_t now)
|
||||||
{
|
{
|
||||||
struct serverfd *serverfdp;
|
struct serverfd *serverfdp;
|
||||||
struct listener *listener;
|
struct listener *listener;
|
||||||
@@ -1338,8 +1442,7 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
|||||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||||
{
|
{
|
||||||
tftp++;
|
tftp++;
|
||||||
FD_SET(transfer->sockfd, set);
|
poll_listen(transfer->sockfd, POLLIN);
|
||||||
bump_maxfd(transfer->sockfd, maxfdp);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1348,45 +1451,32 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
|||||||
get_new_frec(now, &wait, 0);
|
get_new_frec(now, &wait, 0);
|
||||||
|
|
||||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||||
{
|
poll_listen(serverfdp->fd, POLLIN);
|
||||||
FD_SET(serverfdp->fd, set);
|
|
||||||
bump_maxfd(serverfdp->fd, maxfdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (daemon->port != 0 && !daemon->osport)
|
if (daemon->port != 0 && !daemon->osport)
|
||||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||||
if (daemon->randomsocks[i].refcount != 0)
|
if (daemon->randomsocks[i].refcount != 0)
|
||||||
{
|
poll_listen(daemon->randomsocks[i].fd, POLLIN);
|
||||||
FD_SET(daemon->randomsocks[i].fd, set);
|
|
||||||
bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||||
{
|
{
|
||||||
/* only listen for queries if we have resources */
|
/* only listen for queries if we have resources */
|
||||||
if (listener->fd != -1 && wait == 0)
|
if (listener->fd != -1 && wait == 0)
|
||||||
{
|
poll_listen(listener->fd, POLLIN);
|
||||||
FD_SET(listener->fd, set);
|
|
||||||
bump_maxfd(listener->fd, maxfdp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* death of a child goes through the select loop, so
|
/* death of a child goes through the select loop, so
|
||||||
we don't need to explicitly arrange to wake up here */
|
we don't need to explicitly arrange to wake up here */
|
||||||
if (listener->tcpfd != -1)
|
if (listener->tcpfd != -1)
|
||||||
for (i = 0; i < MAX_PROCS; i++)
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
if (daemon->tcp_pids[i] == 0)
|
if (daemon->tcp_pids[i] == 0)
|
||||||
{
|
{
|
||||||
FD_SET(listener->tcpfd, set);
|
poll_listen(listener->tcpfd, POLLIN);
|
||||||
bump_maxfd(listener->tcpfd, maxfdp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||||
{
|
poll_listen(listener->tftpfd, POLLIN);
|
||||||
FD_SET(listener->tftpfd, set);
|
|
||||||
bump_maxfd(listener->tftpfd, maxfdp);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1394,33 +1484,33 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
|||||||
return wait;
|
return wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_dns_listeners(fd_set *set, time_t now)
|
static void check_dns_listeners(time_t now)
|
||||||
{
|
{
|
||||||
struct serverfd *serverfdp;
|
struct serverfd *serverfdp;
|
||||||
struct listener *listener;
|
struct listener *listener;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||||
if (FD_ISSET(serverfdp->fd, set))
|
if (poll_check(serverfdp->fd, POLLIN))
|
||||||
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
|
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
|
||||||
|
|
||||||
if (daemon->port != 0 && !daemon->osport)
|
if (daemon->port != 0 && !daemon->osport)
|
||||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||||
if (daemon->randomsocks[i].refcount != 0 &&
|
if (daemon->randomsocks[i].refcount != 0 &&
|
||||||
FD_ISSET(daemon->randomsocks[i].fd, set))
|
poll_check(daemon->randomsocks[i].fd, POLLIN))
|
||||||
reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
|
reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
|
||||||
|
|
||||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||||
{
|
{
|
||||||
if (listener->fd != -1 && FD_ISSET(listener->fd, set))
|
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||||
receive_query(listener, now);
|
receive_query(listener, now);
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
|
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||||
tftp_request(listener, now);
|
tftp_request(listener, now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
|
if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
|
||||||
{
|
{
|
||||||
int confd, client_ok = 1;
|
int confd, client_ok = 1;
|
||||||
struct irec *iface = NULL;
|
struct irec *iface = NULL;
|
||||||
@@ -1435,7 +1525,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
|
|
||||||
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
|
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
|
||||||
{
|
{
|
||||||
close(confd);
|
while (retry_send(close(confd)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1500,7 +1590,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
if (!client_ok)
|
if (!client_ok)
|
||||||
{
|
{
|
||||||
shutdown(confd, SHUT_RDWR);
|
shutdown(confd, SHUT_RDWR);
|
||||||
close(confd);
|
while (retry_send(close(confd)));
|
||||||
}
|
}
|
||||||
#ifndef NO_FORK
|
#ifndef NO_FORK
|
||||||
else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
|
else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
|
||||||
@@ -1515,7 +1605,10 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close(confd);
|
while (retry_send(close(confd)));
|
||||||
|
|
||||||
|
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
|
||||||
|
daemon->log_id += TCP_MAX_QUERIES;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
@@ -1557,7 +1650,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||||
|
|
||||||
shutdown(confd, SHUT_RDWR);
|
shutdown(confd, SHUT_RDWR);
|
||||||
close(confd);
|
while (retry_send(close(confd)));
|
||||||
|
|
||||||
if (buff)
|
if (buff)
|
||||||
free(buff);
|
free(buff);
|
||||||
@@ -1566,7 +1659,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
|||||||
if (s->tcpfd != -1)
|
if (s->tcpfd != -1)
|
||||||
{
|
{
|
||||||
shutdown(s->tcpfd, SHUT_RDWR);
|
shutdown(s->tcpfd, SHUT_RDWR);
|
||||||
close(s->tcpfd);
|
while (retry_send(close(s->tcpfd)));
|
||||||
}
|
}
|
||||||
#ifndef NO_FORK
|
#ifndef NO_FORK
|
||||||
if (!option_bool(OPT_DEBUG))
|
if (!option_bool(OPT_DEBUG))
|
||||||
@@ -1608,14 +1701,22 @@ int icmp_ping(struct in_addr addr)
|
|||||||
better not use any resources our caller has in use...)
|
better not use any resources our caller has in use...)
|
||||||
but we remain deaf to signals or further DHCP packets. */
|
but we remain deaf to signals or further DHCP packets. */
|
||||||
|
|
||||||
int fd;
|
/* There can be a problem using dnsmasq_time() to end the loop, since
|
||||||
|
it's not monotonic, and can go backwards if the system clock is
|
||||||
|
tweaked, leading to the code getting stuck in this loop and
|
||||||
|
ignoring DHCP requests. To fix this, we check to see if select returned
|
||||||
|
as a result of a timeout rather than a socket becoming available. We
|
||||||
|
only allow this to happen as many times as it takes to get to the wait time
|
||||||
|
in quarter-second chunks. This provides a fallback way to end loop. */
|
||||||
|
|
||||||
|
int fd, rc;
|
||||||
struct sockaddr_in saddr;
|
struct sockaddr_in saddr;
|
||||||
struct {
|
struct {
|
||||||
struct ip ip;
|
struct ip ip;
|
||||||
struct icmp icmp;
|
struct icmp icmp;
|
||||||
} packet;
|
} packet;
|
||||||
unsigned short id = rand16();
|
unsigned short id = rand16();
|
||||||
unsigned int i, j;
|
unsigned int i, j, timeout_count;
|
||||||
int gotreply = 0;
|
int gotreply = 0;
|
||||||
time_t start, now;
|
time_t start, now;
|
||||||
|
|
||||||
@@ -1644,57 +1745,47 @@ int icmp_ping(struct in_addr addr)
|
|||||||
j = (j & 0xffff) + (j >> 16);
|
j = (j & 0xffff) + (j >> 16);
|
||||||
packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
|
packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
|
||||||
|
|
||||||
while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
|
while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
|
||||||
(struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
|
(struct sockaddr *)&saddr, sizeof(saddr))));
|
||||||
retry_send());
|
|
||||||
|
|
||||||
for (now = start = dnsmasq_time();
|
for (now = start = dnsmasq_time(), timeout_count = 0;
|
||||||
difftime(now, start) < (float)PING_WAIT;)
|
(difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
|
||||||
fd_set rset, wset;
|
|
||||||
struct sockaddr_in faddr;
|
struct sockaddr_in faddr;
|
||||||
int maxfd = fd;
|
|
||||||
socklen_t len = sizeof(faddr);
|
socklen_t len = sizeof(faddr);
|
||||||
|
|
||||||
tv.tv_usec = 250000;
|
poll_reset();
|
||||||
tv.tv_sec = 0;
|
poll_listen(fd, POLLIN);
|
||||||
|
set_dns_listeners(now);
|
||||||
FD_ZERO(&rset);
|
set_log_writer();
|
||||||
FD_ZERO(&wset);
|
|
||||||
FD_SET(fd, &rset);
|
|
||||||
set_dns_listeners(now, &rset, &maxfd);
|
|
||||||
set_log_writer(&wset, &maxfd);
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->doing_ra)
|
if (daemon->doing_ra)
|
||||||
{
|
poll_listen(daemon->icmp6fd, POLLIN);
|
||||||
FD_SET(daemon->icmp6fd, &rset);
|
|
||||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
|
rc = do_poll(250);
|
||||||
{
|
|
||||||
FD_ZERO(&rset);
|
if (rc < 0)
|
||||||
FD_ZERO(&wset);
|
continue;
|
||||||
}
|
else if (rc == 0)
|
||||||
|
timeout_count++;
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
check_log_writer(&wset);
|
check_log_writer(0);
|
||||||
check_dns_listeners(&rset, now);
|
check_dns_listeners(now);
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||||
icmp6_packet(now);
|
icmp6_packet(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
check_tftp_listeners(&rset, now);
|
check_tftp_listeners(now);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (FD_ISSET(fd, &rset) &&
|
if (poll_check(fd, POLLIN) &&
|
||||||
recvfrom(fd, &packet, sizeof(packet), 0,
|
recvfrom(fd, &packet, sizeof(packet), 0,
|
||||||
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&
|
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&
|
||||||
saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
|
saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
|
||||||
@@ -1708,7 +1799,7 @@ int icmp_ping(struct in_addr addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
||||||
close(fd);
|
while (retry_send(close(fd)));
|
||||||
#else
|
#else
|
||||||
opt = 1;
|
opt = 1;
|
||||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
|
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
|
||||||
|
|||||||
+159
-46
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define COPYRIGHT "Copyright (c) 2000-2014 Simon Kelley"
|
#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley"
|
||||||
|
|
||||||
#ifndef NO_LARGEFILE
|
#ifndef NO_LARGEFILE
|
||||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||||
@@ -82,7 +82,7 @@ typedef unsigned long long u64;
|
|||||||
#if defined(HAVE_SOLARIS_NETWORK)
|
#if defined(HAVE_SOLARIS_NETWORK)
|
||||||
# include <sys/sockio.h>
|
# include <sys/sockio.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/select.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@@ -164,6 +164,10 @@ struct event_desc {
|
|||||||
#define EVENT_FORK_ERR 18
|
#define EVENT_FORK_ERR 18
|
||||||
#define EVENT_LUA_ERR 19
|
#define EVENT_LUA_ERR 19
|
||||||
#define EVENT_TFTP_ERR 20
|
#define EVENT_TFTP_ERR 20
|
||||||
|
#define EVENT_INIT 21
|
||||||
|
#define EVENT_NEWADDR 22
|
||||||
|
#define EVENT_NEWROUTE 23
|
||||||
|
#define EVENT_TIME_ERR 24
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -230,9 +234,14 @@ struct event_desc {
|
|||||||
#define OPT_QUIET_DHCP6 43
|
#define OPT_QUIET_DHCP6 43
|
||||||
#define OPT_QUIET_RA 44
|
#define OPT_QUIET_RA 44
|
||||||
#define OPT_DNSSEC_VALID 45
|
#define OPT_DNSSEC_VALID 45
|
||||||
#define OPT_DNSSEC_PERMISS 46
|
#define OPT_DNSSEC_TIME 46
|
||||||
#define OPT_DNSSEC_DEBUG 47
|
#define OPT_DNSSEC_DEBUG 47
|
||||||
#define OPT_LAST 48
|
#define OPT_DNSSEC_NO_SIGN 48
|
||||||
|
#define OPT_LOCAL_SERVICE 49
|
||||||
|
#define OPT_LOOP_DETECT 50
|
||||||
|
#define OPT_EXTRALOG 51
|
||||||
|
#define OPT_TFTP_NO_FAIL 52
|
||||||
|
#define OPT_LAST 53
|
||||||
|
|
||||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||||
@@ -278,10 +287,19 @@ struct naptr {
|
|||||||
struct naptr *next;
|
struct naptr *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TXT_STAT_CACHESIZE 1
|
||||||
|
#define TXT_STAT_INSERTS 2
|
||||||
|
#define TXT_STAT_EVICTIONS 3
|
||||||
|
#define TXT_STAT_MISSES 4
|
||||||
|
#define TXT_STAT_HITS 5
|
||||||
|
#define TXT_STAT_AUTH 6
|
||||||
|
#define TXT_STAT_SERVERS 7
|
||||||
|
|
||||||
struct txt_record {
|
struct txt_record {
|
||||||
char *name;
|
char *name;
|
||||||
unsigned char *txt;
|
unsigned char *txt;
|
||||||
unsigned short class, len;
|
unsigned short class, len;
|
||||||
|
int stat;
|
||||||
struct txt_record *next;
|
struct txt_record *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -295,14 +313,15 @@ struct cname {
|
|||||||
struct cname *next;
|
struct cname *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dnskey {
|
struct ds_config {
|
||||||
char *name, *key;
|
char *name, *digest;
|
||||||
int keylen, class, algo, flags;
|
int digestlen, class, algo, keytag, digest_type;
|
||||||
struct dnskey *next;
|
struct ds_config *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ADDRLIST_LITERAL 1
|
#define ADDRLIST_LITERAL 1
|
||||||
#define ADDRLIST_IPV6 2
|
#define ADDRLIST_IPV6 2
|
||||||
|
#define ADDRLIST_REVONLY 4
|
||||||
|
|
||||||
struct addrlist {
|
struct addrlist {
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
@@ -365,7 +384,7 @@ struct crec {
|
|||||||
struct crec *cache;
|
struct crec *cache;
|
||||||
struct interface_name *int_name;
|
struct interface_name *int_name;
|
||||||
} target;
|
} target;
|
||||||
int uid; /* -1 if union is interface-name */
|
unsigned int uid; /* 0 if union is interface-name */
|
||||||
} cname;
|
} cname;
|
||||||
struct {
|
struct {
|
||||||
struct blockdata *keydata;
|
struct blockdata *keydata;
|
||||||
@@ -386,7 +405,7 @@ struct crec {
|
|||||||
} addr;
|
} addr;
|
||||||
time_t ttd; /* time to die */
|
time_t ttd; /* time to die */
|
||||||
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
||||||
int uid;
|
unsigned int uid;
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
union {
|
union {
|
||||||
char sname[SMALLDNAME];
|
char sname[SMALLDNAME];
|
||||||
@@ -423,6 +442,16 @@ struct crec {
|
|||||||
#define F_DNSSEC (1u<<22)
|
#define F_DNSSEC (1u<<22)
|
||||||
#define F_KEYTAG (1u<<23)
|
#define F_KEYTAG (1u<<23)
|
||||||
#define F_SECSTAT (1u<<24)
|
#define F_SECSTAT (1u<<24)
|
||||||
|
#define F_NO_RR (1u<<25)
|
||||||
|
#define F_IPSET (1u<<26)
|
||||||
|
#define F_NSIGMATCH (1u<<27)
|
||||||
|
#define F_NOEXTRA (1u<<28)
|
||||||
|
|
||||||
|
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||||
|
#define SRC_INTERFACE 0
|
||||||
|
#define SRC_CONFIG 1
|
||||||
|
#define SRC_HOSTS 2
|
||||||
|
#define SRC_AH 3
|
||||||
|
|
||||||
|
|
||||||
/* struct sockaddr is not large enough to hold any address,
|
/* struct sockaddr is not large enough to hold any address,
|
||||||
@@ -455,6 +484,8 @@ union mysockaddr {
|
|||||||
#define SERV_COUNTED 512 /* workspace for log code */
|
#define SERV_COUNTED 512 /* workspace for log code */
|
||||||
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
||||||
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
|
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
|
||||||
|
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||||
|
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
||||||
|
|
||||||
struct serverfd {
|
struct serverfd {
|
||||||
int fd;
|
int fd;
|
||||||
@@ -473,8 +504,11 @@ struct server {
|
|||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
struct serverfd *sfd;
|
struct serverfd *sfd;
|
||||||
char *domain; /* set if this server only handles a domain. */
|
char *domain; /* set if this server only handles a domain. */
|
||||||
int flags, tcpfd;
|
int flags, tcpfd, edns_pktsz;
|
||||||
unsigned int queries, failed_queries;
|
unsigned int queries, failed_queries;
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
u32 uid;
|
||||||
|
#endif
|
||||||
struct server *next;
|
struct server *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -512,16 +546,27 @@ struct resolvc {
|
|||||||
int is_default, logged;
|
int is_default, logged;
|
||||||
time_t mtime;
|
time_t mtime;
|
||||||
char *name;
|
char *name;
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
int wd; /* inotify watch descriptor */
|
||||||
|
char *file; /* pointer to file part if path */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile */
|
/* adn-hosts parms from command-line (also dhcp-hostsfile and dhcp-optsfile and dhcp-hostsdir*/
|
||||||
#define AH_DIR 1
|
#define AH_DIR 1
|
||||||
#define AH_INACTIVE 2
|
#define AH_INACTIVE 2
|
||||||
|
#define AH_WD_DONE 4
|
||||||
|
#define AH_HOSTS 8
|
||||||
|
#define AH_DHCP_HST 16
|
||||||
|
#define AH_DHCP_OPT 32
|
||||||
struct hostsfile {
|
struct hostsfile {
|
||||||
struct hostsfile *next;
|
struct hostsfile *next;
|
||||||
int flags;
|
int flags;
|
||||||
char *fname;
|
char *fname;
|
||||||
int index; /* matches to cache entries for logging */
|
#ifdef HAVE_INOTIFY
|
||||||
|
int wd; /* inotify watch descriptor */
|
||||||
|
#endif
|
||||||
|
unsigned int index; /* matches to cache entries for logging */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -532,12 +577,24 @@ struct hostsfile {
|
|||||||
#define STAT_NEED_DS 4
|
#define STAT_NEED_DS 4
|
||||||
#define STAT_NEED_KEY 5
|
#define STAT_NEED_KEY 5
|
||||||
#define STAT_TRUNCATED 6
|
#define STAT_TRUNCATED 6
|
||||||
|
#define STAT_SECURE_WILDCARD 7
|
||||||
|
#define STAT_NO_SIG 8
|
||||||
|
#define STAT_NO_DS 9
|
||||||
|
#define STAT_NO_NS 10
|
||||||
|
#define STAT_NEED_DS_NEG 11
|
||||||
|
#define STAT_CHASE_CNAME 12
|
||||||
|
#define STAT_INSECURE_DS 13
|
||||||
|
|
||||||
#define FREC_NOREBIND 1
|
#define FREC_NOREBIND 1
|
||||||
#define FREC_CHECKING_DISABLED 2
|
#define FREC_CHECKING_DISABLED 2
|
||||||
#define FREC_HAS_SUBNET 4
|
#define FREC_HAS_SUBNET 4
|
||||||
#define FREC_DNSKEY_QUERY 8
|
#define FREC_DNSKEY_QUERY 8
|
||||||
#define FREC_DS_QUERY 16
|
#define FREC_DS_QUERY 16
|
||||||
|
#define FREC_AD_QUESTION 32
|
||||||
|
#define FREC_DO_QUESTION 64
|
||||||
|
#define FREC_ADDED_PHEADER 128
|
||||||
|
#define FREC_CHECK_NOSIGN 256
|
||||||
|
#define FREC_TEST_PKTSZ 512
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
#define HASH_SIZE 20 /* SHA-1 digest size */
|
#define HASH_SIZE 20 /* SHA-1 digest size */
|
||||||
@@ -555,13 +612,15 @@ struct frec {
|
|||||||
#endif
|
#endif
|
||||||
unsigned int iface;
|
unsigned int iface;
|
||||||
unsigned short orig_id, new_id;
|
unsigned short orig_id, new_id;
|
||||||
int fd, forwardall, flags;
|
int log_id, fd, forwardall, flags;
|
||||||
time_t time;
|
time_t time;
|
||||||
unsigned char *hash[HASH_SIZE];
|
unsigned char *hash[HASH_SIZE];
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
int class;
|
int class, work_counter;
|
||||||
struct blockdata *stash; /* Saved reply, whilst we validate */
|
struct blockdata *stash; /* Saved reply, whilst we validate */
|
||||||
size_t stash_len;
|
struct blockdata *orig_domain; /* domain of original query, whilst
|
||||||
|
we're seeing is if in unsigned domain */
|
||||||
|
size_t stash_len, name_start, name_len;
|
||||||
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
|
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
|
||||||
struct frec *blocking_query; /* Query which is blocking us. */
|
struct frec *blocking_query; /* Query which is blocking us. */
|
||||||
#endif
|
#endif
|
||||||
@@ -609,6 +668,8 @@ struct dhcp_lease {
|
|||||||
unsigned char *extradata;
|
unsigned char *extradata;
|
||||||
unsigned int extradata_len, extradata_size;
|
unsigned int extradata_len, extradata_size;
|
||||||
int last_interface;
|
int last_interface;
|
||||||
|
int new_interface; /* save possible originated interface */
|
||||||
|
int new_prefixlen; /* and its prefix length */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
int iaid;
|
int iaid;
|
||||||
@@ -793,7 +854,7 @@ struct dhcp_context {
|
|||||||
#define CONTEXT_NETMASK (1u<<1)
|
#define CONTEXT_NETMASK (1u<<1)
|
||||||
#define CONTEXT_BRDCAST (1u<<2)
|
#define CONTEXT_BRDCAST (1u<<2)
|
||||||
#define CONTEXT_PROXY (1u<<3)
|
#define CONTEXT_PROXY (1u<<3)
|
||||||
#define CONTEXT_RA_ONLY (1u<<4)
|
#define CONTEXT_RA_ROUTER (1u<<4)
|
||||||
#define CONTEXT_RA_DONE (1u<<5)
|
#define CONTEXT_RA_DONE (1u<<5)
|
||||||
#define CONTEXT_RA_NAME (1u<<6)
|
#define CONTEXT_RA_NAME (1u<<6)
|
||||||
#define CONTEXT_RA_STATELESS (1u<<7)
|
#define CONTEXT_RA_STATELESS (1u<<7)
|
||||||
@@ -807,7 +868,7 @@ struct dhcp_context {
|
|||||||
#define CONTEXT_USED (1u<<15)
|
#define CONTEXT_USED (1u<<15)
|
||||||
#define CONTEXT_OLD (1u<<16)
|
#define CONTEXT_OLD (1u<<16)
|
||||||
#define CONTEXT_V6 (1u<<17)
|
#define CONTEXT_V6 (1u<<17)
|
||||||
|
#define CONTEXT_RA_OFF_LINK (1u<<18)
|
||||||
|
|
||||||
struct ping_result {
|
struct ping_result {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@@ -844,6 +905,7 @@ struct addr_list {
|
|||||||
struct tftp_prefix {
|
struct tftp_prefix {
|
||||||
char *interface;
|
char *interface;
|
||||||
char *prefix;
|
char *prefix;
|
||||||
|
int missing;
|
||||||
struct tftp_prefix *next;
|
struct tftp_prefix *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -862,6 +924,7 @@ extern struct daemon {
|
|||||||
unsigned int options, options2;
|
unsigned int options, options2;
|
||||||
struct resolvc default_resolv, *resolv_files;
|
struct resolvc default_resolv, *resolv_files;
|
||||||
time_t last_resolv;
|
time_t last_resolv;
|
||||||
|
char *servers_file;
|
||||||
struct mx_srv_record *mxnames;
|
struct mx_srv_record *mxnames;
|
||||||
struct naptr *naptr;
|
struct naptr *naptr;
|
||||||
struct txt_record *txt, *rr;
|
struct txt_record *txt, *rr;
|
||||||
@@ -885,7 +948,7 @@ extern struct daemon {
|
|||||||
char *runfile;
|
char *runfile;
|
||||||
char *lease_change_command;
|
char *lease_change_command;
|
||||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
||||||
struct bogus_addr *bogus_addr;
|
struct bogus_addr *bogus_addr, *ignore_addr;
|
||||||
struct server *servers;
|
struct server *servers;
|
||||||
struct ipsets *ipsets;
|
struct ipsets *ipsets;
|
||||||
int log_fac; /* log facility */
|
int log_fac; /* log facility */
|
||||||
@@ -893,7 +956,7 @@ extern struct daemon {
|
|||||||
int max_logs; /* queue limit */
|
int max_logs; /* queue limit */
|
||||||
int cachesize, ftabsize;
|
int cachesize, ftabsize;
|
||||||
int port, query_port, min_port;
|
int port, query_port, min_port;
|
||||||
unsigned long local_ttl, neg_ttl, max_ttl, max_cache_ttl, auth_ttl;
|
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
|
||||||
struct hostsfile *addn_hosts;
|
struct hostsfile *addn_hosts;
|
||||||
struct dhcp_context *dhcp, *dhcp6;
|
struct dhcp_context *dhcp, *dhcp6;
|
||||||
struct ra_interface *ra_interfaces;
|
struct ra_interface *ra_interfaces;
|
||||||
@@ -911,7 +974,7 @@ extern struct daemon {
|
|||||||
int doing_ra, doing_dhcp6;
|
int doing_ra, doing_dhcp6;
|
||||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
||||||
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
||||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file;
|
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
|
||||||
int dhcp_max, tftp_max;
|
int dhcp_max, tftp_max;
|
||||||
int dhcp_server_port, dhcp_client_port;
|
int dhcp_server_port, dhcp_client_port;
|
||||||
int start_tftp_port, end_tftp_port;
|
int start_tftp_port, end_tftp_port;
|
||||||
@@ -928,7 +991,8 @@ extern struct daemon {
|
|||||||
struct prefix_class *prefix_classes;
|
struct prefix_class *prefix_classes;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
struct dnskey *dnskeys;
|
struct ds_config *ds;
|
||||||
|
char *timestamp_file;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* globally used stuff for DNS */
|
/* globally used stuff for DNS */
|
||||||
@@ -937,6 +1001,7 @@ extern struct daemon {
|
|||||||
char *namebuff; /* MAXDNAME size buffer */
|
char *namebuff; /* MAXDNAME size buffer */
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
char *keyname; /* MAXDNAME size buffer */
|
char *keyname; /* MAXDNAME size buffer */
|
||||||
|
char *workspacename; /* ditto */
|
||||||
#endif
|
#endif
|
||||||
unsigned int local_answer, queries_forwarded, auth_answer;
|
unsigned int local_answer, queries_forwarded, auth_answer;
|
||||||
struct frec *frec_list;
|
struct frec *frec_list;
|
||||||
@@ -952,9 +1017,15 @@ extern struct daemon {
|
|||||||
pid_t tcp_pids[MAX_PROCS];
|
pid_t tcp_pids[MAX_PROCS];
|
||||||
struct randfd randomsocks[RANDOM_SOCKS];
|
struct randfd randomsocks[RANDOM_SOCKS];
|
||||||
int v6pktinfo;
|
int v6pktinfo;
|
||||||
|
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
|
||||||
|
int log_id, log_display_id; /* ids of transactions for logging */
|
||||||
|
union mysockaddr *log_source_addr;
|
||||||
|
|
||||||
/* DHCP state */
|
/* DHCP state */
|
||||||
int dhcpfd, helperfd, pxefd;
|
int dhcpfd, helperfd, pxefd;
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
int inotifyfd;
|
||||||
|
#endif
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
int netlinkfd;
|
int netlinkfd;
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
@@ -983,19 +1054,20 @@ extern struct daemon {
|
|||||||
|
|
||||||
/* utility string buffer, hold max sized IP address as string */
|
/* utility string buffer, hold max sized IP address as string */
|
||||||
char *addrbuff;
|
char *addrbuff;
|
||||||
|
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
|
||||||
|
|
||||||
} *daemon;
|
} *daemon;
|
||||||
|
|
||||||
/* cache.c */
|
/* cache.c */
|
||||||
void cache_init(void);
|
void cache_init(void);
|
||||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
||||||
char *record_source(int index);
|
char *record_source(unsigned int index);
|
||||||
void querystr(char *desc, char *str, unsigned short type);
|
char *querystr(char *desc, unsigned short type);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
struct all_addr *addr, time_t now,
|
struct all_addr *addr, time_t now,
|
||||||
unsigned short prot);
|
unsigned int prot);
|
||||||
struct crec *cache_find_by_name(struct crec *crecp,
|
struct crec *cache_find_by_name(struct crec *crecp,
|
||||||
char *name, time_t now, unsigned short prot);
|
char *name, time_t now, unsigned int prot);
|
||||||
void cache_end_insert(void);
|
void cache_end_insert(void);
|
||||||
void cache_start_insert(void);
|
void cache_start_insert(void);
|
||||||
struct crec *cache_insert(char *name, struct all_addr *addr,
|
struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||||
@@ -1005,9 +1077,12 @@ void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_addre
|
|||||||
struct in_addr a_record_from_hosts(char *name, time_t now);
|
struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||||
void cache_unhash_dhcp(void);
|
void cache_unhash_dhcp(void);
|
||||||
void dump_cache(time_t now);
|
void dump_cache(time_t now);
|
||||||
|
int cache_make_stat(struct txt_record *t);
|
||||||
char *cache_get_name(struct crec *crecp);
|
char *cache_get_name(struct crec *crecp);
|
||||||
char *cache_get_cname_target(struct crec *crecp);
|
char *cache_get_cname_target(struct crec *crecp);
|
||||||
struct crec *cache_enumerate(int init);
|
struct crec *cache_enumerate(int init);
|
||||||
|
int read_hostsfile(char *filename, unsigned int index, int cache_size,
|
||||||
|
struct crec **rhash, int hashsz);
|
||||||
|
|
||||||
/* blockdata.c */
|
/* blockdata.c */
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
@@ -1031,6 +1106,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
char *name, int isExtract, int extrabytes);
|
char *name, int isExtract, int extrabytes);
|
||||||
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
|
unsigned char *skip_name(unsigned char *ansp, struct dns_header *header, size_t plen, int extrabytes);
|
||||||
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
||||||
|
unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen);
|
||||||
unsigned int extract_request(struct dns_header *header, size_t qlen,
|
unsigned int extract_request(struct dns_header *header, size_t qlen,
|
||||||
char *name, unsigned short *typep);
|
char *name, unsigned short *typep);
|
||||||
size_t setup_reply(struct dns_header *header, size_t qlen,
|
size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||||
@@ -1040,9 +1116,11 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
|
|||||||
time_t now, char **ipsets, int is_sign, int checkrebind,
|
time_t now, char **ipsets, int is_sign, int checkrebind,
|
||||||
int no_cache, int secure, int *doctored);
|
int no_cache, int secure, int *doctored);
|
||||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
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);
|
struct in_addr local_addr, struct in_addr local_netmask,
|
||||||
|
time_t now, int *ad_reqd, int *do_bit);
|
||||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||||
struct bogus_addr *addr, time_t now);
|
struct bogus_addr *addr, time_t now);
|
||||||
|
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
||||||
size_t *len, unsigned char **p, int *is_sign);
|
size_t *len, unsigned char **p, int *is_sign);
|
||||||
int check_for_local_domain(char *name, time_t now);
|
int check_for_local_domain(char *name, time_t now);
|
||||||
@@ -1072,16 +1150,20 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* dnssec.c */
|
/* dnssec.c */
|
||||||
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr);
|
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
|
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, 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);
|
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class);
|
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer, int *nons);
|
||||||
|
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
|
||||||
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
|
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
|
||||||
|
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
||||||
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||||
|
int setup_timestamp(void);
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
|
u32 rand32(void);
|
||||||
u64 rand64(void);
|
u64 rand64(void);
|
||||||
int legal_hostname(char *c);
|
int legal_hostname(char *c);
|
||||||
char *canonicalise(char *s, int *nomem);
|
char *canonicalise(char *s, int *nomem);
|
||||||
@@ -1093,36 +1175,34 @@ int sa_len(union mysockaddr *addr);
|
|||||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||||
int hostname_isequal(const char *a, const char *b);
|
int hostname_isequal(const char *a, const char *b);
|
||||||
time_t dnsmasq_time(void);
|
time_t dnsmasq_time(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(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
|
int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
|
||||||
u64 addr6part(struct in6_addr *addr);
|
u64 addr6part(struct in6_addr *addr);
|
||||||
void setaddr6part(struct in6_addr *addr, u64 host);
|
void setaddr6part(struct in6_addr *addr, u64 host);
|
||||||
#endif
|
#endif
|
||||||
int retry_send(void);
|
int retry_send(ssize_t rc);
|
||||||
void prettyprint_time(char *buf, unsigned int t);
|
void prettyprint_time(char *buf, unsigned int t);
|
||||||
int prettyprint_addr(union mysockaddr *addr, char *buf);
|
int prettyprint_addr(union mysockaddr *addr, char *buf);
|
||||||
int parse_hex(char *in, unsigned char *out, int maxlen,
|
int parse_hex(char *in, unsigned char *out, int maxlen,
|
||||||
unsigned int *wildcard_mask, int *mac_type);
|
unsigned int *wildcard_mask, int *mac_type);
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
int parse_base64(char *in, char *out);
|
|
||||||
#endif
|
|
||||||
int memcmp_masked(unsigned char *a, unsigned char *b, int len,
|
int memcmp_masked(unsigned char *a, unsigned char *b, int len,
|
||||||
unsigned int mask);
|
unsigned int mask);
|
||||||
int expand_buf(struct iovec *iov, size_t size);
|
int expand_buf(struct iovec *iov, size_t size);
|
||||||
char *print_mac(char *buff, unsigned char *mac, int len);
|
char *print_mac(char *buff, unsigned char *mac, int len);
|
||||||
void bump_maxfd(int fd, int *max);
|
|
||||||
int read_write(int fd, unsigned char *packet, int size, int rw);
|
int read_write(int fd, unsigned char *packet, int size, int rw);
|
||||||
|
|
||||||
int wildcard_match(const char* wildcard, const char* match);
|
int wildcard_match(const char* wildcard, const char* match);
|
||||||
|
int wildcard_matchn(const char* wildcard, const char* match, int num);
|
||||||
|
|
||||||
/* log.c */
|
/* log.c */
|
||||||
void die(char *message, char *arg1, int exit_code);
|
void die(char *message, char *arg1, int exit_code);
|
||||||
int log_start(struct passwd *ent_pw, int errfd);
|
int log_start(struct passwd *ent_pw, int errfd);
|
||||||
int log_reopen(char *log_file);
|
int log_reopen(char *log_file);
|
||||||
void my_syslog(int priority, const char *format, ...);
|
void my_syslog(int priority, const char *format, ...);
|
||||||
void set_log_writer(fd_set *set, int *maxfdp);
|
void set_log_writer(void);
|
||||||
void check_log_writer(fd_set *set);
|
void check_log_writer(int force);
|
||||||
void flush_log(void);
|
void flush_log(void);
|
||||||
|
|
||||||
/* option.c */
|
/* option.c */
|
||||||
@@ -1130,11 +1210,13 @@ void read_opts (int argc, char **argv, char *compile_opts);
|
|||||||
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
||||||
int opt_len, char *buf, int buf_len);
|
int opt_len, char *buf, int buf_len);
|
||||||
void reread_dhcp(void);
|
void reread_dhcp(void);
|
||||||
|
void read_servers_file(void);
|
||||||
void set_option_bool(unsigned int opt);
|
void set_option_bool(unsigned int opt);
|
||||||
void reset_option_bool(unsigned int opt);
|
void reset_option_bool(unsigned int opt);
|
||||||
struct hostsfile *expand_filelist(struct hostsfile *list);
|
struct hostsfile *expand_filelist(struct hostsfile *list);
|
||||||
char *parse_server(char *arg, union mysockaddr *addr,
|
char *parse_server(char *arg, union mysockaddr *addr,
|
||||||
union mysockaddr *source_addr, char *interface, int *flags);
|
union mysockaddr *source_addr, char *interface, int *flags);
|
||||||
|
int option_read_dynfile(char *file, int flags);
|
||||||
|
|
||||||
/* forward.c */
|
/* forward.c */
|
||||||
void reply_query(int fd, int family, time_t now);
|
void reply_query(int fd, int family, time_t now);
|
||||||
@@ -1146,6 +1228,9 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
|
|||||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||||
union mysockaddr *to, struct all_addr *source,
|
union mysockaddr *to, struct all_addr *source,
|
||||||
unsigned int iface);
|
unsigned int iface);
|
||||||
|
void resend_query();
|
||||||
|
struct randfd *allocate_rfd(int family);
|
||||||
|
void free_rfd(struct randfd *rfd);
|
||||||
|
|
||||||
/* network.c */
|
/* network.c */
|
||||||
int indextoname(int fd, int index, char *name);
|
int indextoname(int fd, int index, char *name);
|
||||||
@@ -1153,6 +1238,13 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
|
|||||||
int random_sock(int family);
|
int random_sock(int family);
|
||||||
void pre_allocate_sfds(void);
|
void pre_allocate_sfds(void);
|
||||||
int reload_servers(char *fname);
|
int reload_servers(char *fname);
|
||||||
|
void mark_servers(int flag);
|
||||||
|
void cleanup_servers(void);
|
||||||
|
void add_update_server(int flags,
|
||||||
|
union mysockaddr *addr,
|
||||||
|
union mysockaddr *source_addr,
|
||||||
|
const char *interface,
|
||||||
|
const char *domain);
|
||||||
void check_servers(void);
|
void check_servers(void);
|
||||||
int enumerate_interfaces(int reset);
|
int enumerate_interfaces(int reset);
|
||||||
void create_wildcard_listeners(void);
|
void create_wildcard_listeners(void);
|
||||||
@@ -1213,9 +1305,10 @@ void lease_update_slaac(time_t now);
|
|||||||
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
|
void lease_set_iaid(struct dhcp_lease *lease, int iaid);
|
||||||
void lease_make_duid(time_t now);
|
void lease_make_duid(time_t now);
|
||||||
#endif
|
#endif
|
||||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
|
||||||
unsigned char *clid, int hw_len, int hw_type, int clid_len, time_t now, int force);
|
const unsigned char *clid, int hw_len, int hw_type,
|
||||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain);
|
int clid_len, time_t now, int force);
|
||||||
|
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain);
|
||||||
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
|
void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now);
|
||||||
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now);
|
void lease_set_interface(struct dhcp_lease *lease, int interface, time_t now);
|
||||||
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
|
struct dhcp_lease *lease_find_by_client(unsigned char *hwaddr, int hw_len, int hw_type,
|
||||||
@@ -1246,15 +1339,15 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
|||||||
int make_icmp_sock(void);
|
int make_icmp_sock(void);
|
||||||
int icmp_ping(struct in_addr addr);
|
int icmp_ping(struct in_addr addr);
|
||||||
#endif
|
#endif
|
||||||
|
void queue_event(int event);
|
||||||
void send_alarm(time_t event, time_t now);
|
void send_alarm(time_t event, time_t now);
|
||||||
void send_event(int fd, int event, int data, char *msg);
|
void send_event(int fd, int event, int data, char *msg);
|
||||||
void clear_cache_and_reload(time_t now);
|
void clear_cache_and_reload(time_t now);
|
||||||
void poll_resolv(int force, int do_reload, time_t now);
|
|
||||||
|
|
||||||
/* netlink.c */
|
/* netlink.c */
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void netlink_init(void);
|
void netlink_init(void);
|
||||||
void netlink_multicast(time_t now);
|
void netlink_multicast(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c */
|
/* bpf.c */
|
||||||
@@ -1263,7 +1356,7 @@ void init_bpf(void);
|
|||||||
void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
void send_via_bpf(struct dhcp_packet *mess, size_t len,
|
||||||
struct in_addr iface_addr, struct ifreq *ifr);
|
struct in_addr iface_addr, struct ifreq *ifr);
|
||||||
void route_init(void);
|
void route_init(void);
|
||||||
void route_sock(time_t now);
|
void route_sock(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* bpf.c or netlink.c */
|
/* bpf.c or netlink.c */
|
||||||
@@ -1272,8 +1365,8 @@ int iface_enumerate(int family, void *parm, int (callback)());
|
|||||||
/* dbus.c */
|
/* dbus.c */
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
char *dbus_init(void);
|
char *dbus_init(void);
|
||||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
|
void check_dbus_listeners(void);
|
||||||
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
|
void set_dbus_listeners(void);
|
||||||
# ifdef HAVE_DHCP
|
# ifdef HAVE_DHCP
|
||||||
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
||||||
# endif
|
# endif
|
||||||
@@ -1300,7 +1393,7 @@ int helper_buf_empty(void);
|
|||||||
/* tftp.c */
|
/* tftp.c */
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
void tftp_request(struct listener *listen, time_t now);
|
void tftp_request(struct listener *listen, time_t now);
|
||||||
void check_tftp_listeners(fd_set *rset, time_t now);
|
void check_tftp_listeners(time_t now);
|
||||||
int do_tftp_script_run(void);
|
int do_tftp_script_run(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1404,3 +1497,23 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force);
|
|||||||
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
time_t periodic_slaac(time_t now, struct dhcp_lease *leases);
|
||||||
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface, struct dhcp_lease *leases);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* loop.c */
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
void loop_send_probes();
|
||||||
|
int detect_loop(char *query, int type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* inotify.c */
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
void inotify_dnsmasq_init();
|
||||||
|
int inotify_check(time_t now);
|
||||||
|
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* poll.c */
|
||||||
|
void poll_reset(void);
|
||||||
|
int poll_check(int fd, short event);
|
||||||
|
void poll_listen(int fd, short event);
|
||||||
|
int do_poll(int timeout);
|
||||||
|
|
||||||
+1356
-307
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+884
-271
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+288
@@ -0,0 +1,288 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2015 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"
|
||||||
|
#ifdef HAVE_INOTIFY
|
||||||
|
|
||||||
|
#include <sys/inotify.h>
|
||||||
|
#include <sys/param.h> /* For MAXSYMLINKS */
|
||||||
|
|
||||||
|
/* the strategy is to set a inotify on the directories containing
|
||||||
|
resolv files, for any files in the directory which are close-write
|
||||||
|
or moved into the directory.
|
||||||
|
|
||||||
|
When either of those happen, we look to see if the file involved
|
||||||
|
is actually a resolv-file, and if so, call poll-resolv with
|
||||||
|
the "force" argument, to ensure it's read.
|
||||||
|
|
||||||
|
This adds one new error condition: the directories containing
|
||||||
|
all specified resolv-files must exist at start-up, even if the actual
|
||||||
|
files don't.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static char *inotify_buffer;
|
||||||
|
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
|
||||||
|
|
||||||
|
/* If path is a symbolic link, return the path it
|
||||||
|
points to, made absolute if relative.
|
||||||
|
If path doesn't exist or is not a symlink, return NULL.
|
||||||
|
Return value is malloc'ed */
|
||||||
|
static char *my_readlink(char *path)
|
||||||
|
{
|
||||||
|
ssize_t rc, size = 64;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
buf = safe_malloc(size);
|
||||||
|
rc = readlink(path, buf, (size_t)size);
|
||||||
|
|
||||||
|
if (rc == -1)
|
||||||
|
{
|
||||||
|
/* Not link or doesn't exist. */
|
||||||
|
if (errno == EINVAL || errno == ENOENT)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
die(_("cannot access path %s: %s"), path, EC_MISC);
|
||||||
|
}
|
||||||
|
else if (rc < size-1)
|
||||||
|
{
|
||||||
|
char *d;
|
||||||
|
|
||||||
|
buf[rc] = 0;
|
||||||
|
if (buf[0] != '/' && ((d = strrchr(path, '/'))))
|
||||||
|
{
|
||||||
|
/* Add path to relative link */
|
||||||
|
char *new_buf = safe_malloc((d - path) + strlen(buf) + 2);
|
||||||
|
*(d+1) = 0;
|
||||||
|
strcpy(new_buf, path);
|
||||||
|
strcat(new_buf, buf);
|
||||||
|
free(buf);
|
||||||
|
buf = new_buf;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buffer too small, increase and retry */
|
||||||
|
size += 64;
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void inotify_dnsmasq_init()
|
||||||
|
{
|
||||||
|
struct resolvc *res;
|
||||||
|
inotify_buffer = safe_malloc(INOTIFY_SZ);
|
||||||
|
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
|
||||||
|
|
||||||
|
if (daemon->inotifyfd == -1)
|
||||||
|
die(_("failed to create inotify: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
for (res = daemon->resolv_files; res; res = res->next)
|
||||||
|
{
|
||||||
|
char *d, *new_path, *path = safe_malloc(strlen(res->name) + 1);
|
||||||
|
int links = MAXSYMLINKS;
|
||||||
|
|
||||||
|
strcpy(path, res->name);
|
||||||
|
|
||||||
|
/* Follow symlinks until we reach a non-symlink, or a non-existant file. */
|
||||||
|
while ((new_path = my_readlink(path)))
|
||||||
|
{
|
||||||
|
if (links-- == 0)
|
||||||
|
die(_("too many symlinks following %s"), res->name, EC_MISC);
|
||||||
|
free(path);
|
||||||
|
path = new_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->wd = -1;
|
||||||
|
|
||||||
|
if ((d = strrchr(path, '/')))
|
||||||
|
{
|
||||||
|
*d = 0; /* make path just directory */
|
||||||
|
res->wd = inotify_add_watch(daemon->inotifyfd, path, IN_CLOSE_WRITE | IN_MOVED_TO);
|
||||||
|
|
||||||
|
res->file = d+1; /* pointer to filename */
|
||||||
|
*d = '/';
|
||||||
|
|
||||||
|
if (res->wd == -1 && errno == ENOENT)
|
||||||
|
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res->wd == -1)
|
||||||
|
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
DIR *dir_stream = NULL;
|
||||||
|
struct dirent *ent;
|
||||||
|
struct stat buf;
|
||||||
|
|
||||||
|
if (!(ah->flags & flag))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
||||||
|
ah->fname, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(ah->flags & AH_WD_DONE))
|
||||||
|
{
|
||||||
|
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
|
||||||
|
ah->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)))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("failed to create inotify for %s: %s"),
|
||||||
|
ah->fname, strerror(errno));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((ent = readdir(dir_stream)))
|
||||||
|
{
|
||||||
|
size_t lendir = strlen(ah->fname);
|
||||||
|
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);
|
||||||
|
strcat(path, "/");
|
||||||
|
strcat(path, ent->d_name);
|
||||||
|
|
||||||
|
/* ignore non-regular files */
|
||||||
|
if (stat(path, &buf) != -1 && S_ISREG(buf.st_mode))
|
||||||
|
{
|
||||||
|
if (ah->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);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int inotify_check(time_t now)
|
||||||
|
{
|
||||||
|
int hit = 0;
|
||||||
|
struct hostsfile *ah;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
char *p;
|
||||||
|
struct resolvc *res;
|
||||||
|
struct inotify_event *in;
|
||||||
|
|
||||||
|
while ((rc = read(daemon->inotifyfd, inotify_buffer, INOTIFY_SZ)) == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
if (rc <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
|
||||||
|
{
|
||||||
|
in = (struct inotify_event*)p;
|
||||||
|
|
||||||
|
for (res = daemon->resolv_files; res; res = res->next)
|
||||||
|
if (res->wd == in->wd && in->len != 0 && strcmp(res->file, in->name) == 0)
|
||||||
|
hit = 1;
|
||||||
|
|
||||||
|
/* ignore emacs backups and dotfiles */
|
||||||
|
if (in->len == 0 ||
|
||||||
|
in->name[in->len - 1] == '~' ||
|
||||||
|
(in->name[0] == '#' && in->name[in->len - 1] == '#') ||
|
||||||
|
in->name[0] == '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||||
|
if (ah->wd == in->wd)
|
||||||
|
{
|
||||||
|
size_t lendir = strlen(ah->fname);
|
||||||
|
char *path;
|
||||||
|
|
||||||
|
if ((path = whine_malloc(lendir + in->len + 2)))
|
||||||
|
{
|
||||||
|
strcpy(path, ah->fname);
|
||||||
|
strcat(path, "/");
|
||||||
|
strcat(path, in->name);
|
||||||
|
|
||||||
|
my_syslog(LOG_INFO, _("inotify, new or changed file %s"), path);
|
||||||
|
|
||||||
|
if (ah->flags & AH_HOSTS)
|
||||||
|
{
|
||||||
|
read_hostsfile(path, ah->index, 0, NULL, 0);
|
||||||
|
#ifdef HAVE_DHCP
|
||||||
|
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
{
|
||||||
|
/* Propogate 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)
|
||||||
|
{
|
||||||
|
if (option_read_dynfile(path, AH_DHCP_HST))
|
||||||
|
{
|
||||||
|
/* Propogate 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ah->flags & AH_DHCP_OPT)
|
||||||
|
option_read_dynfile(path, AH_DHCP_OPT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
free(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* INOTIFY */
|
||||||
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+5
-5
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#if defined(HAVE_IPSET) && defined(HAVE_LINUX_NETWORK)
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
struct my_nlattr *nested[2];
|
struct my_nlattr *nested[2];
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
int addrsz = INADDRSZ;
|
int addrsz = INADDRSZ;
|
||||||
ssize_t rc;
|
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (af == AF_INET6)
|
if (af == AF_INET6)
|
||||||
@@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
|
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[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
|
||||||
|
|
||||||
while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
|
while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
|
||||||
(struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
|
(struct sockaddr *)&snl, sizeof(snl))));
|
||||||
return rc;
|
|
||||||
|
return errno == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+34
-14
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -352,16 +352,21 @@ static int find_interface_v4(struct in_addr local, int if_index, char *label,
|
|||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
int prefix = netmask_length(netmask);
|
||||||
|
|
||||||
(void) label;
|
(void) label;
|
||||||
(void) broadcast;
|
(void) broadcast;
|
||||||
(void) vparam;
|
(void) vparam;
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if (!(lease->flags & (LEASE_TA | LEASE_NA)))
|
if (!(lease->flags & (LEASE_TA | LEASE_NA)) &&
|
||||||
if (is_same_net(local, lease->addr, netmask))
|
is_same_net(local, lease->addr, netmask) &&
|
||||||
lease_set_interface(lease, if_index, *((time_t *)vparam));
|
prefix > lease->new_prefixlen)
|
||||||
|
{
|
||||||
|
lease->new_interface = if_index;
|
||||||
|
lease->new_prefixlen = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,17 +376,23 @@ static int find_interface_v6(struct in6_addr *local, int prefix,
|
|||||||
int preferred, int valid, void *vparam)
|
int preferred, int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
(void)preferred;
|
(void)preferred;
|
||||||
(void)valid;
|
(void)valid;
|
||||||
|
(void)vparam;
|
||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
if ((lease->flags & (LEASE_TA | LEASE_NA)))
|
||||||
if (is_same_net6(local, &lease->addr6, prefix))
|
if (is_same_net6(local, &lease->addr6, prefix) && prefix > lease->new_prefixlen) {
|
||||||
lease_set_interface(lease, if_index, *((time_t *)vparam));
|
/* save prefix length for comparison, as we might get shorter matching
|
||||||
|
* prefix in upcoming netlink GETADDR responses
|
||||||
|
* */
|
||||||
|
lease->new_interface = if_index;
|
||||||
|
lease->new_prefixlen = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,10 +425,19 @@ void lease_update_slaac(time_t now)
|
|||||||
start-time. */
|
start-time. */
|
||||||
void lease_find_interfaces(time_t now)
|
void lease_find_interfaces(time_t now)
|
||||||
{
|
{
|
||||||
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
|
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, find_interface_v4);
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
iface_enumerate(AF_INET6, &now, find_interface_v6);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for (lease = leases; lease; lease = lease->next)
|
||||||
|
if (lease->new_interface != 0)
|
||||||
|
lease_set_interface(lease, lease->new_interface, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
@@ -793,9 +813,9 @@ void lease_set_iaid(struct dhcp_lease *lease, int iaid)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void lease_set_hwaddr(struct dhcp_lease *lease, unsigned char *hwaddr,
|
void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
|
||||||
unsigned char *clid, int hw_len, int hw_type, int clid_len,
|
const unsigned char *clid, int hw_len, int hw_type,
|
||||||
time_t now, int force)
|
int clid_len, time_t now, int force)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
int change = force;
|
int change = force;
|
||||||
@@ -877,7 +897,7 @@ static void kill_name(struct dhcp_lease *lease)
|
|||||||
lease->hostname = lease->fqdn = NULL;
|
lease->hostname = lease->fqdn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void lease_set_hostname(struct dhcp_lease *lease, char *name, int auth, char *domain, char *config_domain)
|
void lease_set_hostname(struct dhcp_lease *lease, const char *name, int auth, char *domain, char *config_domain)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease_tmp;
|
struct dhcp_lease *lease_tmp;
|
||||||
char *new_name = NULL, *new_fqdn = NULL;
|
char *new_name = NULL, *new_fqdn = NULL;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -421,18 +421,15 @@ void my_syslog(int priority, const char *format, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_log_writer(fd_set *set, int *maxfdp)
|
void set_log_writer(void)
|
||||||
{
|
{
|
||||||
if (entries && log_fd != -1 && connection_good)
|
if (entries && log_fd != -1 && connection_good)
|
||||||
{
|
poll_listen(log_fd, POLLOUT);
|
||||||
FD_SET(log_fd, set);
|
|
||||||
bump_maxfd(log_fd, maxfdp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_log_writer(fd_set *set)
|
void check_log_writer(int force)
|
||||||
{
|
{
|
||||||
if (log_fd != -1 && (!set || FD_ISSET(log_fd, set)))
|
if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
|
||||||
log_write();
|
log_write();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2015 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"
|
||||||
|
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
static ssize_t loop_make_probe(u32 uid);
|
||||||
|
|
||||||
|
void loop_send_probes()
|
||||||
|
{
|
||||||
|
struct server *serv;
|
||||||
|
|
||||||
|
if (!option_bool(OPT_LOOP_DETECT))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Loop through all upstream servers not for particular domains, and send a query to that server which is
|
||||||
|
identifiable, via the uid. If we see that query back again, then the server is looping, and we should not use it. */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (!(serv->flags &
|
||||||
|
(SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_LOOP)))
|
||||||
|
{
|
||||||
|
ssize_t len = loop_make_probe(serv->uid);
|
||||||
|
int fd;
|
||||||
|
struct randfd *rfd = NULL;
|
||||||
|
|
||||||
|
if (serv->sfd)
|
||||||
|
fd = serv->sfd->fd;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(rfd = allocate_rfd(serv->addr.sa.sa_family)))
|
||||||
|
continue;
|
||||||
|
fd = rfd->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (retry_send(sendto(fd, daemon->packet, len, 0,
|
||||||
|
&serv->addr.sa, sa_len(&serv->addr))));
|
||||||
|
|
||||||
|
free_rfd(rfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t loop_make_probe(u32 uid)
|
||||||
|
{
|
||||||
|
struct dns_header *header = (struct dns_header *)daemon->packet;
|
||||||
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
|
|
||||||
|
/* packet buffer overwritten */
|
||||||
|
daemon->srv_save = NULL;
|
||||||
|
|
||||||
|
header->id = rand16();
|
||||||
|
header->ancount = header->nscount = header->arcount = htons(0);
|
||||||
|
header->qdcount = htons(1);
|
||||||
|
header->hb3 = HB3_RD;
|
||||||
|
header->hb4 = 0;
|
||||||
|
SET_OPCODE(header, QUERY);
|
||||||
|
|
||||||
|
*p++ = 8;
|
||||||
|
sprintf((char *)p, "%.8x", uid);
|
||||||
|
p += 8;
|
||||||
|
*p++ = strlen(LOOP_TEST_DOMAIN);
|
||||||
|
strcpy((char *)p, LOOP_TEST_DOMAIN); /* Add terminating zero */
|
||||||
|
p += strlen(LOOP_TEST_DOMAIN) + 1;
|
||||||
|
|
||||||
|
PUTSHORT(LOOP_TEST_TYPE, p);
|
||||||
|
PUTSHORT(C_IN, p);
|
||||||
|
|
||||||
|
return p - (unsigned char *)header;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int detect_loop(char *query, int type)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 uid;
|
||||||
|
struct server *serv;
|
||||||
|
|
||||||
|
if (!option_bool(OPT_LOOP_DETECT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (type != LOOP_TEST_TYPE ||
|
||||||
|
strlen(LOOP_TEST_DOMAIN) + 9 != strlen(query) ||
|
||||||
|
strstr(query, LOOP_TEST_DOMAIN) != query + 9)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
if (!isxdigit(query[i]))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uid = strtol(query, NULL, 16);
|
||||||
|
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (!(serv->flags &
|
||||||
|
(SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND | SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_LOOP)) &&
|
||||||
|
uid == serv->uid)
|
||||||
|
{
|
||||||
|
serv->flags |= SERV_LOOP;
|
||||||
|
check_servers(); /* log new state */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+17
-53
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
static struct iovec iov;
|
static struct iovec iov;
|
||||||
static u32 netlink_pid;
|
static u32 netlink_pid;
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h);
|
static void nl_async(struct nlmsghdr *h);
|
||||||
|
|
||||||
void netlink_init(void)
|
void netlink_init(void)
|
||||||
{
|
{
|
||||||
@@ -142,7 +142,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
static unsigned int seq = 0;
|
static unsigned int seq = 0;
|
||||||
int callback_ok = 1, newaddr = 0;
|
int callback_ok = 1;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct nlmsghdr nlh;
|
struct nlmsghdr nlh;
|
||||||
@@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
req.g.rtgen_family = family;
|
req.g.rtgen_family = family;
|
||||||
|
|
||||||
/* Don't block in recvfrom if send fails */
|
/* Don't block in recvfrom if send fails */
|
||||||
while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
|
while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
|
(struct sockaddr *)&addr, sizeof(addr))));
|
||||||
|
|
||||||
if (len == -1)
|
if (errno != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@@ -191,21 +191,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
/* May be multicast arriving async */
|
/* May be multicast arriving async */
|
||||||
if (nl_async(h))
|
nl_async(h);
|
||||||
{
|
|
||||||
newaddr = 1;
|
|
||||||
enumerate_interfaces(1); /* reset */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == NLMSG_DONE)
|
else if (h->nlmsg_type == NLMSG_DONE)
|
||||||
{
|
return callback_ok;
|
||||||
/* handle async new interface address arrivals, these have to be done
|
|
||||||
after we complete as we're not re-entrant */
|
|
||||||
if (newaddr)
|
|
||||||
newaddress(dnsmasq_time());
|
|
||||||
|
|
||||||
return callback_ok;
|
|
||||||
}
|
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||||
{
|
{
|
||||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||||
@@ -219,7 +208,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct in_addr netmask, addr, broadcast;
|
struct in_addr netmask, addr, broadcast;
|
||||||
char *label = NULL;
|
char *label = NULL;
|
||||||
|
|
||||||
netmask.s_addr = htonl(0xffffffff << (32 - ifa->ifa_prefixlen));
|
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - ifa->ifa_prefixlen));
|
||||||
|
|
||||||
addr.s_addr = 0;
|
addr.s_addr = 0;
|
||||||
broadcast.s_addr = 0;
|
broadcast.s_addr = 0;
|
||||||
|
|
||||||
@@ -330,11 +320,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void netlink_multicast(time_t now)
|
void netlink_multicast(void)
|
||||||
{
|
{
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
int flags, newaddr = 0;
|
int flags;
|
||||||
|
|
||||||
/* don't risk blocking reading netlink messages here. */
|
/* don't risk blocking reading netlink messages here. */
|
||||||
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
if ((flags = fcntl(daemon->netlinkfd, F_GETFL)) == -1 ||
|
||||||
@@ -343,24 +333,19 @@ void netlink_multicast(time_t now)
|
|||||||
|
|
||||||
if ((len = netlink_recv()) != -1)
|
if ((len = netlink_recv()) != -1)
|
||||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||||
if (nl_async(h))
|
nl_async(h);
|
||||||
newaddr = 1;
|
|
||||||
|
|
||||||
/* restore non-blocking status */
|
/* restore non-blocking status */
|
||||||
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
fcntl(daemon->netlinkfd, F_SETFL, flags);
|
||||||
|
|
||||||
if (newaddr)
|
|
||||||
newaddress(now);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nl_async(struct nlmsghdr *h)
|
static void nl_async(struct nlmsghdr *h)
|
||||||
{
|
{
|
||||||
if (h->nlmsg_type == NLMSG_ERROR)
|
if (h->nlmsg_type == NLMSG_ERROR)
|
||||||
{
|
{
|
||||||
struct nlmsgerr *err = NLMSG_DATA(h);
|
struct nlmsgerr *err = NLMSG_DATA(h);
|
||||||
if (err->error != 0)
|
if (err->error != 0)
|
||||||
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
my_syslog(LOG_ERR, _("netlink returns error: %s"), strerror(-(err->error)));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
else if (h->nlmsg_pid == 0 && h->nlmsg_type == RTM_NEWROUTE)
|
||||||
{
|
{
|
||||||
@@ -372,31 +357,10 @@ static int nl_async(struct nlmsghdr *h)
|
|||||||
struct rtmsg *rtm = NLMSG_DATA(h);
|
struct rtmsg *rtm = NLMSG_DATA(h);
|
||||||
|
|
||||||
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
|
if (rtm->rtm_type == RTN_UNICAST && rtm->rtm_scope == RT_SCOPE_LINK)
|
||||||
{
|
queue_event(EVENT_NEWROUTE);
|
||||||
/* Force re-reading resolv file right now, for luck. */
|
|
||||||
daemon->last_resolv = 0;
|
|
||||||
|
|
||||||
if (daemon->srv_save)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if (daemon->srv_save->sfd)
|
|
||||||
fd = daemon->srv_save->sfd->fd;
|
|
||||||
else if (daemon->rfd_save && daemon->rfd_save->refcount != 0)
|
|
||||||
fd = daemon->rfd_save->fd;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
while(sendto(fd, daemon->packet, daemon->packet_len, 0,
|
|
||||||
&daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
return 1; /* clever bind mode - rescan */
|
queue_event(EVENT_NEWADDR);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+210
-103
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,10 +16,6 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifndef IN6_IS_ADDR_ULA
|
|
||||||
#define IN6_IS_ADDR_ULA(a) ((((__const uint32_t *) (a))[0] & htonl (0xfe00000)) == htonl (0xfc000000))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
|
||||||
int indextoname(int fd, int index, char *name)
|
int indextoname(int fd, int index, char *name)
|
||||||
@@ -240,7 +236,7 @@ struct iface_param {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||||
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int dad)
|
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
int mtu = 0, loopback;
|
int mtu = 0, loopback;
|
||||||
@@ -268,7 +264,40 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
|
|
||||||
if (!label)
|
if (!label)
|
||||||
label = ifr.ifr_name;
|
label = ifr.ifr_name;
|
||||||
|
|
||||||
|
/* maintain a list of all addresses on all interfaces for --local-service option */
|
||||||
|
if (option_bool(OPT_LOCAL_SERVICE))
|
||||||
|
{
|
||||||
|
struct addrlist *al;
|
||||||
|
|
||||||
|
if (param->spare)
|
||||||
|
{
|
||||||
|
al = param->spare;
|
||||||
|
param->spare = al->next;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
al = whine_malloc(sizeof(struct addrlist));
|
||||||
|
|
||||||
|
if (al)
|
||||||
|
{
|
||||||
|
al->next = daemon->interface_addrs;
|
||||||
|
daemon->interface_addrs = al;
|
||||||
|
al->prefixlen = prefixlen;
|
||||||
|
|
||||||
|
if (addr->sa.sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
al->addr.addr.addr4 = addr->in.sin_addr;
|
||||||
|
al->flags = 0;
|
||||||
|
}
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
else
|
||||||
|
{
|
||||||
|
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
||||||
|
al->flags = ADDRLIST_IPV6;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
|
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_addr))
|
||||||
@@ -359,6 +388,10 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
{
|
{
|
||||||
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
||||||
al->flags = ADDRLIST_IPV6;
|
al->flags = ADDRLIST_IPV6;
|
||||||
|
/* Privacy addresses and addresses still undergoing DAD and deprecated addresses
|
||||||
|
don't appear in forward queries, but will in reverse ones. */
|
||||||
|
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
|
||||||
|
al->flags |= ADDRLIST_REVONLY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -370,7 +403,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (sockaddr_isequal(&iface->addr, addr))
|
if (sockaddr_isequal(&iface->addr, addr))
|
||||||
{
|
{
|
||||||
iface->dad = dad;
|
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
||||||
iface->found = 1; /* for garbage collection */
|
iface->found = 1; /* for garbage collection */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -445,7 +478,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
iface->dhcp_ok = dhcp_ok;
|
iface->dhcp_ok = dhcp_ok;
|
||||||
iface->dns_auth = auth_dns;
|
iface->dns_auth = auth_dns;
|
||||||
iface->mtu = mtu;
|
iface->mtu = mtu;
|
||||||
iface->dad = dad;
|
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
||||||
iface->found = 1;
|
iface->found = 1;
|
||||||
iface->done = iface->multicast_done = iface->warned = 0;
|
iface->done = iface->multicast_done = iface->warned = 0;
|
||||||
iface->index = if_index;
|
iface->index = if_index;
|
||||||
@@ -490,7 +523,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
else
|
else
|
||||||
addr.in6.sin6_scope_id = 0;
|
addr.in6.sin6_scope_id = 0;
|
||||||
|
|
||||||
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, !!(flags & IFACE_TENTATIVE));
|
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -518,7 +551,7 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
|||||||
int enumerate_interfaces(int reset)
|
int enumerate_interfaces(int reset)
|
||||||
{
|
{
|
||||||
static struct addrlist *spare = NULL;
|
static struct addrlist *spare = NULL;
|
||||||
static int done = 0, active = 0;
|
static int done = 0;
|
||||||
struct iface_param param;
|
struct iface_param param;
|
||||||
int errsave, ret = 1;
|
int errsave, ret = 1;
|
||||||
struct addrlist *addr, *tmp;
|
struct addrlist *addr, *tmp;
|
||||||
@@ -537,14 +570,11 @@ int enumerate_interfaces(int reset)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (done || active)
|
if (done)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
done = 1;
|
done = 1;
|
||||||
|
|
||||||
/* protect against recusive calls from iface_enumerate(); */
|
|
||||||
active = 1;
|
|
||||||
|
|
||||||
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
if ((param.fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -565,6 +595,15 @@ int enumerate_interfaces(int reset)
|
|||||||
intname->addr = NULL;
|
intname->addr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove list of addresses of local interfaces */
|
||||||
|
for (addr = daemon->interface_addrs; addr; addr = tmp)
|
||||||
|
{
|
||||||
|
tmp = addr->next;
|
||||||
|
addr->next = spare;
|
||||||
|
spare = addr;
|
||||||
|
}
|
||||||
|
daemon->interface_addrs = NULL;
|
||||||
|
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
/* remove addresses stored against auth_zone subnets, but not
|
/* remove addresses stored against auth_zone subnets, but not
|
||||||
ones configured as address literals */
|
ones configured as address literals */
|
||||||
@@ -635,10 +674,8 @@ int enumerate_interfaces(int reset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
errno = errsave;
|
errno = errsave;
|
||||||
|
|
||||||
spare = param.spare;
|
spare = param.spare;
|
||||||
active = 0;
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1254,87 +1291,206 @@ void pre_allocate_sfds(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mark_servers(int flag)
|
||||||
|
{
|
||||||
|
struct server *serv;
|
||||||
|
|
||||||
|
/* mark everything with argument flag */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
{
|
||||||
|
if (serv->flags & flag)
|
||||||
|
serv->flags |= SERV_MARK;
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
/* Give looped servers another chance */
|
||||||
|
serv->flags &= ~SERV_LOOP;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
tmp = serv->next;
|
||||||
|
if (serv->flags & SERV_MARK)
|
||||||
|
{
|
||||||
|
server_gone(serv);
|
||||||
|
*up = serv->next;
|
||||||
|
if (serv->domain)
|
||||||
|
free(serv->domain);
|
||||||
|
free(serv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &serv->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
/* Now we have a new set of servers, test for loops. */
|
||||||
|
loop_send_probes();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_update_server(int flags,
|
||||||
|
union mysockaddr *addr,
|
||||||
|
union mysockaddr *source_addr,
|
||||||
|
const char *interface,
|
||||||
|
const char *domain)
|
||||||
|
{
|
||||||
|
struct server *serv, *next = NULL;
|
||||||
|
char *domain_str = NULL;
|
||||||
|
|
||||||
|
/* See if there is a suitable candidate, and unmark */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (serv->flags & SERV_MARK)
|
||||||
|
{
|
||||||
|
if (domain)
|
||||||
|
{
|
||||||
|
if (!(serv->flags & SERV_HAS_DOMAIN) || !hostname_isequal(domain, serv->domain))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serv)
|
||||||
|
{
|
||||||
|
domain_str = serv->domain;
|
||||||
|
next = serv->next;
|
||||||
|
}
|
||||||
|
else if ((serv = whine_malloc(sizeof (struct server))))
|
||||||
|
{
|
||||||
|
/* Not found, create a new one. */
|
||||||
|
if (domain && !(domain_str = whine_malloc(strlen(domain)+1)))
|
||||||
|
{
|
||||||
|
free(serv);
|
||||||
|
serv = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct server *s;
|
||||||
|
/* Add to the end of the chain, for order */
|
||||||
|
if (!daemon->servers)
|
||||||
|
daemon->servers = serv;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (s = daemon->servers; s->next; s = s->next);
|
||||||
|
s->next = serv;
|
||||||
|
}
|
||||||
|
if (domain)
|
||||||
|
strcpy(domain_str, domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (serv)
|
||||||
|
{
|
||||||
|
memset(serv, 0, sizeof(struct server));
|
||||||
|
serv->flags = flags;
|
||||||
|
serv->domain = domain_str;
|
||||||
|
serv->next = next;
|
||||||
|
serv->queries = serv->failed_queries = 0;
|
||||||
|
serv->edns_pktsz = daemon->edns_pktsz;
|
||||||
|
#ifdef HAVE_LOOP
|
||||||
|
serv->uid = rand32();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (domain)
|
||||||
|
serv->flags |= SERV_HAS_DOMAIN;
|
||||||
|
|
||||||
|
if (interface)
|
||||||
|
strcpy(serv->interface, interface);
|
||||||
|
if (addr)
|
||||||
|
serv->addr = *addr;
|
||||||
|
if (source_addr)
|
||||||
|
serv->source_addr = *source_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void check_servers(void)
|
void check_servers(void)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
struct server *new, *tmp, *ret = NULL;
|
struct server *serv;
|
||||||
int port = 0;
|
int port = 0;
|
||||||
|
|
||||||
/* interface may be new since startup */
|
/* interface may be new since startup */
|
||||||
if (!option_bool(OPT_NOWILD))
|
if (!option_bool(OPT_NOWILD))
|
||||||
enumerate_interfaces(0);
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
for (new = daemon->servers; new; new = tmp)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
{
|
{
|
||||||
tmp = new->next;
|
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||||
|
|
||||||
if (!(new->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
|
||||||
{
|
{
|
||||||
port = prettyprint_addr(&new->addr, daemon->namebuff);
|
port = prettyprint_addr(&serv->addr, daemon->namebuff);
|
||||||
|
|
||||||
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
|
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
|
||||||
if (new->addr.sa.sa_family == AF_INET &&
|
if (serv->addr.sa.sa_family == AF_INET &&
|
||||||
new->addr.in.sin_addr.s_addr == 0)
|
serv->addr.in.sin_addr.s_addr == 0)
|
||||||
{
|
{
|
||||||
free(new);
|
serv->flags |= SERV_MARK;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (sockaddr_isequal(&new->addr, &iface->addr))
|
if (sockaddr_isequal(&serv->addr, &iface->addr))
|
||||||
break;
|
break;
|
||||||
if (iface)
|
if (iface)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
|
my_syslog(LOG_WARNING, _("ignoring nameserver %s - local interface"), daemon->namebuff);
|
||||||
free(new);
|
serv->flags |= SERV_MARK;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do we need a socket set? */
|
/* Do we need a socket set? */
|
||||||
if (!new->sfd &&
|
if (!serv->sfd &&
|
||||||
!(new->sfd = allocate_sfd(&new->source_addr, new->interface)) &&
|
!(serv->sfd = allocate_sfd(&serv->source_addr, serv->interface)) &&
|
||||||
errno != 0)
|
errno != 0)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_WARNING,
|
my_syslog(LOG_WARNING,
|
||||||
_("ignoring nameserver %s - cannot make/bind socket: %s"),
|
_("ignoring nameserver %s - cannot make/bind socket: %s"),
|
||||||
daemon->namebuff, strerror(errno));
|
daemon->namebuff, strerror(errno));
|
||||||
free(new);
|
serv->flags |= SERV_MARK;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reverse order - gets it right. */
|
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
|
||||||
new->next = ret;
|
|
||||||
ret = new;
|
|
||||||
|
|
||||||
if (!(new->flags & SERV_NO_REBIND))
|
|
||||||
{
|
{
|
||||||
if (new->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
|
if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
|
||||||
{
|
{
|
||||||
char *s1, *s2;
|
char *s1, *s2;
|
||||||
if (!(new->flags & SERV_HAS_DOMAIN))
|
if (!(serv->flags & SERV_HAS_DOMAIN))
|
||||||
s1 = _("unqualified"), s2 = _("names");
|
s1 = _("unqualified"), s2 = _("names");
|
||||||
else if (strlen(new->domain) == 0)
|
else if (strlen(serv->domain) == 0)
|
||||||
s1 = _("default"), s2 = "";
|
s1 = _("default"), s2 = "";
|
||||||
else
|
else
|
||||||
s1 = _("domain"), s2 = new->domain;
|
s1 = _("domain"), s2 = serv->domain;
|
||||||
|
|
||||||
if (new->flags & SERV_NO_ADDR)
|
if (serv->flags & SERV_NO_ADDR)
|
||||||
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
|
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
|
||||||
else if (new->flags & SERV_USE_RESOLV)
|
else if (serv->flags & SERV_USE_RESOLV)
|
||||||
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
|
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
|
||||||
else if (!(new->flags & SERV_LITERAL_ADDRESS))
|
else
|
||||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
|
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
|
||||||
}
|
}
|
||||||
else if (new->interface[0] != 0)
|
#ifdef HAVE_LOOP
|
||||||
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, new->interface);
|
else if (serv->flags & SERV_LOOP)
|
||||||
|
my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detected"), daemon->namebuff, port);
|
||||||
|
#endif
|
||||||
|
else if (serv->interface[0] != 0)
|
||||||
|
my_syslog(LOG_INFO, _("using nameserver %s#%d(via %s)"), daemon->namebuff, port, serv->interface);
|
||||||
else
|
else
|
||||||
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
|
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
daemon->servers = ret;
|
cleanup_servers();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return zero if no servers found, in that case we keep polling.
|
/* Return zero if no servers found, in that case we keep polling.
|
||||||
@@ -1343,9 +1499,6 @@ int reload_servers(char *fname)
|
|||||||
{
|
{
|
||||||
FILE *f;
|
FILE *f;
|
||||||
char *line;
|
char *line;
|
||||||
struct server *old_servers = NULL;
|
|
||||||
struct server *new_servers = NULL;
|
|
||||||
struct server *serv;
|
|
||||||
int gotone = 0;
|
int gotone = 0;
|
||||||
|
|
||||||
/* buff happens to be MAXDNAME long... */
|
/* buff happens to be MAXDNAME long... */
|
||||||
@@ -1354,28 +1507,9 @@ int reload_servers(char *fname)
|
|||||||
my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
|
my_syslog(LOG_ERR, _("failed to read %s: %s"), fname, strerror(errno));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* move old servers to free list - we can reuse the memory
|
mark_servers(SERV_FROM_RESOLV);
|
||||||
and not risk malloc if there are the same or fewer new servers.
|
|
||||||
Servers which were specced on the command line go to the new list. */
|
|
||||||
for (serv = daemon->servers; serv;)
|
|
||||||
{
|
|
||||||
struct server *tmp = serv->next;
|
|
||||||
if (serv->flags & SERV_FROM_RESOLV)
|
|
||||||
{
|
|
||||||
serv->next = old_servers;
|
|
||||||
old_servers = serv;
|
|
||||||
/* forward table rules reference servers, so have to blow them away */
|
|
||||||
server_gone(serv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serv->next = new_servers;
|
|
||||||
new_servers = serv;
|
|
||||||
}
|
|
||||||
serv = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
|
while ((line = fgets(daemon->namebuff, MAXDNAME, f)))
|
||||||
{
|
{
|
||||||
union mysockaddr addr, source_addr;
|
union mysockaddr addr, source_addr;
|
||||||
@@ -1434,49 +1568,23 @@ int reload_servers(char *fname)
|
|||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (old_servers)
|
add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
|
||||||
{
|
|
||||||
serv = old_servers;
|
|
||||||
old_servers = old_servers->next;
|
|
||||||
}
|
|
||||||
else if (!(serv = whine_malloc(sizeof (struct server))))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* this list is reverse ordered:
|
|
||||||
it gets reversed again in check_servers */
|
|
||||||
serv->next = new_servers;
|
|
||||||
new_servers = serv;
|
|
||||||
serv->addr = addr;
|
|
||||||
serv->source_addr = source_addr;
|
|
||||||
serv->domain = NULL;
|
|
||||||
serv->interface[0] = 0;
|
|
||||||
serv->sfd = NULL;
|
|
||||||
serv->flags = SERV_FROM_RESOLV;
|
|
||||||
serv->queries = serv->failed_queries = 0;
|
|
||||||
gotone = 1;
|
gotone = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free any memory not used. */
|
|
||||||
while (old_servers)
|
|
||||||
{
|
|
||||||
struct server *tmp = old_servers->next;
|
|
||||||
free(old_servers);
|
|
||||||
old_servers = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
daemon->servers = new_servers;
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
cleanup_servers();
|
||||||
|
|
||||||
return gotone;
|
return gotone;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_BSD_NETWORK)
|
|
||||||
/* Called when addresses are added or deleted from an interface */
|
/* Called when addresses are added or deleted from an interface */
|
||||||
void newaddress(time_t now)
|
void newaddress(time_t now)
|
||||||
{
|
{
|
||||||
(void)now;
|
(void)now;
|
||||||
|
|
||||||
if (option_bool(OPT_CLEVERBIND) || daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
|
if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
|
||||||
|
daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
|
||||||
enumerate_interfaces(0);
|
enumerate_interfaces(0);
|
||||||
|
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
@@ -1494,7 +1602,6 @@ void newaddress(time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+450
-180
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+124
@@ -0,0 +1,124 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2015 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"
|
||||||
|
|
||||||
|
/* Wrapper for poll(). Allocates and extends array of struct pollfds,
|
||||||
|
keeps them in fd order so that we can set and test conditions on
|
||||||
|
fd using a simple but efficient binary chop. */
|
||||||
|
|
||||||
|
/* poll_reset()
|
||||||
|
poll_listen(fd, event)
|
||||||
|
.
|
||||||
|
.
|
||||||
|
poll_listen(fd, event);
|
||||||
|
|
||||||
|
hits = do_poll(timeout);
|
||||||
|
|
||||||
|
if (poll_check(fd, event)
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
if (poll_check(fd, event)
|
||||||
|
.
|
||||||
|
.
|
||||||
|
|
||||||
|
event is OR of POLLIN, POLLOUT, POLLERR, etc
|
||||||
|
*/
|
||||||
|
|
||||||
|
static struct pollfd *pollfds = NULL;
|
||||||
|
static nfds_t nfds, arrsize = 0;
|
||||||
|
|
||||||
|
/* Binary search. Returns either the pollfd with fd, or
|
||||||
|
if the fd doesn't match, or return equals nfds, the entry
|
||||||
|
to the left of which a new record should be inserted. */
|
||||||
|
static nfds_t fd_search(int fd)
|
||||||
|
{
|
||||||
|
nfds_t left, right, mid;
|
||||||
|
|
||||||
|
if ((right = nfds) == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
left = 0;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (right == left + 1)
|
||||||
|
return (pollfds[left].fd >= fd) ? left : right;
|
||||||
|
|
||||||
|
mid = (left + right)/2;
|
||||||
|
|
||||||
|
if (pollfds[mid].fd > fd)
|
||||||
|
right = mid;
|
||||||
|
else
|
||||||
|
left = mid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poll_reset(void)
|
||||||
|
{
|
||||||
|
nfds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_poll(int timeout)
|
||||||
|
{
|
||||||
|
return poll(pollfds, nfds, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int poll_check(int fd, short event)
|
||||||
|
{
|
||||||
|
nfds_t i = fd_search(fd);
|
||||||
|
|
||||||
|
if (i < nfds && pollfds[i].fd == fd)
|
||||||
|
return pollfds[i].revents & event;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poll_listen(int fd, short event)
|
||||||
|
{
|
||||||
|
nfds_t i = fd_search(fd);
|
||||||
|
|
||||||
|
if (i < nfds && pollfds[i].fd == fd)
|
||||||
|
pollfds[i].events |= event;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (arrsize != nfds)
|
||||||
|
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Array too small, extend. */
|
||||||
|
struct pollfd *new;
|
||||||
|
arrsize += 64;
|
||||||
|
|
||||||
|
if (!(new = whine_malloc(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
pollfds[i].fd = fd;
|
||||||
|
pollfds[i].events = event;
|
||||||
|
nfds++;
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -49,6 +49,8 @@ struct prefix_opt {
|
|||||||
#define ICMP6_OPT_SOURCE_MAC 1
|
#define ICMP6_OPT_SOURCE_MAC 1
|
||||||
#define ICMP6_OPT_PREFIX 3
|
#define ICMP6_OPT_PREFIX 3
|
||||||
#define ICMP6_OPT_MTU 5
|
#define ICMP6_OPT_MTU 5
|
||||||
|
#define ICMP6_OPT_ADV_INTERVAL 7
|
||||||
|
#define ICMP6_OPT_RT_INFO 24
|
||||||
#define ICMP6_OPT_RDNSS 25
|
#define ICMP6_OPT_RDNSS 25
|
||||||
#define ICMP6_OPT_DNSSL 31
|
#define ICMP6_OPT_DNSSL 31
|
||||||
|
|
||||||
|
|||||||
+185
-35
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,11 +28,11 @@
|
|||||||
|
|
||||||
struct ra_param {
|
struct ra_param {
|
||||||
time_t now;
|
time_t now;
|
||||||
int ind, managed, other, found_context, first;
|
int ind, managed, other, found_context, first, adv_router;
|
||||||
char *if_name;
|
char *if_name;
|
||||||
struct dhcp_netid *tags;
|
struct dhcp_netid *tags;
|
||||||
struct in6_addr link_local, link_global, ula;
|
struct in6_addr link_local, link_global, ula;
|
||||||
unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval;
|
unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval, prio;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct search_param {
|
struct search_param {
|
||||||
@@ -40,7 +40,18 @@ struct search_param {
|
|||||||
char name[IF_NAMESIZE+1];
|
char name[IF_NAMESIZE+1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct alias_param {
|
||||||
|
int iface;
|
||||||
|
struct dhcp_bridge *bridge;
|
||||||
|
int num_alias_ifs;
|
||||||
|
int max_alias_ifs;
|
||||||
|
int *alias_ifs;
|
||||||
|
};
|
||||||
|
|
||||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
|
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest);
|
||||||
|
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest,
|
||||||
|
int send_iface);
|
||||||
|
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int flags,
|
int scope, int if_index, int flags,
|
||||||
unsigned int preferred, unsigned int valid, void *vparam);
|
unsigned int preferred, unsigned int valid, void *vparam);
|
||||||
@@ -181,6 +192,7 @@ void icmp6_packet(time_t now)
|
|||||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||||
{
|
{
|
||||||
char *mac = "";
|
char *mac = "";
|
||||||
|
struct dhcp_bridge *bridge, *alias;
|
||||||
|
|
||||||
/* look for link-layer address option for logging */
|
/* look for link-layer address option for logging */
|
||||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||||
@@ -191,12 +203,37 @@ void icmp6_packet(time_t now)
|
|||||||
|
|
||||||
if (!option_bool(OPT_QUIET_RA))
|
if (!option_bool(OPT_QUIET_RA))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||||
/* source address may not be valid in solicit request. */
|
|
||||||
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
/* If the incoming interface is an alias of some other one (as
|
||||||
|
specified by the --bridge-interface option), send an RA using
|
||||||
|
the context of the aliased interface. */
|
||||||
|
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||||
|
{
|
||||||
|
int bridge_index = if_nametoindex(bridge->iface);
|
||||||
|
if (bridge_index)
|
||||||
|
{
|
||||||
|
for (alias = bridge->alias; alias; alias = alias->next)
|
||||||
|
if (wildcard_matchn(alias->iface, interface, IF_NAMESIZE))
|
||||||
|
{
|
||||||
|
/* Send an RA on if_index with information from
|
||||||
|
bridge_index. */
|
||||||
|
send_ra_alias(now, bridge_index, bridge->iface, NULL, if_index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (alias)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the incoming interface wasn't an alias, send an RA using
|
||||||
|
the context of the incoming interface. */
|
||||||
|
if (!bridge)
|
||||||
|
/* source address may not be valid in solicit request. */
|
||||||
|
send_ra(now, if_index, interface, !IN6_IS_ADDR_UNSPECIFIED(&from.sin6_addr) ? &from.sin6_addr : NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_addr *dest, int send_iface)
|
||||||
{
|
{
|
||||||
struct ra_packet *ra;
|
struct ra_packet *ra;
|
||||||
struct ra_param parm;
|
struct ra_param parm;
|
||||||
@@ -210,28 +247,30 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
FILE *f;
|
FILE *f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
parm.ind = iface;
|
||||||
|
parm.managed = 0;
|
||||||
|
parm.other = 0;
|
||||||
|
parm.found_context = 0;
|
||||||
|
parm.adv_router = 0;
|
||||||
|
parm.if_name = iface_name;
|
||||||
|
parm.first = 1;
|
||||||
|
parm.now = now;
|
||||||
|
parm.glob_pref_time = parm.link_pref_time = parm.ula_pref_time = 0;
|
||||||
|
parm.adv_interval = calc_interval(ra_param);
|
||||||
|
parm.prio = calc_prio(ra_param);
|
||||||
|
|
||||||
save_counter(0);
|
save_counter(0);
|
||||||
ra = expand(sizeof(struct ra_packet));
|
ra = expand(sizeof(struct ra_packet));
|
||||||
|
|
||||||
ra->type = ND_ROUTER_ADVERT;
|
ra->type = ND_ROUTER_ADVERT;
|
||||||
ra->code = 0;
|
ra->code = 0;
|
||||||
ra->hop_limit = hop_limit;
|
ra->hop_limit = hop_limit;
|
||||||
ra->flags = calc_prio(ra_param);
|
ra->flags = parm.prio;
|
||||||
ra->lifetime = htons(calc_lifetime(ra_param));
|
ra->lifetime = htons(calc_lifetime(ra_param));
|
||||||
ra->reachable_time = 0;
|
ra->reachable_time = 0;
|
||||||
ra->retrans_time = 0;
|
ra->retrans_time = 0;
|
||||||
|
|
||||||
parm.ind = iface;
|
|
||||||
parm.managed = 0;
|
|
||||||
parm.other = 0;
|
|
||||||
parm.found_context = 0;
|
|
||||||
parm.if_name = iface_name;
|
|
||||||
parm.first = 1;
|
|
||||||
parm.now = now;
|
|
||||||
parm.glob_pref_time = parm.link_pref_time = parm.ula_pref_time = 0;
|
|
||||||
parm.adv_interval = calc_interval(ra_param);
|
|
||||||
|
|
||||||
/* set tag with name == interface */
|
/* set tag with name == interface */
|
||||||
iface_id.net = iface_name;
|
iface_id.net = iface_name;
|
||||||
iface_id.next = NULL;
|
iface_id.next = NULL;
|
||||||
@@ -286,8 +325,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
|
setaddr6part(&local, addr6part(&local) & ~((context->prefix == 64) ? (u64)-1LL : (1LLU << (128 - context->prefix)) - 1LLU));
|
||||||
|
|
||||||
|
|
||||||
if ((context->flags &
|
if (context->flags & CONTEXT_RA)
|
||||||
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
|
||||||
{
|
{
|
||||||
do_slaac = 1;
|
do_slaac = 1;
|
||||||
if (context->flags & CONTEXT_DHCP)
|
if (context->flags & CONTEXT_DHCP)
|
||||||
@@ -312,8 +350,10 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
opt->type = ICMP6_OPT_PREFIX;
|
opt->type = ICMP6_OPT_PREFIX;
|
||||||
opt->len = 4;
|
opt->len = 4;
|
||||||
opt->prefix_len = context->prefix;
|
opt->prefix_len = context->prefix;
|
||||||
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
/* autonomous only if we're not doing dhcp, set
|
||||||
opt->flags = do_slaac ? 0xC0 : 0x80;
|
"on-link" unless "off-link" was specified */
|
||||||
|
opt->flags = (do_slaac ? 0x40 : 0) |
|
||||||
|
((context->flags & CONTEXT_RA_OFF_LINK) ? 0 : 0x80);
|
||||||
opt->valid_lifetime = htonl(context->saved_valid - old);
|
opt->valid_lifetime = htonl(context->saved_valid - old);
|
||||||
opt->preferred_lifetime = htonl(0);
|
opt->preferred_lifetime = htonl(0);
|
||||||
opt->reserved = 0;
|
opt->reserved = 0;
|
||||||
@@ -339,6 +379,17 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
if (!old_prefix && !parm.found_context)
|
if (!old_prefix && !parm.found_context)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* If we're sending router address instead of prefix in at least on prefix,
|
||||||
|
include the advertisement interval option. */
|
||||||
|
if (parm.adv_router)
|
||||||
|
{
|
||||||
|
put_opt6_char(ICMP6_OPT_ADV_INTERVAL);
|
||||||
|
put_opt6_char(1);
|
||||||
|
put_opt6_short(0);
|
||||||
|
/* interval value is in milliseconds */
|
||||||
|
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
|
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
|
||||||
available from SIOCGIFMTU */
|
available from SIOCGIFMTU */
|
||||||
@@ -356,7 +407,7 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
iface_enumerate(AF_LOCAL, &iface, add_lla);
|
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
|
||||||
|
|
||||||
/* RDNSS, RFC 6106, use relevant DHCP6 options */
|
/* 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);
|
||||||
@@ -464,14 +515,22 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
|
inet_pton(AF_INET6, ALL_NODES, &addr.sin6_addr);
|
||||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
|
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
|
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
|
||||||
(struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
|
save_counter(0), 0, (struct sockaddr *)&addr,
|
||||||
|
sizeof(addr))));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *dest)
|
||||||
|
{
|
||||||
|
/* Send an RA on the same interface that the RA content is based
|
||||||
|
on. */
|
||||||
|
send_ra_alias(now, iface, iface_name, dest, iface);
|
||||||
|
}
|
||||||
|
|
||||||
static int add_prefixes(struct in6_addr *local, int prefix,
|
static int add_prefixes(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int flags,
|
int scope, int if_index, int flags,
|
||||||
unsigned int preferred, unsigned int valid, void *vparam)
|
unsigned int preferred, unsigned int valid, void *vparam)
|
||||||
@@ -500,6 +559,8 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
int do_slaac = 0;
|
int do_slaac = 0;
|
||||||
int deprecate = 0;
|
int deprecate = 0;
|
||||||
int constructed = 0;
|
int constructed = 0;
|
||||||
|
int adv_router = 0;
|
||||||
|
int off_link = 0;
|
||||||
unsigned int time = 0xffffffff;
|
unsigned int time = 0xffffffff;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
@@ -511,8 +572,7 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
{
|
{
|
||||||
context->saved_valid = valid;
|
context->saved_valid = valid;
|
||||||
|
|
||||||
if ((context->flags &
|
if (context->flags & CONTEXT_RA)
|
||||||
(CONTEXT_RA_ONLY | CONTEXT_RA_NAME | CONTEXT_RA_STATELESS)))
|
|
||||||
{
|
{
|
||||||
do_slaac = 1;
|
do_slaac = 1;
|
||||||
if (context->flags & CONTEXT_DHCP)
|
if (context->flags & CONTEXT_DHCP)
|
||||||
@@ -530,7 +590,17 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
param->managed = 1;
|
param->managed = 1;
|
||||||
param->other = 1;
|
param->other = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Configured to advertise router address, not prefix. See RFC 3775 7.2
|
||||||
|
In this case we do all addresses associated with a context,
|
||||||
|
hence the real_prefix setting here. */
|
||||||
|
if (context->flags & CONTEXT_RA_ROUTER)
|
||||||
|
{
|
||||||
|
adv_router = 1;
|
||||||
|
param->adv_router = 1;
|
||||||
|
real_prefix = context->prefix;
|
||||||
|
}
|
||||||
|
|
||||||
/* find floor time, don't reduce below 3 * RA interval. */
|
/* find floor time, don't reduce below 3 * RA interval. */
|
||||||
if (time > context->lease_time)
|
if (time > context->lease_time)
|
||||||
{
|
{
|
||||||
@@ -556,13 +626,14 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
/* subsequent prefixes on the same interface
|
/* subsequent prefixes on the same interface
|
||||||
and subsequent instances of this prefix don't need timers.
|
and subsequent instances of this prefix don't need timers.
|
||||||
Be careful not to find the same prefix twice with different
|
Be careful not to find the same prefix twice with different
|
||||||
addresses. */
|
addresses unless we're advertising the actual addresses. */
|
||||||
if (!(context->flags & CONTEXT_RA_DONE))
|
if (!(context->flags & CONTEXT_RA_DONE))
|
||||||
{
|
{
|
||||||
if (!param->first)
|
if (!param->first)
|
||||||
context->ra_time = 0;
|
context->ra_time = 0;
|
||||||
context->flags |= CONTEXT_RA_DONE;
|
context->flags |= CONTEXT_RA_DONE;
|
||||||
real_prefix = context->prefix;
|
real_prefix = context->prefix;
|
||||||
|
off_link = (context->flags & CONTEXT_RA_OFF_LINK);
|
||||||
}
|
}
|
||||||
|
|
||||||
param->first = 0;
|
param->first = 0;
|
||||||
@@ -607,13 +678,19 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
if ((opt = expand(sizeof(struct prefix_opt))))
|
if ((opt = expand(sizeof(struct prefix_opt))))
|
||||||
{
|
{
|
||||||
/* zero net part of address */
|
/* zero net part of address */
|
||||||
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
|
if (!adv_router)
|
||||||
|
setaddr6part(local, addr6part(local) & ~((real_prefix == 64) ? (u64)-1LL : (1LLU << (128 - real_prefix)) - 1LLU));
|
||||||
|
|
||||||
opt->type = ICMP6_OPT_PREFIX;
|
opt->type = ICMP6_OPT_PREFIX;
|
||||||
opt->len = 4;
|
opt->len = 4;
|
||||||
opt->prefix_len = real_prefix;
|
opt->prefix_len = real_prefix;
|
||||||
/* autonomous only if we're not doing dhcp, always set "on-link" */
|
/* autonomous only if we're not doing dhcp, set
|
||||||
opt->flags = do_slaac ? 0xC0 : 0x80;
|
"on-link" unless "off-link" was specified */
|
||||||
|
opt->flags = (off_link ? 0 : 0x80);
|
||||||
|
if (do_slaac)
|
||||||
|
opt->flags |= 0x40;
|
||||||
|
if (adv_router)
|
||||||
|
opt->flags |= 0x20;
|
||||||
opt->valid_lifetime = htonl(valid);
|
opt->valid_lifetime = htonl(valid);
|
||||||
opt->preferred_lifetime = htonl(preferred);
|
opt->preferred_lifetime = htonl(preferred);
|
||||||
opt->reserved = 0;
|
opt->reserved = 0;
|
||||||
@@ -655,6 +732,7 @@ time_t periodic_ra(time_t now)
|
|||||||
struct search_param param;
|
struct search_param param;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
time_t next_event;
|
time_t next_event;
|
||||||
|
struct alias_param aparam;
|
||||||
|
|
||||||
param.now = now;
|
param.now = now;
|
||||||
param.iface = 0;
|
param.iface = 0;
|
||||||
@@ -702,12 +780,84 @@ time_t periodic_ra(time_t now)
|
|||||||
if (tmp->name && wildcard_match(tmp->name, param.name))
|
if (tmp->name && wildcard_match(tmp->name, param.name))
|
||||||
break;
|
break;
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
send_ra(now, param.iface, param.name, NULL);
|
{
|
||||||
|
send_ra(now, param.iface, param.name, NULL);
|
||||||
|
|
||||||
|
/* Also send on all interfaces that are aliases of this
|
||||||
|
one. */
|
||||||
|
for (aparam.bridge = daemon->bridges;
|
||||||
|
aparam.bridge;
|
||||||
|
aparam.bridge = aparam.bridge->next)
|
||||||
|
if ((int)if_nametoindex(aparam.bridge->iface) == param.iface)
|
||||||
|
{
|
||||||
|
/* Count the number of alias interfaces for this
|
||||||
|
'bridge', by calling iface_enumerate with
|
||||||
|
send_ra_to_aliases and NULL alias_ifs. */
|
||||||
|
aparam.iface = param.iface;
|
||||||
|
aparam.alias_ifs = NULL;
|
||||||
|
aparam.num_alias_ifs = 0;
|
||||||
|
iface_enumerate(AF_LOCAL, &aparam, 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);
|
||||||
|
|
||||||
|
/* Allocate memory to store the alias interface
|
||||||
|
indices. */
|
||||||
|
aparam.alias_ifs = (int *)whine_malloc(aparam.num_alias_ifs *
|
||||||
|
sizeof(int));
|
||||||
|
if (aparam.alias_ifs)
|
||||||
|
{
|
||||||
|
/* Use iface_enumerate again to get the alias
|
||||||
|
interface indices, then send on each of
|
||||||
|
those. */
|
||||||
|
aparam.max_alias_ifs = aparam.num_alias_ifs;
|
||||||
|
aparam.num_alias_ifs = 0;
|
||||||
|
iface_enumerate(AF_LOCAL, &aparam, 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",
|
||||||
|
param.name, daemon->addrbuff,
|
||||||
|
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
|
||||||
|
send_ra_alias(now,
|
||||||
|
param.iface,
|
||||||
|
param.name,
|
||||||
|
NULL,
|
||||||
|
aparam.alias_ifs[aparam.num_alias_ifs - 1]);
|
||||||
|
}
|
||||||
|
free(aparam.alias_ifs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The source interface can only appear in at most
|
||||||
|
one --bridge-interface. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return next_event;
|
return next_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int send_ra_to_aliases(int index, unsigned int type, char *mac, size_t maclen, void *parm)
|
||||||
|
{
|
||||||
|
struct alias_param *aparam = (struct alias_param *)parm;
|
||||||
|
char ifrn_name[IFNAMSIZ];
|
||||||
|
struct dhcp_bridge *alias;
|
||||||
|
|
||||||
|
(void)type;
|
||||||
|
(void)mac;
|
||||||
|
(void)maclen;
|
||||||
|
|
||||||
|
if (if_indextoname(index, ifrn_name))
|
||||||
|
for (alias = aparam->bridge->alias; alias; alias = alias->next)
|
||||||
|
if (wildcard_matchn(alias->iface, ifrn_name, IFNAMSIZ))
|
||||||
|
{
|
||||||
|
if (aparam->alias_ifs && (aparam->num_alias_ifs < aparam->max_alias_ifs))
|
||||||
|
aparam->alias_ifs[aparam->num_alias_ifs] = index;
|
||||||
|
aparam->num_alias_ifs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int iface_search(struct in6_addr *local, int prefix,
|
static int iface_search(struct in6_addr *local, int prefix,
|
||||||
int scope, int if_index, int flags,
|
int scope, int if_index, int flags,
|
||||||
int preferred, int valid, void *vparam)
|
int preferred, int valid, void *vparam)
|
||||||
|
|||||||
+243
-186
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -20,7 +20,7 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
char *name, int isExtract, int extrabytes)
|
char *name, int isExtract, int extrabytes)
|
||||||
{
|
{
|
||||||
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
unsigned char *cp = (unsigned char *)name, *p = *pp, *p1 = NULL;
|
||||||
unsigned int j, l, hops = 0;
|
unsigned int j, l, namelen = 0, hops = 0;
|
||||||
int retvalue = 1;
|
int retvalue = 1;
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
@@ -77,49 +77,10 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
|
|
||||||
p = l + (unsigned char *)header;
|
p = l + (unsigned char *)header;
|
||||||
}
|
}
|
||||||
else if (label_type == 0x80)
|
else if (label_type == 0x00)
|
||||||
return 0; /* reserved */
|
|
||||||
else if (label_type == 0x40)
|
|
||||||
{ /* ELT */
|
|
||||||
unsigned int count, digs;
|
|
||||||
|
|
||||||
if ((l & 0x3f) != 1)
|
|
||||||
return 0; /* we only understand bitstrings */
|
|
||||||
|
|
||||||
if (!isExtract)
|
|
||||||
return 0; /* Cannot compare bitsrings */
|
|
||||||
|
|
||||||
count = *p++;
|
|
||||||
if (count == 0)
|
|
||||||
count = 256;
|
|
||||||
digs = ((count-1)>>2)+1;
|
|
||||||
|
|
||||||
/* output is \[x<hex>/siz]. which is digs+9 chars */
|
|
||||||
if (cp - (unsigned char *)name + digs + 9 >= MAXDNAME)
|
|
||||||
return 0;
|
|
||||||
if (!CHECK_LEN(header, p, plen, (count-1)>>3))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
*cp++ = '\\';
|
|
||||||
*cp++ = '[';
|
|
||||||
*cp++ = 'x';
|
|
||||||
for (j=0; j<digs; j++)
|
|
||||||
{
|
|
||||||
unsigned int dig;
|
|
||||||
if (j%2 == 0)
|
|
||||||
dig = *p >> 4;
|
|
||||||
else
|
|
||||||
dig = *p++ & 0x0f;
|
|
||||||
|
|
||||||
*cp++ = dig < 10 ? dig + '0' : dig + 'A' - 10;
|
|
||||||
}
|
|
||||||
cp += sprintf((char *)cp, "/%d]", count);
|
|
||||||
/* do this here to overwrite the zero char from sprintf */
|
|
||||||
*cp++ = '.';
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ /* label_type = 0 -> label. */
|
{ /* label_type = 0 -> label. */
|
||||||
if (cp - (unsigned char *)name + l + 1 >= MAXDNAME)
|
namelen += l + 1; /* include period */
|
||||||
|
if (namelen >= MAXDNAME)
|
||||||
return 0;
|
return 0;
|
||||||
if (!CHECK_LEN(header, p, plen, l))
|
if (!CHECK_LEN(header, p, plen, l))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -128,8 +89,21 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
if (isExtract)
|
if (isExtract)
|
||||||
{
|
{
|
||||||
unsigned char c = *p;
|
unsigned char c = *p;
|
||||||
if (isascii(c) && !iscntrl(c) && c != '.')
|
#ifdef HAVE_DNSSEC
|
||||||
*cp++ = *p;
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
|
{
|
||||||
|
if (c == 0 || c == '.' || c == NAME_ESCAPE)
|
||||||
|
{
|
||||||
|
*cp++ = NAME_ESCAPE;
|
||||||
|
*cp++ = c+1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*cp++ = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
if (c != 0 && c != '.')
|
||||||
|
*cp++ = c;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -144,19 +118,26 @@ int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|||||||
cp++;
|
cp++;
|
||||||
if (c1 >= 'A' && c1 <= 'Z')
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
c1 += 'a' - 'A';
|
c1 += 'a' - 'A';
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && c1 == NAME_ESCAPE)
|
||||||
|
c1 = (*cp++)-1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
if (c1 != c2)
|
if (c1 != c2)
|
||||||
retvalue = 2;
|
retvalue = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isExtract)
|
if (isExtract)
|
||||||
*cp++ = '.';
|
*cp++ = '.';
|
||||||
else if (*cp != 0 && *cp++ != '.')
|
else if (*cp != 0 && *cp++ != '.')
|
||||||
retvalue = 2;
|
retvalue = 2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return 0; /* label types 0x40 and 0x80 not supported */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +318,7 @@ unsigned char *skip_questions(struct dns_header *header, size_t plen)
|
|||||||
return ansp;
|
return ansp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
|
unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *header, size_t plen)
|
||||||
{
|
{
|
||||||
int i, rdlen;
|
int i, rdlen;
|
||||||
|
|
||||||
@@ -527,7 +508,7 @@ static size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned
|
|||||||
return plen;
|
return plen;
|
||||||
*p++ = 0; /* empty name */
|
*p++ = 0; /* empty name */
|
||||||
PUTSHORT(T_OPT, p);
|
PUTSHORT(T_OPT, p);
|
||||||
PUTSHORT(daemon->edns_pktsz, p); /* max packet length */
|
PUTSHORT(SAFE_PKTSZ, p); /* max packet length, this will be overwritten */
|
||||||
PUTSHORT(0, p); /* extended RCODE and version */
|
PUTSHORT(0, p); /* extended RCODE and version */
|
||||||
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
|
PUTSHORT(set_do ? 0x8000 : 0, p); /* DO flag */
|
||||||
lenp = p;
|
lenp = p;
|
||||||
@@ -601,11 +582,11 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
|
|||||||
|
|
||||||
if (family == parm->l3->sa.sa_family)
|
if (family == parm->l3->sa.sa_family)
|
||||||
{
|
{
|
||||||
if (family == AF_INET && memcmp (&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
|
if (family == AF_INET && memcmp(&parm->l3->in.sin_addr, addrp, INADDRSZ) == 0)
|
||||||
match = 1;
|
match = 1;
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else
|
else
|
||||||
if (family == AF_INET6 && memcmp (&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
|
if (family == AF_INET6 && memcmp(&parm->l3->in6.sin6_addr, addrp, IN6ADDRSZ) == 0)
|
||||||
match = 1;
|
match = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -917,8 +898,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
searched_soa = 1;
|
searched_soa = 1;
|
||||||
ttl = find_soa(header, qlen, name, doctored);
|
ttl = find_soa(header, qlen, name, doctored);
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (*doctored)
|
if (*doctored && secure)
|
||||||
secure = 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -927,7 +908,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
for (i = ntohs(header->qdcount); i != 0; i--)
|
for (i = ntohs(header->qdcount); i != 0; i--)
|
||||||
{
|
{
|
||||||
int found = 0, cname_count = 5;
|
int found = 0, cname_count = CNAME_CHAIN;
|
||||||
struct crec *cpp = NULL;
|
struct crec *cpp = NULL;
|
||||||
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
int flags = RCODE(header) == NXDOMAIN ? F_NXDOMAIN : 0;
|
||||||
int secflag = secure ? F_DNSSECOK : 0;
|
int secflag = secure ? F_DNSSECOK : 0;
|
||||||
@@ -988,9 +969,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
if (aqtype == T_CNAME)
|
if (aqtype == T_CNAME)
|
||||||
{
|
{
|
||||||
if (!cname_count--)
|
if (!cname_count-- || secure)
|
||||||
return 0; /* looped CNAMES */
|
return 0; /* looped CNAMES, or DNSSEC, which we can't cache. */
|
||||||
secflag = 0; /* no longer DNSSEC */
|
|
||||||
goto cname_loop;
|
goto cname_loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1066,6 +1046,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
if (newc)
|
if (newc)
|
||||||
{
|
{
|
||||||
newc->addr.cname.target.cache = NULL;
|
newc->addr.cname.target.cache = NULL;
|
||||||
|
/* anything other than zero, to avoid being mistaken for CNAME to interface-name */
|
||||||
|
newc->addr.cname.uid = 1;
|
||||||
if (cpp)
|
if (cpp)
|
||||||
{
|
{
|
||||||
cpp->addr.cname.target.cache = newc;
|
cpp->addr.cname.target.cache = newc;
|
||||||
@@ -1091,17 +1073,33 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
memcpy(&addr, p1, addrlen);
|
memcpy(&addr, p1, addrlen);
|
||||||
|
|
||||||
/* check for returned address in private space */
|
/* check for returned address in private space */
|
||||||
if (check_rebind &&
|
if (check_rebind)
|
||||||
(flags & F_IPV4) &&
|
{
|
||||||
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
if ((flags & F_IPV4) &&
|
||||||
return 1;
|
private_net(addr.addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if ((flags & F_IPV6) &&
|
||||||
|
IN6_IS_ADDR_V4MAPPED(&addr.addr.addr6))
|
||||||
|
{
|
||||||
|
struct in_addr v4;
|
||||||
|
v4.s_addr = ((const uint32_t *) (&addr.addr.addr6))[3];
|
||||||
|
if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||||
{
|
{
|
||||||
ipsets_cur = ipsets;
|
ipsets_cur = ipsets;
|
||||||
while (*ipsets_cur)
|
while (*ipsets_cur)
|
||||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
{
|
||||||
|
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur);
|
||||||
|
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1194,7 +1192,10 @@ unsigned int extract_request(struct dns_header *header, size_t qlen, char *name,
|
|||||||
size_t setup_reply(struct dns_header *header, size_t qlen,
|
size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||||
struct all_addr *addrp, unsigned int flags, unsigned long ttl)
|
struct all_addr *addrp, unsigned int flags, unsigned long ttl)
|
||||||
{
|
{
|
||||||
unsigned char *p = skip_questions(header, qlen);
|
unsigned char *p;
|
||||||
|
|
||||||
|
if (!(p = skip_questions(header, qlen)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* clear authoritative and truncated flags, set QR flag */
|
/* clear authoritative and truncated flags, set QR flag */
|
||||||
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
|
header->hb3 = (header->hb3 & ~(HB3_AA | HB3_TC)) | HB3_QR;
|
||||||
@@ -1210,7 +1211,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
|
|||||||
SET_RCODE(header, NOERROR); /* empty domain */
|
SET_RCODE(header, NOERROR); /* empty domain */
|
||||||
else if (flags == F_NXDOMAIN)
|
else if (flags == F_NXDOMAIN)
|
||||||
SET_RCODE(header, NXDOMAIN);
|
SET_RCODE(header, NXDOMAIN);
|
||||||
else if (p && flags == F_IPV4)
|
else if (flags == F_IPV4)
|
||||||
{ /* we know the address */
|
{ /* we know the address */
|
||||||
SET_RCODE(header, NOERROR);
|
SET_RCODE(header, NOERROR);
|
||||||
header->ancount = htons(1);
|
header->ancount = htons(1);
|
||||||
@@ -1218,7 +1219,7 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
|
|||||||
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
|
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
else if (p && flags == F_IPV6)
|
else if (flags == F_IPV6)
|
||||||
{
|
{
|
||||||
SET_RCODE(header, NOERROR);
|
SET_RCODE(header, NOERROR);
|
||||||
header->ancount = htons(1);
|
header->ancount = htons(1);
|
||||||
@@ -1242,7 +1243,12 @@ int check_for_local_domain(char *name, time_t now)
|
|||||||
struct ptr_record *ptr;
|
struct ptr_record *ptr;
|
||||||
struct naptr *naptr;
|
struct naptr *naptr;
|
||||||
|
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME)) &&
|
/* Note: the call to cache_find_by_name is intended to find any record which matches
|
||||||
|
ie A, AAAA, CNAME, DS. Because RRSIG records are marked by setting both F_DS and F_DNSKEY,
|
||||||
|
cache_find_by name ordinarily only returns records with an exact match on those bits (ie
|
||||||
|
for the call below, only DS records). The F_NSIGMATCH bit changes this behaviour */
|
||||||
|
|
||||||
|
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_DS | F_NO_RR | F_NSIGMATCH)) &&
|
||||||
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@@ -1319,6 +1325,43 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
int i, qtype, qclass, rdlen;
|
||||||
|
struct bogus_addr *baddrp;
|
||||||
|
|
||||||
|
/* skip over questions */
|
||||||
|
if (!(p = skip_questions(header, qlen)))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
for (i = ntohs(header->ancount); i != 0; i--)
|
||||||
|
{
|
||||||
|
if (!(p = skip_name(p, header, qlen, 10)))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
|
||||||
|
GETSHORT(qtype, p);
|
||||||
|
GETSHORT(qclass, p);
|
||||||
|
p += 4; /* TTL */
|
||||||
|
GETSHORT(rdlen, p);
|
||||||
|
|
||||||
|
if (qclass == C_IN && qtype == T_A)
|
||||||
|
{
|
||||||
|
if (!CHECK_LEN(header, p, qlen, INADDRSZ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (baddrp = baddr; baddrp; baddrp = baddrp->next)
|
||||||
|
if (memcmp(&baddrp->addr, p, INADDRSZ) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ADD_RDLEN(header, p, qlen, rdlen))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp, int nameoffset, unsigned char **pp,
|
||||||
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
unsigned long ttl, int *offset, unsigned short type, unsigned short class, char *format, ...)
|
||||||
{
|
{
|
||||||
@@ -1452,25 +1495,29 @@ static unsigned long crec_ttl(struct crec *crecp, time_t now)
|
|||||||
|
|
||||||
/* return zero if we can't answer from cache, or packet size if we can */
|
/* return zero if we can't answer from cache, or packet size if we can */
|
||||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
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)
|
struct in_addr local_addr, struct in_addr local_netmask,
|
||||||
|
time_t now, int *ad_reqd, int *do_bit)
|
||||||
{
|
{
|
||||||
char *name = daemon->namebuff;
|
char *name = daemon->namebuff;
|
||||||
unsigned char *p, *ansp, *pheader;
|
unsigned char *p, *ansp, *pheader;
|
||||||
int qtype, qclass;
|
unsigned int qtype, qclass;
|
||||||
struct all_addr addr;
|
struct all_addr addr;
|
||||||
int nameoffset;
|
int nameoffset;
|
||||||
unsigned short flag;
|
unsigned short flag;
|
||||||
int q, ans, anscount = 0, addncount = 0;
|
int q, ans, anscount = 0, addncount = 0;
|
||||||
int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
|
int dryrun = 0, sec_reqd = 0, have_pseudoheader = 0;
|
||||||
int is_sign;
|
|
||||||
struct crec *crecp;
|
struct crec *crecp;
|
||||||
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
|
int nxdomain = 0, auth = 1, trunc = 0, sec_data = 1;
|
||||||
struct mx_srv_record *rec;
|
struct mx_srv_record *rec;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
/* Don't return AD set even for local data if checking disabled. */
|
/* Don't return AD set if checking disabled. */
|
||||||
if (header->hb4 & HB4_CD)
|
if (header->hb4 & HB4_CD)
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
|
|
||||||
|
/* RFC 6840 5.7 */
|
||||||
|
*ad_reqd = header->hb4 & HB4_AD;
|
||||||
|
*do_bit = 0;
|
||||||
|
|
||||||
/* If there is an RFC2671 pseudoheader then it will be overwritten by
|
/* If there is an RFC2671 pseudoheader then it will be overwritten by
|
||||||
partial replies, so we have to do a dry run to see if we can answer
|
partial replies, so we have to do a dry run to see if we can answer
|
||||||
@@ -1478,26 +1525,19 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
forward rather than answering from the cache, which doesn't include
|
forward rather than answering from the cache, which doesn't include
|
||||||
security information, unless we're in DNSSEC validation mode. */
|
security information, unless we're in DNSSEC validation mode. */
|
||||||
|
|
||||||
if (find_pseudoheader(header, qlen, NULL, &pheader, &is_sign))
|
if (find_pseudoheader(header, qlen, NULL, &pheader, NULL))
|
||||||
{
|
{
|
||||||
unsigned short udpsz, flags;
|
unsigned short flags;
|
||||||
unsigned char *psave = pheader;
|
|
||||||
|
|
||||||
have_pseudoheader = 1;
|
have_pseudoheader = 1;
|
||||||
|
|
||||||
GETSHORT(udpsz, pheader);
|
pheader += 4; /* udp size, ext_rcode */
|
||||||
pheader += 2; /* ext_rcode */
|
|
||||||
GETSHORT(flags, pheader);
|
GETSHORT(flags, pheader);
|
||||||
|
|
||||||
sec_reqd = flags & 0x8000; /* do bit */
|
if ((sec_reqd = flags & 0x8000))
|
||||||
|
*do_bit = 1;/* do bit */
|
||||||
/* If our client is advertising a larger UDP packet size
|
|
||||||
than we allow, trim it so that we don't get an overlarge
|
|
||||||
response from upstream */
|
|
||||||
|
|
||||||
if (!is_sign && (udpsz > daemon->edns_pktsz))
|
|
||||||
PUTSHORT(daemon->edns_pktsz, psave);
|
|
||||||
|
|
||||||
|
*ad_reqd = 1;
|
||||||
dryrun = 1;
|
dryrun = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1527,6 +1567,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
GETSHORT(qtype, p);
|
GETSHORT(qtype, p);
|
||||||
GETSHORT(qclass, p);
|
GETSHORT(qclass, p);
|
||||||
|
|
||||||
|
/* Don't filter RRSIGS from answers to ANY queries, even if do-bit
|
||||||
|
not set. */
|
||||||
|
if (qtype == T_ANY)
|
||||||
|
*do_bit = 1;
|
||||||
|
|
||||||
ans = 0; /* have we answered this question */
|
ans = 0; /* have we answered this question */
|
||||||
|
|
||||||
if (qtype == T_TXT || qtype == T_ANY)
|
if (qtype == T_TXT || qtype == T_ANY)
|
||||||
@@ -1539,10 +1584,20 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
|
unsigned long ttl = daemon->local_ttl;
|
||||||
|
int ok = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
/* Dynamically generate stat record */
|
||||||
daemon->local_ttl, NULL,
|
if (t->stat != 0)
|
||||||
T_TXT, t->class, "t", t->len, t->txt))
|
{
|
||||||
|
ttl = 0;
|
||||||
|
if (!cache_make_stat(t))
|
||||||
|
ok = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok && add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
ttl, NULL,
|
||||||
|
T_TXT, t->class, "t", t->len, t->txt))
|
||||||
anscount++;
|
anscount++;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1551,58 +1606,60 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS || qtype == T_RRSIG))
|
if (option_bool(OPT_DNSSEC_VALID) && (qtype == T_DNSKEY || qtype == T_DS))
|
||||||
{
|
{
|
||||||
int gotone = 0, have_rrsig = 0;
|
int gotone = 0;
|
||||||
struct blockdata *keydata;
|
struct blockdata *keydata;
|
||||||
|
|
||||||
/* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
|
/* Do we have RRSIG? Can't do DS or DNSKEY otherwise. */
|
||||||
crecp = NULL;
|
if (sec_reqd)
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
|
{
|
||||||
if (crecp->uid == qclass && (qtype == T_RRSIG || crecp->addr.sig.type_covered == qtype))
|
crecp = NULL;
|
||||||
{
|
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
|
||||||
have_rrsig = 1;
|
if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qtype == T_RRSIG && have_rrsig)
|
if (!sec_reqd || crecp)
|
||||||
{
|
{
|
||||||
ans = gotone = 1;
|
if (qtype == T_DS)
|
||||||
auth = 0;
|
{
|
||||||
}
|
crecp = NULL;
|
||||||
else if (qtype == T_DS && have_rrsig)
|
while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
|
||||||
{
|
if (crecp->uid == qclass)
|
||||||
auth = 0;
|
|
||||||
crecp = NULL;
|
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DS)))
|
|
||||||
if (crecp->uid == qclass)
|
|
||||||
{
|
|
||||||
ans = gotone = 1;
|
|
||||||
if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
|
|
||||||
{
|
|
||||||
struct all_addr a;
|
|
||||||
a.addr.keytag = crecp->addr.ds.keytag;
|
|
||||||
log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
|
||||||
T_DS, qclass, "sbbt",
|
|
||||||
crecp->addr.ds.keytag, crecp->addr.ds.algo, crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
|
|
||||||
anscount++;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (qtype == T_DNSKEY)
|
|
||||||
{
|
|
||||||
crecp = NULL;
|
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
|
|
||||||
if (crecp->uid == qclass)
|
|
||||||
{
|
|
||||||
if ((crecp->flags & F_CONFIG) || have_rrsig) /* Return configured keys without an RRISG */
|
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_CONFIG))
|
gotone = 1;
|
||||||
auth = 0, gotone = 1;
|
if (!dryrun)
|
||||||
ans = 1;
|
{
|
||||||
|
if (crecp->flags & F_NEG)
|
||||||
|
{
|
||||||
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
|
nxdomain = 1;
|
||||||
|
log_query(F_UPSTREAM, name, NULL, "no DS");
|
||||||
|
}
|
||||||
|
else if ((keydata = blockdata_retrieve(crecp->addr.ds.keydata, crecp->addr.ds.keylen, NULL)))
|
||||||
|
{
|
||||||
|
struct all_addr a;
|
||||||
|
a.addr.keytag = crecp->addr.ds.keytag;
|
||||||
|
log_query(F_KEYTAG | (crecp->flags & F_CONFIG), name, &a, "DS keytag %u");
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
crec_ttl(crecp, now), &nameoffset,
|
||||||
|
T_DS, qclass, "sbbt",
|
||||||
|
crecp->addr.ds.keytag, crecp->addr.ds.algo,
|
||||||
|
crecp->addr.ds.digest, crecp->addr.ds.keylen, keydata))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* DNSKEY */
|
||||||
|
{
|
||||||
|
crecp = NULL;
|
||||||
|
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY)))
|
||||||
|
if (crecp->uid == qclass)
|
||||||
|
{
|
||||||
|
gotone = 1;
|
||||||
if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
|
if (!dryrun && (keydata = blockdata_retrieve(crecp->addr.key.keydata, crecp->addr.key.keylen, NULL)))
|
||||||
{
|
{
|
||||||
struct all_addr a;
|
struct all_addr a;
|
||||||
@@ -1615,30 +1672,27 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now do RRSIGs */
|
/* Now do RRSIGs */
|
||||||
if (gotone)
|
if (gotone)
|
||||||
{
|
{
|
||||||
crecp = NULL;
|
ans = 1;
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
|
auth = 0;
|
||||||
if (crecp->uid == qclass && (qtype == T_RRSIG || (sec_reqd && crecp->addr.sig.type_covered == qtype)) &&
|
if (!dryrun && sec_reqd)
|
||||||
!dryrun &&
|
{
|
||||||
(keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
|
crecp = NULL;
|
||||||
{
|
while ((crecp = cache_find_by_name(crecp, name, now, F_DNSKEY | F_DS)))
|
||||||
if (qtype == T_RRSIG)
|
if (crecp->uid == qclass && crecp->addr.sig.type_covered == qtype &&
|
||||||
|
(keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)))
|
||||||
{
|
{
|
||||||
char types[20];
|
|
||||||
querystr("rrsig", types, crecp->addr.sig.type_covered);
|
|
||||||
log_query(F_RRNAME, name, NULL, types);
|
|
||||||
}
|
|
||||||
if ((keydata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL)) &&
|
|
||||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crec_ttl(crecp, now), &nameoffset,
|
crec_ttl(crecp, now), &nameoffset,
|
||||||
T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata))
|
T_RRSIG, qclass, "t", crecp->addr.sig.keylen, keydata);
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1742,24 +1796,25 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
else if (crecp->flags & F_DNSSECOK)
|
else if (crecp->flags & F_DNSSECOK)
|
||||||
{
|
{
|
||||||
int gotsig = 0;
|
int gotsig = 0;
|
||||||
|
struct crec *rr_crec = NULL;
|
||||||
crecp = NULL;
|
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DS | F_DNSKEY)))
|
while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
|
||||||
{
|
{
|
||||||
if (crecp->addr.sig.type_covered == T_PTR && crecp->uid == C_IN)
|
if (rr_crec->addr.sig.type_covered == T_PTR && rr_crec->uid == C_IN)
|
||||||
{
|
{
|
||||||
char *sigdata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL);
|
char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
|
||||||
gotsig = 1;
|
gotsig = 1;
|
||||||
|
|
||||||
if (!dryrun &&
|
if (!dryrun &&
|
||||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crecp->ttd - now, &nameoffset,
|
rr_crec->ttd - now, &nameoffset,
|
||||||
T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
|
T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Need to re-run original cache search */
|
|
||||||
crecp = gotsig ? cache_find_by_addr(NULL, &addr, now, is_arpa) : NULL;
|
if (!gotsig)
|
||||||
|
crecp = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1897,14 +1952,17 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
if (hostname_isequal(name, intr->name))
|
if (hostname_isequal(name, intr->name))
|
||||||
{
|
{
|
||||||
ans = 1;
|
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||||
if (!dryrun)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
|
||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
|
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == type)
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (addrlist->flags & ADDRLIST_REVONLY)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
ans = 1;
|
||||||
|
if (!dryrun)
|
||||||
{
|
{
|
||||||
gotit = 1;
|
gotit = 1;
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addrlist->addr, NULL);
|
||||||
@@ -1913,7 +1971,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
type == T_A ? "4" : "6", &addrlist->addr))
|
type == T_A ? "4" : "6", &addrlist->addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dryrun && !gotit)
|
if (!dryrun && !gotit)
|
||||||
@@ -1923,7 +1981,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cname_restart:
|
cname_restart:
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME)))
|
if ((crecp = cache_find_by_name(NULL, name, now, flag | F_CNAME | (dryrun ? F_NO_RR : 0))))
|
||||||
{
|
{
|
||||||
int localise = 0;
|
int localise = 0;
|
||||||
|
|
||||||
@@ -1954,7 +2012,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
else if (crecp->flags & F_DNSSECOK)
|
else if (crecp->flags & F_DNSSECOK)
|
||||||
{
|
{
|
||||||
/* We're returning validated data, need to return the RRSIG too. */
|
/* We're returning validated data, need to return the RRSIG too. */
|
||||||
|
struct crec *rr_crec = NULL;
|
||||||
int sigtype = type;
|
int sigtype = type;
|
||||||
/* The signature may have expired even though the data is still in cache,
|
/* The signature may have expired even though the data is still in cache,
|
||||||
forward instead of answering from cache if so. */
|
forward instead of answering from cache if so. */
|
||||||
@@ -1963,23 +2021,23 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (crecp->flags & F_CNAME)
|
if (crecp->flags & F_CNAME)
|
||||||
sigtype = T_CNAME;
|
sigtype = T_CNAME;
|
||||||
|
|
||||||
crecp = NULL;
|
while ((rr_crec = cache_find_by_name(rr_crec, name, now, F_DS | F_DNSKEY)))
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_DS | F_DNSKEY)))
|
|
||||||
{
|
{
|
||||||
if (crecp->addr.sig.type_covered == sigtype && crecp->uid == C_IN)
|
if (rr_crec->addr.sig.type_covered == sigtype && rr_crec->uid == C_IN)
|
||||||
{
|
{
|
||||||
char *sigdata = blockdata_retrieve(crecp->addr.sig.keydata, crecp->addr.sig.keylen, NULL);
|
char *sigdata = blockdata_retrieve(rr_crec->addr.sig.keydata, rr_crec->addr.sig.keylen, NULL);
|
||||||
gotsig = 1;
|
gotsig = 1;
|
||||||
|
|
||||||
if (!dryrun &&
|
if (!dryrun &&
|
||||||
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
crecp->ttd - now, &nameoffset,
|
rr_crec->ttd - now, &nameoffset,
|
||||||
T_RRSIG, C_IN, "t", crecp->addr.sig.keylen, sigdata))
|
T_RRSIG, C_IN, "t", rr_crec->addr.sig.keylen, sigdata))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Need to re-run original cache search */
|
|
||||||
crecp = gotsig ? cache_find_by_name(NULL, name, now, flag | F_CNAME) : NULL;
|
if (!gotsig)
|
||||||
|
crecp = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -2010,7 +2068,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
|
|
||||||
strcpy(name, cname_target);
|
strcpy(name, cname_target);
|
||||||
/* check if target interface_name */
|
/* check if target interface_name */
|
||||||
if (crecp->addr.cname.uid == -1)
|
if (crecp->addr.cname.uid == SRC_INTERFACE)
|
||||||
goto intname_restart;
|
goto intname_restart;
|
||||||
else
|
else
|
||||||
goto cname_restart;
|
goto cname_restart;
|
||||||
@@ -2072,7 +2130,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
if (qtype == T_CNAME || qtype == T_ANY)
|
if (qtype == T_CNAME || qtype == T_ANY)
|
||||||
{
|
{
|
||||||
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
|
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME)) &&
|
||||||
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))))
|
(qtype == T_CNAME || (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG | (dryrun ? F_NO_RR : 0)))))
|
||||||
{
|
{
|
||||||
if (!(crecp->flags & F_DNSSECOK))
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
sec_data = 0;
|
sec_data = 0;
|
||||||
@@ -2111,7 +2169,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
|
if (!found && (option_bool(OPT_SELFMX) || option_bool(OPT_LOCALMX)) &&
|
||||||
cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP))
|
cache_find_by_name(NULL, name, now, F_HOSTS | F_DHCP | F_NO_RR))
|
||||||
{
|
{
|
||||||
ans = 1;
|
ans = 1;
|
||||||
if (!dryrun)
|
if (!dryrun)
|
||||||
@@ -2263,17 +2321,16 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
header->ancount = htons(anscount);
|
header->ancount = htons(anscount);
|
||||||
header->nscount = htons(0);
|
header->nscount = htons(0);
|
||||||
header->arcount = htons(addncount);
|
header->arcount = htons(addncount);
|
||||||
|
|
||||||
header->hb4 &= ~HB4_AD;
|
|
||||||
len = ansp - (unsigned char *)header;
|
len = ansp - (unsigned char *)header;
|
||||||
|
|
||||||
if (have_pseudoheader)
|
if (have_pseudoheader)
|
||||||
{
|
len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
|
||||||
len = add_pseudoheader(header, len, (unsigned char *)limit, 0, NULL, 0, sec_reqd);
|
|
||||||
if (sec_reqd && sec_data)
|
if (*ad_reqd && sec_data)
|
||||||
header->hb4 |= HB4_AD;
|
header->hb4 |= HB4_AD;
|
||||||
|
else
|
||||||
}
|
header->hb4 &= ~HB4_AD;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|||||||
+62
-26
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -52,7 +52,9 @@ static void do_options(struct dhcp_context *context,
|
|||||||
int null_term, int pxearch,
|
int null_term, int pxearch,
|
||||||
unsigned char *uuid,
|
unsigned char *uuid,
|
||||||
int vendor_class_len,
|
int vendor_class_len,
|
||||||
time_t now);
|
time_t now,
|
||||||
|
unsigned int lease_time,
|
||||||
|
unsigned short fuzz);
|
||||||
|
|
||||||
|
|
||||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||||
@@ -610,7 +612,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
|
||||||
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now);
|
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -803,9 +805,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (service->type == type)
|
if (service->type == type)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!service || !service->basename)
|
for (; context; context = context->current)
|
||||||
return 0;
|
if (match_netid(context->filter, tagif_netid, 1) &&
|
||||||
|
is_same_net(mess->ciaddr, context->start, context->netmask))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!service || !service->basename || !context)
|
||||||
|
return 0;
|
||||||
|
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
|
|
||||||
mess->yiaddr = mess->ciaddr;
|
mess->yiaddr = mess->ciaddr;
|
||||||
@@ -886,10 +893,10 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
||||||
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
|
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
|
||||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
|
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
|
||||||
pxe_misc(mess, end, uuid);
|
pxe_misc(mess, end, uuid);
|
||||||
prune_vendor_opts(tagif_netid);
|
prune_vendor_opts(tagif_netid);
|
||||||
do_encap_opts(pxe_opts(pxearch, tagif_netid, context->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||||
|
|
||||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
||||||
log_tags(tagif_netid, ntohl(mess->xid));
|
log_tags(tagif_netid, ntohl(mess->xid));
|
||||||
@@ -962,6 +969,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
case DHCPDISCOVER:
|
case DHCPDISCOVER:
|
||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
{
|
{
|
||||||
|
if (option_bool(OPT_QUIET_DHCP))
|
||||||
|
return 0;
|
||||||
message = _("ignored");
|
message = _("ignored");
|
||||||
opt = NULL;
|
opt = NULL;
|
||||||
}
|
}
|
||||||
@@ -1040,13 +1049,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||||
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
|
||||||
if (time != 0xffffffff)
|
|
||||||
{
|
|
||||||
option_put(mess, end, OPTION_T1, 4, (time/2));
|
|
||||||
option_put(mess, end, OPTION_T2, 4, (time*7)/8);
|
|
||||||
}
|
|
||||||
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
|
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
|
||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
|
||||||
|
|
||||||
return dhcp_packet_size(mess, agent_id, real_end);
|
return dhcp_packet_size(mess, agent_id, real_end);
|
||||||
|
|
||||||
@@ -1365,15 +1369,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
|
||||||
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
|
||||||
if (time != 0xffffffff)
|
|
||||||
{
|
|
||||||
while (fuzz > (time/16))
|
|
||||||
fuzz = fuzz/2;
|
|
||||||
option_put(mess, end, OPTION_T1, 4, (time/2) - fuzz);
|
|
||||||
option_put(mess, end, OPTION_T2, 4, ((time/8)*7) - fuzz);
|
|
||||||
}
|
|
||||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
|
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
|
||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dhcp_packet_size(mess, agent_id, real_end);
|
return dhcp_packet_size(mess, agent_id, real_end);
|
||||||
@@ -1438,7 +1435,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
|
||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
|
||||||
|
|
||||||
*is_inform = 1; /* handle reply differently */
|
*is_inform = 1; /* handle reply differently */
|
||||||
return dhcp_packet_size(mess, agent_id, real_end);
|
return dhcp_packet_size(mess, agent_id, real_end);
|
||||||
@@ -2135,7 +2132,9 @@ static void do_options(struct dhcp_context *context,
|
|||||||
int null_term, int pxe_arch,
|
int null_term, int pxe_arch,
|
||||||
unsigned char *uuid,
|
unsigned char *uuid,
|
||||||
int vendor_class_len,
|
int vendor_class_len,
|
||||||
time_t now)
|
time_t now,
|
||||||
|
unsigned int lease_time,
|
||||||
|
unsigned short fuzz)
|
||||||
{
|
{
|
||||||
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
|
||||||
struct dhcp_boot *boot;
|
struct dhcp_boot *boot;
|
||||||
@@ -2259,7 +2258,42 @@ static void do_options(struct dhcp_context *context,
|
|||||||
/* rfc3011 says this doesn't need to be in the requested options list. */
|
/* rfc3011 says this doesn't need to be in the requested options list. */
|
||||||
if (subnet_addr.s_addr)
|
if (subnet_addr.s_addr)
|
||||||
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
|
option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
|
||||||
|
|
||||||
|
if (lease_time != 0xffffffff)
|
||||||
|
{
|
||||||
|
unsigned int t1val = lease_time/2;
|
||||||
|
unsigned int t2val = (lease_time*7)/8;
|
||||||
|
unsigned int hval;
|
||||||
|
|
||||||
|
/* If set by user, sanity check, so not longer than lease. */
|
||||||
|
if ((opt = option_find2(OPTION_T1)))
|
||||||
|
{
|
||||||
|
hval = ntohl(*((unsigned int *)opt->val));
|
||||||
|
if (hval < lease_time && hval > 2)
|
||||||
|
t1val = hval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opt = option_find2(OPTION_T2)))
|
||||||
|
{
|
||||||
|
hval = ntohl(*((unsigned int *)opt->val));
|
||||||
|
if (hval < lease_time && hval > 2)
|
||||||
|
t2val = hval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ensure T1 is still < T2 */
|
||||||
|
if (t2val <= t1val)
|
||||||
|
t1val = t2val - 1;
|
||||||
|
|
||||||
|
while (fuzz > (t1val/8))
|
||||||
|
fuzz = fuzz/2;
|
||||||
|
|
||||||
|
t1val -= fuzz;
|
||||||
|
t2val -= fuzz;
|
||||||
|
|
||||||
|
option_put(mess, end, OPTION_T1, 4, t1val);
|
||||||
|
option_put(mess, end, OPTION_T2, 4, t2val);
|
||||||
|
}
|
||||||
|
|
||||||
/* replies to DHCPINFORM may not have a valid context */
|
/* replies to DHCPINFORM may not have a valid context */
|
||||||
if (context)
|
if (context)
|
||||||
{
|
{
|
||||||
@@ -2354,12 +2388,14 @@ static void do_options(struct dhcp_context *context,
|
|||||||
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
|
if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* prohibit some used-internally options */
|
/* prohibit some used-internally options. T1 and T2 already handled. */
|
||||||
if (optno == OPTION_CLIENT_FQDN ||
|
if (optno == OPTION_CLIENT_FQDN ||
|
||||||
optno == OPTION_MAXMESSAGE ||
|
optno == OPTION_MAXMESSAGE ||
|
||||||
optno == OPTION_OVERLOAD ||
|
optno == OPTION_OVERLOAD ||
|
||||||
optno == OPTION_PAD ||
|
optno == OPTION_PAD ||
|
||||||
optno == OPTION_END)
|
optno == OPTION_END ||
|
||||||
|
optno == OPTION_T1 ||
|
||||||
|
optno == OPTION_T2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (optno == OPTION_SNAME && done_server)
|
if (optno == OPTION_SNAME && done_server)
|
||||||
|
|||||||
+54
-8
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -313,8 +313,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
else if (msg_type != DHCP6IREQ)
|
else if (msg_type != DHCP6IREQ)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* server-id must match except for SOLICIT and CONFIRM messages */
|
/* server-id must match except for SOLICIT, CONFIRM and REBIND messages */
|
||||||
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ &&
|
if (msg_type != DHCP6SOLICIT && msg_type != DHCP6CONFIRM && msg_type != DHCP6IREQ && msg_type != DHCP6REBIND &&
|
||||||
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
|
(!(opt = opt6_find(state->packet_options, state->end, OPTION6_SERVER_ID, 1)) ||
|
||||||
opt6_len(opt) != daemon->duid_len ||
|
opt6_len(opt) != daemon->duid_len ||
|
||||||
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
|
memcmp(opt6_ptr(opt, 0), daemon->duid, daemon->duid_len) != 0))
|
||||||
@@ -328,6 +328,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
|
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
|
||||||
|
|
||||||
{
|
{
|
||||||
|
*outmsgtypep = DHCP6REPLY;
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6USEMULTI);
|
put_opt6_short(DHCP6USEMULTI);
|
||||||
put_opt6_string("Use multicast");
|
put_opt6_string("Use multicast");
|
||||||
@@ -690,6 +691,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
o = build_ia(state, &t1cntr);
|
o = build_ia(state, &t1cntr);
|
||||||
|
if (address_assigned)
|
||||||
|
address_assigned = 2;
|
||||||
|
|
||||||
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
@@ -780,6 +783,27 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
address_assigned = 1;
|
address_assigned = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (address_assigned != 1)
|
||||||
|
{
|
||||||
|
/* If the server will not assign any addresses to any IAs in a
|
||||||
|
subsequent Request from the client, the server MUST send an Advertise
|
||||||
|
message to the client that doesn't include any IA options. */
|
||||||
|
if (!state->lease_allocate)
|
||||||
|
{
|
||||||
|
save_counter(o);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the server cannot assign any addresses to an IA in the message
|
||||||
|
from the client, the server MUST include the IA in the Reply message
|
||||||
|
with no addresses in the IA and a Status Code option in the IA
|
||||||
|
containing status code NoAddrsAvail. */
|
||||||
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
|
put_opt6_string(_("address unavailable"));
|
||||||
|
end_opt6(o1);
|
||||||
|
}
|
||||||
|
|
||||||
end_ia(t1cntr, min_time, 0);
|
end_ia(t1cntr, min_time, 0);
|
||||||
end_opt6(o);
|
end_opt6(o);
|
||||||
}
|
}
|
||||||
@@ -805,7 +829,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
put_opt6_short(DHCP6NOADDRS);
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
put_opt6_string(_("no addresses available"));
|
put_opt6_string(_("no addresses available"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
log6_packet(state, "DHCPADVERTISE", NULL, _("no addresses available"));
|
|
||||||
|
/* Some clients will ask repeatedly when we're not giving
|
||||||
|
out addresses because we're in stateless mode. Avoid spamming
|
||||||
|
the log in that case. */
|
||||||
|
for (c = state->context; c; c = c->current)
|
||||||
|
if (!(c->flags & CONTEXT_RA_STATELESS))
|
||||||
|
{
|
||||||
|
log6_packet(state, state->lease_allocate ? "DHCPREPLY" : "DHCPADVERTISE", NULL, _("no addresses available"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -861,7 +894,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
{
|
{
|
||||||
/* Static range, not configured. */
|
/* Static range, not configured. */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6UNSPEC);
|
put_opt6_short(DHCP6NOADDRS);
|
||||||
put_opt6_string(_("address unavailable"));
|
put_opt6_string(_("address unavailable"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
}
|
}
|
||||||
@@ -1014,9 +1047,9 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
{
|
{
|
||||||
preferred_time = valid_time = 0;
|
preferred_time = valid_time = 0;
|
||||||
message = _("address invalid");
|
message = _("address invalid");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message)
|
if (message && (message != state->hostname))
|
||||||
log6_packet(state, "DHCPREPLY", req_addr, message);
|
log6_packet(state, "DHCPREPLY", req_addr, message);
|
||||||
else
|
else
|
||||||
log6_quiet(state, "DHCPREPLY", req_addr, message);
|
log6_quiet(state, "DHCPREPLY", req_addr, message);
|
||||||
@@ -1039,6 +1072,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
|
|
||||||
case DHCP6CONFIRM:
|
case DHCP6CONFIRM:
|
||||||
{
|
{
|
||||||
|
int good_addr = 0;
|
||||||
|
|
||||||
/* set reply message type */
|
/* set reply message type */
|
||||||
*outmsgtypep = DHCP6REPLY;
|
*outmsgtypep = DHCP6REPLY;
|
||||||
|
|
||||||
@@ -1054,7 +1089,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
{
|
{
|
||||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||||
|
|
||||||
if (!address6_available(state->context, req_addr, tagif, 1))
|
if (!address6_valid(state->context, req_addr, tagif, 1))
|
||||||
{
|
{
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6NOTONLINK);
|
put_opt6_short(DHCP6NOTONLINK);
|
||||||
@@ -1063,9 +1098,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
good_addr = 1;
|
||||||
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
|
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No addresses, no reply: RFC 3315 18.2.2 */
|
||||||
|
if (!good_addr)
|
||||||
|
return 0;
|
||||||
|
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6SUCCESS );
|
put_opt6_short(DHCP6SUCCESS );
|
||||||
@@ -1232,6 +1272,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We must anwser with 'success' in global section anyway */
|
||||||
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
|
put_opt6_short(DHCP6SUCCESS);
|
||||||
|
put_opt6_string(_("success"));
|
||||||
|
end_opt6(o1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
+173
@@ -0,0 +1,173 @@
|
|||||||
|
/* tables.c is Copyright (c) 2014 Sven Falempin All Rights Reserved.
|
||||||
|
|
||||||
|
Author's email: sfalempin@citypassenger.com
|
||||||
|
|
||||||
|
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_IPSET) && defined(HAVE_BSD_NETWORK)
|
||||||
|
|
||||||
|
#ifndef __FreeBSD__
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <net/pfvar.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#define UNUSED(x) (void)(x)
|
||||||
|
|
||||||
|
static char *pf_device = "/dev/pf";
|
||||||
|
static int dev = -1;
|
||||||
|
|
||||||
|
static char *pfr_strerror(int errnum)
|
||||||
|
{
|
||||||
|
switch (errnum)
|
||||||
|
{
|
||||||
|
case ESRCH:
|
||||||
|
return "Table does not exist";
|
||||||
|
case ENOENT:
|
||||||
|
return "Anchor or Ruleset does not exist";
|
||||||
|
default:
|
||||||
|
return strerror(errnum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||||
|
{
|
||||||
|
struct pfioc_table io;
|
||||||
|
|
||||||
|
if (size < 0 || (size && tbl == NULL))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
bzero(&io, sizeof io);
|
||||||
|
io.pfrio_flags = flags;
|
||||||
|
io.pfrio_buffer = tbl;
|
||||||
|
io.pfrio_esize = sizeof(*tbl);
|
||||||
|
io.pfrio_size = size;
|
||||||
|
if (ioctl(dev, DIOCRADDTABLES, &io))
|
||||||
|
return (-1);
|
||||||
|
if (nadd != NULL)
|
||||||
|
*nadd = io.pfrio_nadd;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
|
||||||
|
if ( !addr || !ipaddr)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("error: fill_addr missused"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
bzero(addr, sizeof(*addr));
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (flags & F_IPV6)
|
||||||
|
{
|
||||||
|
addr->pfra_af = AF_INET6;
|
||||||
|
addr->pfra_net = 0x80;
|
||||||
|
memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
addr->pfra_af = AF_INET;
|
||||||
|
addr->pfra_net = 0x20;
|
||||||
|
addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void ipset_init(void)
|
||||||
|
{
|
||||||
|
dev = open( pf_device, O_RDWR);
|
||||||
|
if (dev == -1)
|
||||||
|
{
|
||||||
|
err(1, "%s", pf_device);
|
||||||
|
die (_("failed to access pf devices: %s"), NULL, EC_MISC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
||||||
|
int flags, int remove)
|
||||||
|
{
|
||||||
|
struct pfr_addr addr;
|
||||||
|
struct pfioc_table io;
|
||||||
|
struct pfr_table table;
|
||||||
|
int n = 0, rc = 0;
|
||||||
|
|
||||||
|
if ( dev == -1 )
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&table, sizeof(struct pfr_table));
|
||||||
|
table.pfrt_flags |= PFR_TFLAG_PERSIST;
|
||||||
|
if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( strlcpy(table.pfrt_name, setname,
|
||||||
|
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((rc = pfr_add_tables(&table, 1, &n, 0)))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
|
||||||
|
pfr_strerror(errno),rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
|
||||||
|
if (n)
|
||||||
|
my_syslog(LOG_INFO, _("info: table created"));
|
||||||
|
|
||||||
|
fill_addr(ipaddr,flags,&addr);
|
||||||
|
bzero(&io, sizeof(io));
|
||||||
|
io.pfrio_flags = 0;
|
||||||
|
io.pfrio_table = table;
|
||||||
|
io.pfrio_buffer = &addr;
|
||||||
|
io.pfrio_esize = sizeof(addr);
|
||||||
|
io.pfrio_size = 1;
|
||||||
|
if (ioctl(dev, ( remove ? DIOCRDELADDRS : DIOCRADDADDRS ), &io))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_WARNING, _("warning: DIOCR%sADDRS: %s"), ( remove ? "DEL" : "ADD" ), pfr_strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
my_syslog(LOG_INFO, _("%d addresses %s"),
|
||||||
|
io.pfrio_nadd, ( remove ? "removed" : "added" ));
|
||||||
|
|
||||||
|
return io.pfrio_nadd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -236,7 +236,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
/* check for per-interface prefix */
|
/* check for per-interface prefix */
|
||||||
@@ -502,7 +502,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_tftp_listeners(fd_set *rset, time_t now)
|
void check_tftp_listeners(time_t now)
|
||||||
{
|
{
|
||||||
struct tftp_transfer *transfer, *tmp, **up;
|
struct tftp_transfer *transfer, *tmp, **up;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
@@ -518,7 +518,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
|||||||
|
|
||||||
prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
||||||
|
|
||||||
if (FD_ISSET(transfer->sockfd, rset))
|
if (poll_check(transfer->sockfd, POLLIN))
|
||||||
{
|
{
|
||||||
/* we overwrote the buffer... */
|
/* we overwrote the buffer... */
|
||||||
daemon->srv_save = NULL;
|
daemon->srv_save = NULL;
|
||||||
|
|||||||
+95
-90
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -81,6 +81,18 @@ unsigned short rand16(void)
|
|||||||
return (unsigned short) out[--outleft];
|
return (unsigned short) out[--outleft];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 rand32(void)
|
||||||
|
{
|
||||||
|
if (!outleft)
|
||||||
|
{
|
||||||
|
if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3];
|
||||||
|
surf();
|
||||||
|
outleft = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out[--outleft];
|
||||||
|
}
|
||||||
|
|
||||||
u64 rand64(void)
|
u64 rand64(void)
|
||||||
{
|
{
|
||||||
static int outleft = 0;
|
static int outleft = 0;
|
||||||
@@ -214,7 +226,14 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
|||||||
{
|
{
|
||||||
unsigned char *cp = p++;
|
unsigned char *cp = p++;
|
||||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||||
*p++ = *sval;
|
{
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||||
|
*p++ = (*(++sval))-1;
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
*p++ = *sval;
|
||||||
|
}
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
@@ -262,6 +281,7 @@ int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
|
|||||||
#ifdef HAVE_IPV6
|
#ifdef HAVE_IPV6
|
||||||
if (s1->sa.sa_family == AF_INET6 &&
|
if (s1->sa.sa_family == AF_INET6 &&
|
||||||
s1->in6.sin6_port == s2->in6.sin6_port &&
|
s1->in6.sin6_port == s2->in6.sin6_port &&
|
||||||
|
s1->in6.sin6_scope_id == s2->in6.sin6_scope_id &&
|
||||||
IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
|
IN6_ARE_ADDR_EQUAL(&s1->in6.sin6_addr, &s2->in6.sin6_addr))
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
@@ -319,6 +339,19 @@ time_t dnsmasq_time(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int netmask_length(struct in_addr mask)
|
||||||
|
{
|
||||||
|
int zero_count = 0;
|
||||||
|
|
||||||
|
while (0x0 == (mask.s_addr & 0x1) && zero_count < 32)
|
||||||
|
{
|
||||||
|
mask.s_addr >>= 1;
|
||||||
|
zero_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 32 - zero_count;
|
||||||
|
}
|
||||||
|
|
||||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
||||||
{
|
{
|
||||||
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||||
@@ -482,66 +515,6 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
static int charval(char c)
|
|
||||||
{
|
|
||||||
if (c >= 'A' && c <= 'Z')
|
|
||||||
return c - 'A';
|
|
||||||
|
|
||||||
if (c >= 'a' && c <= 'z')
|
|
||||||
return c - 'a' + 26;
|
|
||||||
|
|
||||||
if (c >= '0' && c <= '9')
|
|
||||||
return c - '0' + 52;
|
|
||||||
|
|
||||||
if (c == '+')
|
|
||||||
return 62;
|
|
||||||
|
|
||||||
if (c == '/')
|
|
||||||
return 63;
|
|
||||||
|
|
||||||
if (c == '=')
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parse_base64(char *in, char *out)
|
|
||||||
{
|
|
||||||
char *p = out;
|
|
||||||
int i, val[4];
|
|
||||||
|
|
||||||
while (*in)
|
|
||||||
{
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
while (*in == ' ')
|
|
||||||
in++;
|
|
||||||
if (*in == 0)
|
|
||||||
return -1;
|
|
||||||
if ((val[i] = charval(*in++)) == -2)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*in == ' ')
|
|
||||||
in++;
|
|
||||||
|
|
||||||
if (val[1] == -1)
|
|
||||||
return -1; /* too much padding */
|
|
||||||
|
|
||||||
*p++ = (val[0] << 2) | (val[1] >> 4);
|
|
||||||
|
|
||||||
if (val[2] != -1)
|
|
||||||
*p++ = (val[1] << 4) | ( val[2] >> 2);
|
|
||||||
|
|
||||||
if (val[3] != -1)
|
|
||||||
*p++ = (val[2] << 6) | val[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
return p - out;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* return 0 for no match, or (no matched octets) + 1 */
|
/* return 0 for no match, or (no matched octets) + 1 */
|
||||||
int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
|
int memcmp_masked(unsigned char *a, unsigned char *b, int len, unsigned int mask)
|
||||||
{
|
{
|
||||||
@@ -597,27 +570,41 @@ char *print_mac(char *buff, unsigned char *mac, int len)
|
|||||||
return buff;
|
return buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bump_maxfd(int fd, int *max)
|
/* rc is return from sendto and friends.
|
||||||
|
Return 1 if we should retry.
|
||||||
|
Set errno to zero if we succeeded. */
|
||||||
|
int retry_send(ssize_t rc)
|
||||||
{
|
{
|
||||||
if (fd > *max)
|
static int retries = 0;
|
||||||
*max = fd;
|
struct timespec waiter;
|
||||||
}
|
|
||||||
|
if (rc != -1)
|
||||||
|
{
|
||||||
|
retries = 0;
|
||||||
|
errno = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Linux kernels can return EAGAIN in perpetuity when calling
|
||||||
|
sendmsg() and the relevant interface has gone. Here we loop
|
||||||
|
retrying in EAGAIN for 1 second max, to avoid this hanging
|
||||||
|
dnsmasq. */
|
||||||
|
|
||||||
int retry_send(void)
|
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||||
{
|
|
||||||
struct timespec waiter;
|
|
||||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
|
||||||
{
|
{
|
||||||
waiter.tv_sec = 0;
|
waiter.tv_sec = 0;
|
||||||
waiter.tv_nsec = 10000;
|
waiter.tv_nsec = 10000;
|
||||||
nanosleep(&waiter, NULL);
|
nanosleep(&waiter, NULL);
|
||||||
return 1;
|
if (retries++ < 1000)
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno == EINTR)
|
retries = 0;
|
||||||
return 1;
|
|
||||||
|
if (errno == EINTR)
|
||||||
return 0;
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int read_write(int fd, unsigned char *packet, int size, int rw)
|
int read_write(int fd, unsigned char *packet, int size, int rw)
|
||||||
@@ -626,22 +613,21 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
|
|||||||
|
|
||||||
for (done = 0; done < size; done += n)
|
for (done = 0; done < size; done += n)
|
||||||
{
|
{
|
||||||
retry:
|
do {
|
||||||
if (rw)
|
if (rw)
|
||||||
n = read(fd, &packet[done], (size_t)(size - done));
|
n = read(fd, &packet[done], (size_t)(size - done));
|
||||||
else
|
else
|
||||||
n = write(fd, &packet[done], (size_t)(size - done));
|
n = write(fd, &packet[done], (size_t)(size - done));
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
} while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
|
||||||
|
|
||||||
if (n == 0)
|
if (errno != 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (n == -1)
|
|
||||||
{
|
|
||||||
if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
|
|
||||||
goto retry;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -662,3 +648,22 @@ int wildcard_match(const char* wildcard, const char* match)
|
|||||||
|
|
||||||
return *wildcard == *match;
|
return *wildcard == *match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The same but comparing a maximum of NUM characters, like strncmp. */
|
||||||
|
int wildcard_matchn(const char* wildcard, const char* match, int num)
|
||||||
|
{
|
||||||
|
while (*wildcard && *match && num)
|
||||||
|
{
|
||||||
|
if (*wildcard == '*')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (*wildcard != *match)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
++wildcard;
|
||||||
|
++match;
|
||||||
|
--num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (!num) || (*wildcard == *match);
|
||||||
|
}
|
||||||
+6
-5
@@ -1,8 +1,9 @@
|
|||||||
# The root DNSSEC trust anchors, valid as at 30/01/2014
|
# The root DNSSEC trust anchor, valid as at 30/01/2014
|
||||||
|
|
||||||
|
# Note that this is a DS record (ie a hash of the root Zone Signing Key)
|
||||||
|
# If was downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||||
|
|
||||||
|
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
|
||||||
|
|
||||||
|
|
||||||
dnskey=.,257,8,AwEAAagAIKlVZrpC6Ia7gEzahOR+9W29euxhJhVVLOyQbSEW0O8gcCjF FVQUTf6v58fLjwBd0YI0EzrAcQqBGCzh/RStIoO8g0NfnfL2MTJRkxoX bfDaUeVPQuYEhg37NZWAJQ9VnMVDxP/VHL496M/QZxkjf5/Efucp2gaD X6RS6CXpoY68LsvPVjR0ZSwzz1apAzvN9dlzEheX7ICJBBtuA6G3LQpz W5hOA2hzCTMjJPJ8LbqF6dsV6DoBQzgul0sGIcGOYl7OyQdXfZ57relS Qageu+ipAdTTJ25AsRTAoub8ONGcLmqrAmRLKBP1dfwhYB4N7knNnulq QxA+Uk1ihz0=
|
|
||||||
dnskey=.,256,8,AwEAAb8sU6pbYMWRbkRnEuEZw9NSir707TkOcF+UL1XiK4NDJOvXRyX1 95Am5dQ7bRnnuySZ3daf37vvjUUhuIWUAQ4stht8nJfYxVQXDYjSpGH5 I6Hf/0CZEoNP6cNvrQ7AFmKkmv00xWExKQjbvnRPI4bqpMwtHVzn6Wyb BZ6kuqED
|
|
||||||
dnskey=.,256,8,AwEAAYRU41/8smgAvuSojEP4jaj5Yll7WPaUKpYvnz2pnX2VIvRn4jsy Jns80bloenG6X9ebJVy2CFtZQLKHP8DcKmIFotdgs2HolyocY1am/+33 4RtzusM2ojkhjn1FRGtuSE9s2TSz1ISv0yVnFyu+EP/ZkiWnDfWeVrJI SEWBEr4V
|
|
||||||
|
|
||||||
|
|
||||||
Reference in new issue
Block a user