mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-04 13:48:30 +00:00
Compare commits
338
Commits
v2.78
...
v2.83test1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45903b7776 | ||
|
|
f60fea1fb0 | ||
|
|
4d85e409cd | ||
|
|
2bd02d2f59 | ||
|
|
7e194a0a7d | ||
|
|
9beb4d9ea2 | ||
|
|
ab5ebe9507 | ||
|
|
837e8f4eb5 | ||
|
|
e2cb655958 | ||
|
|
8270648da1 | ||
|
|
619000a3c5 | ||
|
|
1c1b925052 | ||
|
|
49bdf1ead9 | ||
|
|
60a3ae19c5 | ||
|
|
951a22165c | ||
|
|
51cdd1a227 | ||
|
|
66adee85be | ||
|
|
4890bcdea2 | ||
|
|
8baf583a3f | ||
|
|
913fa15fb1 | ||
|
|
00fe2f49e0 | ||
|
|
ec2067df75 | ||
|
|
7ddb99d251 | ||
|
|
ba26d3485b | ||
|
|
081a1c4014 | ||
|
|
532246fc9e | ||
|
|
8caf3d7c6c | ||
|
|
d162bee356 | ||
|
|
b43585c34b | ||
|
|
3f60ecd6f0 | ||
|
|
0506a5ed4e | ||
|
|
e7ee1aa093 | ||
|
|
63ed917ad9 | ||
|
|
63e21bdea3 | ||
|
|
1627d577af | ||
|
|
b837c4528d | ||
|
|
46bdfe691a | ||
|
|
dded78b233 | ||
|
|
b594e8defa | ||
|
|
70c50efd0d | ||
|
|
ea3c60ac07 | ||
|
|
fc19399a1f | ||
|
|
980b14f174 | ||
|
|
1df73fe831 | ||
|
|
c125c1dfee | ||
|
|
e39c484ebd | ||
|
|
977a5a2df1 | ||
|
|
02df0007c8 | ||
|
|
b2ed691eb3 | ||
|
|
8d6d5730c9 | ||
|
|
48755ebf09 | ||
|
|
0541a1adf7 | ||
|
|
c992ed4bef | ||
|
|
92025a4113 | ||
|
|
a7d19e917a | ||
|
|
ec1cc455d6 | ||
|
|
ee64582a1f | ||
|
|
425e2405aa | ||
|
|
dea53e6658 | ||
|
|
a9b022ab65 | ||
|
|
c65b77c87f | ||
|
|
8e3a5cba8b | ||
|
|
29ae308398 | ||
|
|
306888afb3 | ||
|
|
f064188032 | ||
|
|
77476580ed | ||
|
|
52ec783613 | ||
|
|
137286e9ba | ||
|
|
79aba0f10a | ||
|
|
515ba97595 | ||
|
|
cd672933c9 | ||
|
|
d9603ef781 | ||
|
|
e40d8bef3b | ||
|
|
ab53883c94 | ||
|
|
6c1e9ac14b | ||
|
|
c7a44c4690 | ||
|
|
2ac4cf0146 | ||
|
|
a914d0aa6a | ||
|
|
91102ad5eb | ||
|
|
378fa56888 | ||
|
|
2a8710ac2f | ||
|
|
66f62650c3 | ||
|
|
18a6bdd541 | ||
|
|
9e732445cf | ||
|
|
7d04e17444 | ||
|
|
34d41475e7 | ||
|
|
0c211c4ec5 | ||
|
|
bf23c8a394 | ||
|
|
f73f7397d7 | ||
|
|
5cee7c2702 | ||
|
|
1aef66bb34 | ||
|
|
4a1c21d62c | ||
|
|
c117675ebd | ||
|
|
6ebdc95754 | ||
|
|
55a22b88c2 | ||
|
|
1fd56c0e33 | ||
|
|
376cb97685 | ||
|
|
84449bf41c | ||
|
|
456a319775 | ||
|
|
157d8cfd6a | ||
|
|
1292e1a557 | ||
|
|
122997da54 | ||
|
|
b59a5c2567 | ||
|
|
2a20cc6da8 | ||
|
|
936bd82755 | ||
|
|
13a58f9590 | ||
|
|
19b0e3bf21 | ||
|
|
203ce0a081 | ||
|
|
e3002bf1a6 | ||
|
|
04db1483d1 | ||
|
|
6fe436a448 | ||
|
|
e710c34469 | ||
|
|
defd6b1d85 | ||
|
|
90d7c6b97d | ||
|
|
e24abf28a2 | ||
|
|
69a0477b74 | ||
|
|
ae7a3b9d2e | ||
|
|
d9f882bea2 | ||
|
|
fef2f1c75e | ||
|
|
5a91334985 | ||
|
|
e198fe833a | ||
|
|
248efe8410 | ||
|
|
dc6a57ffb8 | ||
|
|
240da59f73 | ||
|
|
5a56233f53 | ||
|
|
225accd235 | ||
|
|
ab73a746a0 | ||
|
|
69bc94779c | ||
|
|
3052ce208a | ||
|
|
18e17665fd | ||
|
|
05299fdd5a | ||
|
|
7ef55691a2 | ||
|
|
7509f94fc4 | ||
|
|
343b7b4ad0 | ||
|
|
a2b8220f4e | ||
|
|
5c464ef62e | ||
|
|
5fc639cf9a | ||
|
|
7673013d23 | ||
|
|
c6cc455dd1 | ||
|
|
1da81f7e23 | ||
|
|
ae5b7e04a1 | ||
|
|
305ffb5ef0 | ||
|
|
608aa9fcfc | ||
|
|
c61c7bb225 | ||
|
|
5ed82ae5f2 | ||
|
|
6799320edb | ||
|
|
c406fd60be | ||
|
|
5d514f22a9 | ||
|
|
a066aac332 | ||
|
|
8bd28a87a2 | ||
|
|
065e5bb0b1 | ||
|
|
df6636bff6 | ||
|
|
162e5e0062 | ||
|
|
4219adeeef | ||
|
|
28cfe36e1e | ||
|
|
d2d4990743 | ||
|
|
18eac67c0a | ||
|
|
f8c77edbdf | ||
|
|
4bf62f616b | ||
|
|
9c0d445ef4 | ||
|
|
2896e2485e | ||
|
|
a90f09db4c | ||
|
|
5b99eae59d | ||
|
|
2daca52b80 | ||
|
|
2c594732eb | ||
|
|
cc921df9ce | ||
|
|
ab194ed7ca | ||
|
|
65a01b71bb | ||
|
|
bde46476ee | ||
|
|
e7bfd556c0 | ||
|
|
b683cf37f9 | ||
|
|
3becf468ba | ||
|
|
137e9f878f | ||
|
|
07e25da5bf | ||
|
|
d46ee724fc | ||
|
|
59e470381f | ||
|
|
48d12f14c9 | ||
|
|
122392e0b3 | ||
|
|
3a5a84cdd1 | ||
|
|
24b87607c1 | ||
|
|
6f7812d97b | ||
|
|
cbb5b17ad8 | ||
|
|
cf5984367b | ||
|
|
ee8750451b | ||
|
|
a220545c42 | ||
|
|
a799ca0c63 | ||
|
|
91421cb757 | ||
|
|
53792c934c | ||
|
|
df071825f2 | ||
|
|
e1791f36ea | ||
|
|
0fdf3c1f61 | ||
|
|
ee1df06aab | ||
|
|
1e87eba424 | ||
|
|
08933475ab | ||
|
|
7cbf497da4 | ||
|
|
3a610a007f | ||
|
|
48b090cb5c | ||
|
|
4139298d28 | ||
|
|
51cc10fa54 | ||
|
|
ea6cc33804 | ||
|
|
ad03967ee4 | ||
|
|
f4fd07d303 | ||
|
|
e3c08a34a7 | ||
|
|
118011fe2b | ||
|
|
af3bd07355 | ||
|
|
d68209978a | ||
|
|
47b45b2967 | ||
|
|
2b38e3823b | ||
|
|
282eab7952 | ||
|
|
c346f61535 | ||
|
|
03212e533b | ||
|
|
da8b6517de | ||
|
|
c5db8f93ec | ||
|
|
974a6d087a | ||
|
|
b758b67c37 | ||
|
|
9bafdc62b7 | ||
|
|
97f876b64c | ||
|
|
cbfbd173c4 | ||
|
|
b6f926fbef | ||
|
|
c822620967 | ||
|
|
397c0502e2 | ||
|
|
1682d15a74 | ||
|
|
dd33e98da0 | ||
|
|
c16d966ad3 | ||
|
|
1dfed16071 | ||
|
|
6f835ed6c8 | ||
|
|
9d6fd1727e | ||
|
|
8c1b6a5fd7 | ||
|
|
8dcdb33be9 | ||
|
|
aba8bbb6e3 | ||
|
|
caf4d571e6 | ||
|
|
3b6eb197a8 | ||
|
|
f3e57877ed | ||
|
|
c851c695db | ||
|
|
a3bd7e73d3 | ||
|
|
ab5ceaf74a | ||
|
|
1f2f69d4f6 | ||
|
|
f361b39dea | ||
|
|
eb1fe15ca8 | ||
|
|
45d8a2435e | ||
|
|
706d84fd10 | ||
|
|
a997ca0da0 | ||
|
|
9268b5d677 | ||
|
|
51e4eeeb04 | ||
|
|
05ff659a3c | ||
|
|
db0f488ea8 | ||
|
|
7dcca6c622 | ||
|
|
090856c7e6 | ||
|
|
cc5cc8f1e0 | ||
|
|
c488b68e75 | ||
|
|
1f1873aadd | ||
|
|
0a496f059c | ||
|
|
e27825b0ef | ||
|
|
1f60a18ea1 | ||
|
|
a0088e8364 | ||
|
|
34e26e14c5 | ||
|
|
6b17335209 | ||
|
|
07ed585c38 | ||
|
|
0669ee7a69 | ||
|
|
f84e674d8a | ||
|
|
7f0084316a | ||
|
|
a6918530ce | ||
|
|
4e72fec660 | ||
|
|
4441cf762c | ||
|
|
e83915d10d | ||
|
|
6d37924b86 | ||
|
|
f3d7974e86 | ||
|
|
734d53176f | ||
|
|
9a7be47614 | ||
|
|
26e27d0015 | ||
|
|
94b6878821 | ||
|
|
8b96552f0d | ||
|
|
ae290659de | ||
|
|
6b2b564ac3 | ||
|
|
4f7bb57e97 | ||
|
|
56f0623930 | ||
|
|
f3223fbff6 | ||
|
|
4c4f4c2649 | ||
|
|
773af304ea | ||
|
|
4cc944b0d6 | ||
|
|
87e00feb01 | ||
|
|
e7a4af8903 | ||
|
|
2d69d6146d | ||
|
|
30e4a9441e | ||
|
|
232a8f3569 | ||
|
|
1721453d51 | ||
|
|
499d8dde2b | ||
|
|
6f1cbfd000 | ||
|
|
55ecde7f1b | ||
|
|
6b54d69a85 | ||
|
|
246a31cd73 | ||
|
|
83e4b73596 | ||
|
|
6340ca734f | ||
|
|
baf553db0c | ||
|
|
486bcd5a7b | ||
|
|
be9a74d2f8 | ||
|
|
ffcbc0f011 | ||
|
|
a969ba6e2a | ||
|
|
f1781728af | ||
|
|
cd7df612b1 | ||
|
|
c1a4e257a3 | ||
|
|
4fe6744a22 | ||
|
|
3bd4c47f31 | ||
|
|
98196c4931 | ||
|
|
22cd860124 | ||
|
|
3c973ad92d | ||
|
|
faaf306a63 | ||
|
|
c7e6aea81b | ||
|
|
e541245987 | ||
|
|
84a01bee10 | ||
|
|
d1ced3ae38 | ||
|
|
a6cee69af4 | ||
|
|
0039920ab6 | ||
|
|
39d8550a80 | ||
|
|
ef3d137a64 | ||
|
|
8c707e1e37 | ||
|
|
373e917389 | ||
|
|
74f0f9a042 | ||
|
|
ed6bdb0967 | ||
|
|
c88af046b7 | ||
|
|
ae0187d454 | ||
|
|
0c50e3ddc8 | ||
|
|
075366ad6e | ||
|
|
8e8b2d6f63 | ||
|
|
087eb76140 | ||
|
|
ebedcbaeb8 | ||
|
|
0954a977c9 | ||
|
|
b77efc1948 | ||
|
|
3b0cb34710 | ||
|
|
aa6f832d61 | ||
|
|
ad9c6f06c5 | ||
|
|
a6004d7f17 | ||
|
|
c366717e66 | ||
|
|
22dee512f3 | ||
|
|
6fd5d79e73 | ||
|
|
9d6918d32c | ||
|
|
a49c5c2265 | ||
|
|
30858e3b9b |
No files matched your search
+2
-3
@@ -7,9 +7,8 @@ src/.copts_*
|
|||||||
contrib/lease-tools/dhcp_lease_time
|
contrib/lease-tools/dhcp_lease_time
|
||||||
contrib/lease-tools/dhcp_release
|
contrib/lease-tools/dhcp_release
|
||||||
contrib/lease-tools/dhcp_release6
|
contrib/lease-tools/dhcp_release6
|
||||||
debian/base/
|
|
||||||
debian/daemon/
|
|
||||||
debian/files
|
debian/files
|
||||||
debian/substvars
|
debian/substvars
|
||||||
debian/utils-substvars
|
debian/utils-substvars
|
||||||
debian/utils/
|
debian/trees/
|
||||||
|
debian/build/
|
||||||
@@ -1,3 +1,258 @@
|
|||||||
|
version 2.83
|
||||||
|
Fix a remote buffer overflow problem in the DNSSEC code. Any
|
||||||
|
dnsmasq with DNSSEC compiled in and enabled is vulnerable to this,
|
||||||
|
referenced by CERT VU#434904.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.82
|
||||||
|
Improve behaviour in the face of network interfaces which come
|
||||||
|
and go and change index. Thanks to Petr Mensik for the patch.
|
||||||
|
|
||||||
|
Convert hard startup failure on NETLINK_NO_ENOBUFS under qemu-user
|
||||||
|
to a warning.
|
||||||
|
|
||||||
|
Allow IPv6 addresses ofthe form [::ffff:1.2.3.4] in --dhcp-option.
|
||||||
|
|
||||||
|
Fix crash under heavy TCP connection load introduced in 2.81.
|
||||||
|
Thanks to Frank for good work chasing this down.
|
||||||
|
|
||||||
|
Change default lease time for DHCPv6 to one day.
|
||||||
|
|
||||||
|
Alter calculation of preferred and valid times in router
|
||||||
|
advertisements, so that these do not have a floor applied
|
||||||
|
of the lease time in the dhcp-range if this is not explicitly
|
||||||
|
specified and is merely the default.
|
||||||
|
Thanks to Martin-Éric Racine for suggestions on this.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.81
|
||||||
|
Improve cache behaviour for TCP connections. For ease of
|
||||||
|
implementation, dnsmasq has always forked a new process to handle
|
||||||
|
each incoming TCP connection. A side-effect of this is that
|
||||||
|
any DNS queries answered from TCP connections are not cached:
|
||||||
|
when TCP connections were rare, this was not a problem.
|
||||||
|
With the coming of DNSSEC, it is now the case that some
|
||||||
|
DNSSEC queries have answers which spill to TCP, and if,
|
||||||
|
for instance, this applies to the keys for the root, then
|
||||||
|
those never get cached, and performance is very bad.
|
||||||
|
This fix passes cache entries back from the TCP child process to
|
||||||
|
the main server process, and fixes the problem.
|
||||||
|
|
||||||
|
Remove the NO_FORK compile-time option, and support for uclinux.
|
||||||
|
In an era where everything has an MMU, this looks like
|
||||||
|
an anachronism, and it adds to (Ok, multiplies!) the
|
||||||
|
combinatorial explosion of compile-time options. Thanks to
|
||||||
|
Kevin Darbyshire-Bryant for the patch.
|
||||||
|
|
||||||
|
Fix line-counting when reading /etc/hosts and friends; for
|
||||||
|
correct error messages. Thanks to Christian Rosentreter
|
||||||
|
for reporting this.
|
||||||
|
|
||||||
|
Fix bug in DNS non-terminal code, added in 2.80, which could
|
||||||
|
sometimes cause a NODATA rather than an NXDOMAIN reply.
|
||||||
|
Thanks to Norman Rasmussen, Sven Mueller and Maciej Żenczykowski
|
||||||
|
for spotting and diagnosing the bug and providing patches.
|
||||||
|
|
||||||
|
Support TCP-fastopen (RFC-7413) on both incoming and
|
||||||
|
outgoing TCP connections, if supported and enabled in the OS.
|
||||||
|
|
||||||
|
Improve kernel-capability manipulation code under Linux. Dnsmasq
|
||||||
|
now fails early if a required capability is not available, and
|
||||||
|
tries not to request capabilities not required by its
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
Add --shared-network config. This enables allocation of addresses
|
||||||
|
by the DHCP server in subnets where the server (or relay) does not
|
||||||
|
have an interface on the network in that subnet. Many thanks to
|
||||||
|
kamp.de for sponsoring this feature.
|
||||||
|
|
||||||
|
Fix broken contrib/lease_tools/dhcp_lease_time.c. A packet
|
||||||
|
validation check got borked in commit 2b38e382 and release 2.80.
|
||||||
|
Thanks to Tomasz Szajner for spotting this.
|
||||||
|
|
||||||
|
Fix compilation against nettle version 3.5 and later.
|
||||||
|
|
||||||
|
Fix spurious DNSSEC validation failures when the auth section
|
||||||
|
of a reply contains unsigned RRs from a signed zone,
|
||||||
|
with the exception that NSEC and NSEC3 RRs must always be signed.
|
||||||
|
Thanks to Tore Anderson for spotting and diagnosing the bug.
|
||||||
|
|
||||||
|
Add --dhcp-ignore-clid. This disables reading of DHCP client
|
||||||
|
identifier option (option 61), so clients are only identified by
|
||||||
|
MAC addresses.
|
||||||
|
|
||||||
|
Fix a bug which stopped --dhcp-name-match from working when a hostname
|
||||||
|
is supplied in --dhcp-host. Thanks to James Feeney for spotting this.
|
||||||
|
|
||||||
|
Fix bug which caused very rarely caused zero-length DHCPv6 packets.
|
||||||
|
Thanks to Dereck Higgins for spotting this.
|
||||||
|
|
||||||
|
Add --tftp-single-port option.
|
||||||
|
|
||||||
|
Enhance --conf-dir to load files in a deterministic order. Thanks to
|
||||||
|
Evgenii Seliavka for the suggestion and initial patch.
|
||||||
|
|
||||||
|
In the router advert code, handle case where we have two
|
||||||
|
different interfaces on the same IPv6 net, and we are doing
|
||||||
|
RA/DHCP service on only one of them. Thanks to NIIBE Yutaka
|
||||||
|
for spotting this case and making the initial patch.
|
||||||
|
|
||||||
|
Support prefixed ranges of ipv6 addresses in dhcp-host.
|
||||||
|
This eases problems chain-netbooting, where each link in the
|
||||||
|
chain requests an address using a different UID. With a single
|
||||||
|
address, only one gets the "static" address, but with this
|
||||||
|
fix, enough addresses can be reserved for all the stages of the
|
||||||
|
boot. Many thanks to Harald Jensås for his work on this idea and
|
||||||
|
earlier patches.
|
||||||
|
|
||||||
|
Add filtering by tag of --dhcp-host directives. Based on a patch
|
||||||
|
by Harald Jensås.
|
||||||
|
|
||||||
|
Allow empty server spec in --rev-server, to match --server.
|
||||||
|
|
||||||
|
Remove DSA signature verification from DNSSEC, as specified in
|
||||||
|
RFC 8624. Thanks to Loganaden Velvindron for the original patch.
|
||||||
|
|
||||||
|
Add --script-on-renewal option.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.80
|
||||||
|
Add support for RFC 4039 DHCP rapid commit. Thanks to Ashram Method
|
||||||
|
for the initial patch and motivation.
|
||||||
|
|
||||||
|
Alter the default for dnssec-check-unsigned. Versions of
|
||||||
|
dnsmasq prior to 2.80 defaulted to not checking unsigned
|
||||||
|
replies, and used --dnssec-check-unsigned to switch
|
||||||
|
this on. Such configurations will continue to work as before,
|
||||||
|
but those which used the default of no checking will need to be
|
||||||
|
altered to explicitly select no checking. The new default is
|
||||||
|
because switching off checking for unsigned replies is
|
||||||
|
inherently dangerous. Not only does it open the possiblity of forged
|
||||||
|
replies, but it allows everything to appear to be working even
|
||||||
|
when the upstream namesevers do not support DNSSEC, and in this
|
||||||
|
case no DNSSEC validation at all is occuring.
|
||||||
|
|
||||||
|
Fix DHCP broken-ness when --no-ping AND --dhcp-sequential-ip
|
||||||
|
are set. Thanks to Daniel Miess for help with this.
|
||||||
|
|
||||||
|
Add a facilty to store DNS packets sent/recieved in a
|
||||||
|
pcap-format file for later debugging. The file location
|
||||||
|
is given by the --dumpfile option, and a bitmap controlling
|
||||||
|
which packets should be dumped is given by the --dumpmask
|
||||||
|
option.
|
||||||
|
|
||||||
|
Handle the case of both standard and constructed dhcp-ranges on the
|
||||||
|
same interface better. We don't now contruct a dhcp-range if there's
|
||||||
|
already one specified. This allows the specified interface to
|
||||||
|
have different parameters and avoids advertising the same
|
||||||
|
prefix twice. Thanks to Luis Marsano for spotting this case.
|
||||||
|
|
||||||
|
Allow zone transfer in authoritative mode if auth-peer is specified,
|
||||||
|
even if auth-sec-servers is not. Thanks to Raphaël Halimi for
|
||||||
|
the suggestion.
|
||||||
|
|
||||||
|
Fix bug which sometimes caused dnsmasq to wrongly return answers
|
||||||
|
without DNSSEC RRs to queries with the do-bit set, but only when
|
||||||
|
DNSSEC validation was not enabled.
|
||||||
|
Thanks to Petr Menšík for spotting this.
|
||||||
|
|
||||||
|
Fix missing fatal errors with some malformed options
|
||||||
|
(server, local, address, rebind-domain-ok, ipset, alias).
|
||||||
|
Thanks to Eugene Lozovoy for spotting the problem.
|
||||||
|
|
||||||
|
Fix crash on startup with a --synth-domain which has no prefix.
|
||||||
|
Introduced in 2.79. Thanks to Andreas Engel for the bug report.
|
||||||
|
|
||||||
|
Fix missing EDNS0 section in some replies generated by local
|
||||||
|
DNS configuration which confused systemd-resolvd. Thanks to
|
||||||
|
Steve Dodd for characterising the problem.
|
||||||
|
|
||||||
|
Add --dhcp-name-match config option.
|
||||||
|
|
||||||
|
Add --caa-record config option.
|
||||||
|
|
||||||
|
Implement --address=/example.com/# as (more efficient) syntactic
|
||||||
|
sugar for --address=/example.com/0.0.0.0 and
|
||||||
|
--address=/example.com/::
|
||||||
|
Returning null addresses is a useful technique for ad-blocking.
|
||||||
|
Thanks to Peter Russell for the suggestion.
|
||||||
|
|
||||||
|
Change anti cache-snooping behaviour with queries with the
|
||||||
|
recursion-desired bit unset. Instead to returning SERVFAIL, we
|
||||||
|
now always forward, and never answer from the cache. This
|
||||||
|
allows "dig +trace" command to work.
|
||||||
|
|
||||||
|
Include in the example config file a formulation which
|
||||||
|
stops DHCP clients from claiming the DNS name "wpad".
|
||||||
|
This is a fix for the CERT Vulnerability VU#598349.
|
||||||
|
|
||||||
|
|
||||||
|
version 2.79
|
||||||
|
Fix parsing of CNAME arguments, which are confused by extra spaces.
|
||||||
|
Thanks to Diego Aguirre for spotting the bug.
|
||||||
|
|
||||||
|
Where available, use IP_UNICAST_IF or IPV6_UNICAST_IF to bind
|
||||||
|
upstream servers to an interface, rather than SO_BINDTODEVICE.
|
||||||
|
Thanks to Beniamino Galvani for the patch.
|
||||||
|
|
||||||
|
Always return a SERVFAIL answer to DNS queries without the
|
||||||
|
recursion desired bit set, UNLESS acting as an authoritative
|
||||||
|
DNS server. This avoids a potential route to cache snooping.
|
||||||
|
|
||||||
|
Add support for Ed25519 signatures in DNSSEC validation.
|
||||||
|
|
||||||
|
No longer support RSA/MD5 signatures in DNSSEC validation,
|
||||||
|
since these are not secure. This behaviour is mandated in
|
||||||
|
RFC-6944.
|
||||||
|
|
||||||
|
Fix incorrect error exit code from dhcp_release6 utility.
|
||||||
|
Thanks Gaudenz Steinlin for the bug report.
|
||||||
|
|
||||||
|
Use SIGINT (instead of overloading SIGHUP) to turn on DNSSEC
|
||||||
|
time validation when --dnssec-no-timecheck is in use.
|
||||||
|
Note that this is an incompatible change from earlier releases.
|
||||||
|
|
||||||
|
Allow more than one --bridge-interface option to refer to an
|
||||||
|
interface, so that we can use
|
||||||
|
--bridge-interface=int1,alias1
|
||||||
|
--bridge-interface=int1,alias2
|
||||||
|
as an alternative to
|
||||||
|
--bridge-interface=int1,alias1,alias2
|
||||||
|
Thanks to Neil Jerram for work on this.
|
||||||
|
|
||||||
|
Fix for DNSSEC with wildcard-derived NSEC records.
|
||||||
|
It's OK for NSEC records to be expanded from wildcards,
|
||||||
|
but in that case, the proof of non-existence is only valid
|
||||||
|
starting at the wildcard name, *.<domain> NOT the name expanded
|
||||||
|
from the wildcard. Without this check it's possible for an
|
||||||
|
attacker to craft an NSEC which wrongly proves non-existence.
|
||||||
|
Thanks to Ralph Dolmans for finding this, and co-ordinating
|
||||||
|
the vulnerability tracking and fix release.
|
||||||
|
CVE-2017-15107 applies.
|
||||||
|
|
||||||
|
Remove special handling of A-for-A DNS queries. These
|
||||||
|
are no longer a significant problem in the global DNS.
|
||||||
|
http://cs.northwestern.edu/~ychen/Papers/DNS_ToN15.pdf
|
||||||
|
Thanks to Mattias Hellström for the initial patch.
|
||||||
|
|
||||||
|
Fix failure to delete dynamically created dhcp options
|
||||||
|
from files in -dhcp-optsdir directories. Thanks to
|
||||||
|
Lindgren Fredrik for the bug report.
|
||||||
|
|
||||||
|
Add to --synth-domain the ability to create names using
|
||||||
|
sequential numbers, as well as encodings of IP addresses.
|
||||||
|
For instance,
|
||||||
|
--synth-domain=thekelleys.org.uk,192.168.0.50,192.168.0.70,internal-*
|
||||||
|
creates 21 domain names of the form
|
||||||
|
internal-4.thekelleys.org.uk over the address range given, with
|
||||||
|
internal-0.thekelleys.org.uk being 192.168.0.50 and
|
||||||
|
internal-20.thekelleys.org.uk being 192.168.0.70
|
||||||
|
Thanks to Andy Hawkins for the suggestion.
|
||||||
|
|
||||||
|
Tidy up Crypto code, removing workarounds for ancient
|
||||||
|
versions of libnettle. We now require libnettle 3.
|
||||||
|
|
||||||
|
|
||||||
version 2.78
|
version 2.78
|
||||||
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
Fix logic of appending ".<layer>" to PXE basename. Thanks to Chris
|
||||||
Novakovic for the patch.
|
Novakovic for the patch.
|
||||||
@@ -1526,7 +1781,7 @@ version 2.56
|
|||||||
|
|
||||||
By default, setting an IPv4 address for a domain but not
|
By default, setting an IPv4 address for a domain but not
|
||||||
an IPv6 address causes dnsmasq to return
|
an IPv6 address causes dnsmasq to return
|
||||||
an NODATA reply for IPv6 (or vice-versa). So
|
a NODATA reply for IPv6 (or vice-versa). So
|
||||||
--address=/google.com/1.2.3.4 stops IPv6 queries for
|
--address=/google.com/1.2.3.4 stops IPv6 queries for
|
||||||
*google.com from being forwarded. Make it possible to
|
*google.com from being forwarded. Make it possible to
|
||||||
override this behaviour by defining the semantics if the
|
override this behaviour by defining the semantics if the
|
||||||
@@ -2032,13 +2287,13 @@ version 2.47
|
|||||||
|
|
||||||
Support arbitrarily encapsulated DHCP options, suggestion
|
Support arbitrarily encapsulated DHCP options, suggestion
|
||||||
and initial patch from Samium Gromoff. This is useful for
|
and initial patch from Samium Gromoff. This is useful for
|
||||||
(eg) gPXE, which expect all its private options to be
|
(eg) iPXE, which expect all its private options to be
|
||||||
encapsulated inside a single option 175. So, eg,
|
encapsulated inside a single option 175. So, eg,
|
||||||
|
|
||||||
dhcp-option = encap:175, 190, "iscsi-client0"
|
dhcp-option = encap:175, 190, "iscsi-client0"
|
||||||
dhcp-option = encap:175, 191, "iscsi-client0-secret"
|
dhcp-option = encap:175, 191, "iscsi-client0-secret"
|
||||||
|
|
||||||
will provide iSCSI parameters to gPXE.
|
will provide iSCSI parameters to iPXE.
|
||||||
|
|
||||||
Enhance --dhcp-match to allow testing of the contents of a
|
Enhance --dhcp-match to allow testing of the contents of a
|
||||||
client-sent option, as well as its presence. This
|
client-sent option, as well as its presence. This
|
||||||
|
|||||||
+4
-4
@@ -1010,7 +1010,7 @@ release 2.9
|
|||||||
but to the address of another interface were ignored
|
but to the address of another interface were ignored
|
||||||
unless the loopback interface was explicitly configured.
|
unless the loopback interface was explicitly configured.
|
||||||
2) on OpenBSD failure to configure one interface now
|
2) on OpenBSD failure to configure one interface now
|
||||||
causes a fatal error on startup rather than an huge
|
causes a fatal error on startup rather than a huge
|
||||||
stream of log messages. Thanks to Erik Jan Tromp for
|
stream of log messages. Thanks to Erik Jan Tromp for
|
||||||
finding that bug.
|
finding that bug.
|
||||||
|
|
||||||
@@ -2067,7 +2067,7 @@ version 2.36
|
|||||||
kernel. Thanks to Philip Wall for the bug report.
|
kernel. Thanks to Philip Wall for the bug report.
|
||||||
|
|
||||||
Added --dhcp-bridge option, but only to the FreeBSD
|
Added --dhcp-bridge option, but only to the FreeBSD
|
||||||
build. This fixes an oddity with a a particular bridged
|
build. This fixes an oddity with a particular bridged
|
||||||
network configuration on FreeBSD. Thanks to Luigi Rizzo
|
network configuration on FreeBSD. Thanks to Luigi Rizzo
|
||||||
for the patch.
|
for the patch.
|
||||||
|
|
||||||
@@ -2273,7 +2273,7 @@ version 2.40
|
|||||||
this.
|
this.
|
||||||
|
|
||||||
Use client-id as hash-seed for DHCP address allocation
|
Use client-id as hash-seed for DHCP address allocation
|
||||||
with Firewire and InfiniBand, as these don't supply an MAC
|
with Firewire and InfiniBand, as these don't supply a MAC
|
||||||
address.
|
address.
|
||||||
|
|
||||||
Tweaked TFTP file-open code to make it behave sensibly
|
Tweaked TFTP file-open code to make it behave sensibly
|
||||||
@@ -2433,7 +2433,7 @@ version 2.41
|
|||||||
|
|
||||||
Add --dhcp-match flag, to check for arbitrary options in
|
Add --dhcp-match flag, to check for arbitrary options in
|
||||||
DHCP messages from clients. This enables use of dnsmasq
|
DHCP messages from clients. This enables use of dnsmasq
|
||||||
with gPXE. Thanks to Rance Hall for the suggestion.
|
with iPXE. Thanks to Rance Hall for the suggestion.
|
||||||
|
|
||||||
Added --dhcp-broadcast, to force broadcast replies to DHCP
|
Added --dhcp-broadcast, to force broadcast replies to DHCP
|
||||||
clients which need them but are too dumb or too old to
|
clients which need them but are too dumb or too old to
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ A: The high ports that dnsmasq opens are for replies from the upstream
|
|||||||
from port 53 the replies would be _to_ port 53 and get blocked.
|
from port 53 the replies would be _to_ port 53 and get blocked.
|
||||||
|
|
||||||
This is not a security hole since dnsmasq will only accept replies to that
|
This is not a security hole since dnsmasq will only accept replies to that
|
||||||
port: queries are dropped. The replies must be to oustanding queries
|
port: queries are dropped. The replies must be to outstanding queries
|
||||||
which dnsmasq has forwarded, otherwise they are dropped too.
|
which dnsmasq has forwarded, otherwise they are dropped too.
|
||||||
|
|
||||||
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
|
Addendum: dnsmasq now has the option "query-port" (-Q), which allows
|
||||||
@@ -297,7 +297,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
|
|||||||
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
by dnsmasq when in --bind-interfaces mode. In wildcard or bind-dynamic
|
||||||
mode, such interfaces are handled normally.
|
mode, such interfaces are handled normally.
|
||||||
|
|
||||||
A --interface specification for a non-existent interface is a fatal
|
An --interface specification for a non-existent interface is a fatal
|
||||||
error at start-up when in --bind-interfaces mode, by just generates a
|
error at start-up when in --bind-interfaces mode, by just generates a
|
||||||
warning in wildcard or bind-dynamic mode.
|
warning in wildcard or bind-dynamic mode.
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ A: Yes, new releases of dnsmasq are always announced through
|
|||||||
|
|
||||||
Q: What does the dhcp-authoritative option do?
|
Q: What does the dhcp-authoritative option do?
|
||||||
|
|
||||||
A: The DHCP spec says that when a DHCP server recieves a renewal request
|
A: The DHCP spec says that when a DHCP server receives a renewal request
|
||||||
from a client it has no knowledge of, it should just ignore it.
|
from a client it has no knowledge of, it should just ignore it.
|
||||||
This is because it's supported to have more than one DHCP server
|
This is because it's supported to have more than one DHCP server
|
||||||
on a network, and another DHCP server may be dealing with the client.
|
on a network, and another DHCP server may be dealing with the client.
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ top?=$(CURDIR)
|
|||||||
|
|
||||||
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
|
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
|
||||||
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
||||||
|
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS "" --copy -lubox -lubus`
|
||||||
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
||||||
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
||||||
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
|
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
|
||||||
@@ -76,16 +77,16 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.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 tables.o loop.o inotify.o \
|
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||||
poll.o rrfilter.o edns0.o arp.o
|
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o metrics.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 metrics.h
|
||||||
|
|
||||||
all : $(BUILDDIR)
|
all : $(BUILDDIR)
|
||||||
@cd $(BUILDDIR) && $(MAKE) \
|
@cd $(BUILDDIR) && $(MAKE) \
|
||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||||
-f $(top)/Makefile dnsmasq
|
-f $(top)/Makefile dnsmasq
|
||||||
|
|
||||||
mostly_clean :
|
mostly_clean :
|
||||||
@@ -100,7 +101,8 @@ clean : mostly_clean
|
|||||||
install : all install-common
|
install : all install-common
|
||||||
|
|
||||||
install-common :
|
install-common :
|
||||||
$(INSTALL) -d $(DESTDIR)$(BINDIR) -d $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -d $(DESTDIR)$(BINDIR)
|
||||||
|
$(INSTALL) -d $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
|
$(INSTALL) -m 644 $(MAN)/dnsmasq.8 $(DESTDIR)$(MANDIR)/man8
|
||||||
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
|
$(INSTALL) -m 755 $(BUILDDIR)/dnsmasq $(DESTDIR)$(BINDIR)
|
||||||
|
|
||||||
@@ -109,7 +111,7 @@ all-i18n : $(BUILDDIR)
|
|||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||||
-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; \
|
||||||
|
|||||||
+2
-1
@@ -10,7 +10,8 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.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 tables.c \
|
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||||
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c
|
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
|
||||||
|
crypto.c dump.c ubus.c
|
||||||
|
|
||||||
LOCAL_MODULE := dnsmasq
|
LOCAL_MODULE := dnsmasq
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -11,23 +11,25 @@ in=`cat`
|
|||||||
|
|
||||||
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
|
||||||
# Nasty, nasty, in --copy, arg 2 is another config to search for, use with NO_GMP
|
# Nasty, nasty, in --copy, arg 2 (if non-empty) is another config to search for, used with NO_GMP
|
||||||
if [ $op = "--copy" ]; then
|
if [ $op = "--copy" ]; then
|
||||||
if grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
|
if [ -z "$pkg" ]; then
|
||||||
echo $in | grep $pkg >/dev/null 2>&1; then
|
pkg="$*"
|
||||||
|
elif grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
|
||||||
|
echo $in | grep $pkg >/dev/null 2>&1; then
|
||||||
pkg=""
|
pkg=""
|
||||||
else
|
else
|
||||||
pkg="$*"
|
pkg="$*"
|
||||||
fi
|
fi
|
||||||
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||||
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||||
pkg=`$pkg --static $op $*`
|
pkg=`$pkg --static $op $*`
|
||||||
else
|
else
|
||||||
pkg=`$pkg $op $*`
|
pkg=`$pkg $op $*`
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
|
||||||
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
|
||||||
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
|
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
|
||||||
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
|
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
|||||||
if (p >= end - 2)
|
if (p >= end - 2)
|
||||||
return NULL; /* malformed packet */
|
return NULL; /* malformed packet */
|
||||||
opt_len = option_len(p);
|
opt_len = option_len(p);
|
||||||
if (p >= end - (2 + opt_len))
|
if (end - p < (2 + opt_len))
|
||||||
return NULL; /* malformed packet */
|
return NULL; /* malformed packet */
|
||||||
if (*p == opt && opt_len >= minsize)
|
if (*p == opt && opt_len >= minsize)
|
||||||
return p;
|
return p;
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ static int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask)
|
|||||||
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
return (a.s_addr & mask.s_addr) == (b.s_addr & mask.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index)
|
static struct in_addr find_interface(struct in_addr client, int fd, unsigned int index, int ifrfd, struct ifreq *ifr)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
struct nlmsghdr *h;
|
struct nlmsghdr *h;
|
||||||
@@ -218,7 +218,17 @@ static struct in_addr find_interface(struct in_addr client, int fd, unsigned int
|
|||||||
|
|
||||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||||
if (h->nlmsg_type == NLMSG_DONE)
|
if (h->nlmsg_type == NLMSG_DONE)
|
||||||
exit(0);
|
{
|
||||||
|
/* No match found, return first address as src/dhcp.c code does */
|
||||||
|
ifr->ifr_addr.sa_family = AF_INET;
|
||||||
|
if (ioctl(ifrfd, SIOCGIFADDR, ifr) != -1)
|
||||||
|
return ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf(stderr, "error: local IPv4 address not found\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR)
|
||||||
{
|
{
|
||||||
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
struct ifaddrmsg *ifa = NLMSG_DATA(h);
|
||||||
@@ -270,7 +280,8 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
||||||
a DHCP server */
|
a DHCP server */
|
||||||
strcpy(ifr.ifr_name, argv[1]);
|
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
||||||
|
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||||
{
|
{
|
||||||
perror("cannot setup interface");
|
perror("cannot setup interface");
|
||||||
@@ -284,7 +295,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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]), fd, &ifr);
|
||||||
|
|
||||||
memset(&packet, 0, sizeof(packet));
|
memset(&packet, 0, sizeof(packet));
|
||||||
|
|
||||||
|
|||||||
+325
-271
@@ -46,7 +46,8 @@ typedef unsigned char u8;
|
|||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
typedef unsigned int u32;
|
typedef unsigned int u32;
|
||||||
|
|
||||||
enum DHCP6_TYPES{
|
enum DHCP6_TYPES
|
||||||
|
{
|
||||||
SOLICIT = 1,
|
SOLICIT = 1,
|
||||||
ADVERTISE = 2,
|
ADVERTISE = 2,
|
||||||
REQUEST = 3,
|
REQUEST = 3,
|
||||||
@@ -61,8 +62,10 @@ enum DHCP6_TYPES{
|
|||||||
RELAY_FORW = 12,
|
RELAY_FORW = 12,
|
||||||
RELAY_REPL = 13
|
RELAY_REPL = 13
|
||||||
|
|
||||||
};
|
};
|
||||||
enum DHCP6_OPTIONS{
|
|
||||||
|
enum DHCP6_OPTIONS
|
||||||
|
{
|
||||||
CLIENTID = 1,
|
CLIENTID = 1,
|
||||||
SERVERID = 2,
|
SERVERID = 2,
|
||||||
IA_NA = 3,
|
IA_NA = 3,
|
||||||
@@ -82,25 +85,27 @@ enum DHCP6_OPTIONS{
|
|||||||
INTERFACE_ID = 18,
|
INTERFACE_ID = 18,
|
||||||
RECONF_MSG = 19,
|
RECONF_MSG = 19,
|
||||||
RECONF_ACCEPT = 20,
|
RECONF_ACCEPT = 20,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DHCP6_STATUSES{
|
enum DHCP6_STATUSES
|
||||||
|
{
|
||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
UNSPEC_FAIL = 1,
|
UNSPEC_FAIL = 1,
|
||||||
NOADDR_AVAIL=2,
|
NOADDR_AVAIL=2,
|
||||||
NO_BINDING = 3,
|
NO_BINDING = 3,
|
||||||
NOT_ON_LINK = 4,
|
NOT_ON_LINK = 4,
|
||||||
USE_MULTICAST =5
|
USE_MULTICAST =5
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
{"ip", required_argument, 0, 'a'},
|
{"ip", required_argument, 0, 'a' },
|
||||||
{"server-id", required_argument, 0, 's'},
|
{"server-id", required_argument, 0, 's' },
|
||||||
{"client-id", required_argument, 0, 'c'},
|
{"client-id", required_argument, 0, 'c' },
|
||||||
{"iface", required_argument, 0, 'n'},
|
{"iface", required_argument, 0, 'n' },
|
||||||
{"iaid", required_argument, 0, 'i'},
|
{"iaid", required_argument, 0, 'i' },
|
||||||
{"dry-run", no_argument, 0, 'd'},
|
{"dry-run", no_argument, 0, 'd' },
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h' },
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
const short DHCP6_CLIENT_PORT = 546;
|
const short DHCP6_CLIENT_PORT = 546;
|
||||||
@@ -108,207 +113,230 @@ const short DHCP6_SERVER_PORT = 547;
|
|||||||
|
|
||||||
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
||||||
|
|
||||||
struct dhcp6_option{
|
struct dhcp6_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
char value[1024];
|
char value[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp6_iaaddr_option{
|
struct dhcp6_iaaddr_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
struct in6_addr ip;
|
struct in6_addr ip;
|
||||||
uint32_t preferred_lifetime;
|
uint32_t preferred_lifetime;
|
||||||
uint32_t valid_lifetime;
|
uint32_t valid_lifetime;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp6_iana_option{
|
struct dhcp6_iana_option {
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint32_t iaid;
|
uint32_t iaid;
|
||||||
uint32_t t1;
|
uint32_t t1;
|
||||||
uint32_t t2;
|
uint32_t t2;
|
||||||
char options[1024];
|
char options[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct dhcp6_packet{
|
struct dhcp6_packet {
|
||||||
size_t len;
|
size_t len;
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
|
};
|
||||||
} ;
|
|
||||||
|
|
||||||
size_t pack_duid(const char* str, char* dst){
|
size_t pack_duid(const char* str, char* dst)
|
||||||
|
{
|
||||||
char* tmp = strdup(str);
|
char* tmp = strdup(str);
|
||||||
char* tmp_to_free = tmp;
|
char* tmp_to_free = tmp;
|
||||||
char *ptr;
|
char *ptr;
|
||||||
uint8_t write_pos = 0;
|
uint8_t write_pos = 0;
|
||||||
while ((ptr = strtok (tmp, ":"))) {
|
while ((ptr = strtok (tmp, ":")))
|
||||||
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
{
|
||||||
write_pos += 1;
|
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
||||||
tmp = NULL;
|
write_pos += 1;
|
||||||
|
tmp = NULL;
|
||||||
}
|
}
|
||||||
free(tmp_to_free);
|
|
||||||
return write_pos;
|
free(tmp_to_free);
|
||||||
|
return write_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_option create_client_id_option(const char* duid){
|
struct dhcp6_option create_client_id_option(const char* duid)
|
||||||
struct dhcp6_option option;
|
{
|
||||||
option.type = htons(CLIENTID);
|
struct dhcp6_option option;
|
||||||
bzero(option.value, sizeof(option.value));
|
option.type = htons(CLIENTID);
|
||||||
option.len = htons(pack_duid(duid, option.value));
|
bzero(option.value, sizeof(option.value));
|
||||||
return option;
|
option.len = htons(pack_duid(duid, option.value));
|
||||||
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_option create_server_id_option(const char* duid){
|
struct dhcp6_option create_server_id_option(const char* duid)
|
||||||
struct dhcp6_option option;
|
{
|
||||||
option.type = htons(SERVERID);
|
struct dhcp6_option option;
|
||||||
bzero(option.value, sizeof(option.value));
|
option.type = htons(SERVERID);
|
||||||
option.len = htons(pack_duid(duid, option.value));
|
bzero(option.value, sizeof(option.value));
|
||||||
return option;
|
option.len = htons(pack_duid(duid, option.value));
|
||||||
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){
|
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip)
|
||||||
struct dhcp6_iaaddr_option result;
|
{
|
||||||
result.type =htons(IAADDR);
|
struct dhcp6_iaaddr_option result;
|
||||||
/* no suboptions needed here, so length is 24 */
|
result.type =htons(IAADDR);
|
||||||
result.len = htons(24);
|
/* no suboptions needed here, so length is 24 */
|
||||||
result.preferred_lifetime = 0;
|
result.len = htons(24);
|
||||||
result.valid_lifetime = 0;
|
result.preferred_lifetime = 0;
|
||||||
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
result.valid_lifetime = 0;
|
||||||
if (s <= 0) {
|
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
||||||
if (s == 0)
|
if (s <= 0) {
|
||||||
fprintf(stderr, "Not in presentation format");
|
if (s == 0)
|
||||||
else
|
fprintf(stderr, "Not in presentation format");
|
||||||
perror("inet_pton");
|
else
|
||||||
exit(EXIT_FAILURE);
|
perror("inet_pton");
|
||||||
}
|
exit(EXIT_FAILURE);
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
|
return result;
|
||||||
struct dhcp6_iana_option result;
|
|
||||||
result.type = htons(IA_NA);
|
|
||||||
result.iaid = htonl(atoi(iaid));
|
|
||||||
result.t1 = 0;
|
|
||||||
result.t2 = 0;
|
|
||||||
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
|
||||||
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id){
|
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr)
|
||||||
struct dhcp6_packet result;
|
{
|
||||||
bzero(result.buf, sizeof(result.buf));
|
struct dhcp6_iana_option result;
|
||||||
/* message_type */
|
result.type = htons(IA_NA);
|
||||||
result.buf[0] = RELEASE;
|
result.iaid = htonl(atoi(iaid));
|
||||||
/* tx_id */
|
result.t1 = 0;
|
||||||
bzero(result.buf+1, 3);
|
result.t2 = 0;
|
||||||
|
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||||
struct dhcp6_option client_option = create_client_id_option(client_id);
|
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||||
struct dhcp6_option server_option = create_server_id_option(server_id);
|
return result;
|
||||||
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
|
|
||||||
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
|
|
||||||
int offset = 4;
|
|
||||||
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
|
|
||||||
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
|
|
||||||
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
|
|
||||||
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
|
|
||||||
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
|
|
||||||
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
|
|
||||||
result.len = offset;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t parse_iana_suboption(char* buf, size_t len){
|
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id)
|
||||||
size_t current_pos = 0;
|
{
|
||||||
char option_value[1024];
|
struct dhcp6_packet result;
|
||||||
while (current_pos < len) {
|
bzero(result.buf, sizeof(result.buf));
|
||||||
uint16_t option_type, option_len;
|
/* message_type */
|
||||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
result.buf[0] = RELEASE;
|
||||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
/* tx_id */
|
||||||
option_type = ntohs(option_type);
|
bzero(result.buf+1, 3);
|
||||||
option_len = ntohs(option_len);
|
|
||||||
current_pos += 2 * sizeof(uint16_t);
|
struct dhcp6_option client_option = create_client_id_option(client_id);
|
||||||
if (option_type == STATUS_CODE){
|
struct dhcp6_option server_option = create_server_id_option(server_id);
|
||||||
uint16_t status;
|
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
|
||||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
|
||||||
status = ntohs(status);
|
int offset = 4;
|
||||||
if (status != SUCCESS){
|
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
|
||||||
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
|
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
|
||||||
option_value[option_len-sizeof(uint16_t)] ='\0';
|
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
|
||||||
fprintf(stderr, "Error: %s\n", option_value);
|
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
|
||||||
|
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
|
||||||
|
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
|
||||||
|
result.len = offset;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t parse_iana_suboption(char* buf, size_t len)
|
||||||
|
{
|
||||||
|
size_t current_pos = 0;
|
||||||
|
char option_value[1024];
|
||||||
|
while (current_pos < len)
|
||||||
|
{
|
||||||
|
uint16_t option_type, option_len;
|
||||||
|
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||||
|
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
|
option_type = ntohs(option_type);
|
||||||
|
option_len = ntohs(option_len);
|
||||||
|
current_pos += 2 * sizeof(uint16_t);
|
||||||
|
if (option_type == STATUS_CODE)
|
||||||
|
{
|
||||||
|
uint16_t status;
|
||||||
|
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||||
|
status = ntohs(status);
|
||||||
|
if (status != SUCCESS)
|
||||||
|
{
|
||||||
|
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
|
||||||
|
option_value[option_len-sizeof(uint16_t)] ='\0';
|
||||||
|
fprintf(stderr, "Error: %s\n", option_value);
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -2;
|
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t parse_packet(char* buf, size_t len){
|
int16_t parse_packet(char* buf, size_t len)
|
||||||
uint8_t type = buf[0];
|
{
|
||||||
/*skipping tx id. you need it, uncomment following line
|
int16_t ret = -1;
|
||||||
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
uint8_t type = buf[0];
|
||||||
*/
|
/*skipping tx id. you need it, uncomment following line
|
||||||
size_t current_pos = 4;
|
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
||||||
if (type != REPLY ){
|
*/
|
||||||
return NOT_REPLY_CODE;
|
size_t current_pos = 4;
|
||||||
}
|
if (type != REPLY )
|
||||||
char option_value[1024];
|
return NOT_REPLY_CODE;
|
||||||
while (current_pos < len) {
|
|
||||||
uint16_t option_type, option_len;
|
char option_value[1024];
|
||||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
while (current_pos < len)
|
||||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
{
|
||||||
option_type = ntohs(option_type);
|
uint16_t option_type, option_len;
|
||||||
option_len = ntohs(option_len);
|
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||||
current_pos += 2 * sizeof(uint16_t);
|
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||||
if (option_type == STATUS_CODE){
|
option_type = ntohs(option_type);
|
||||||
uint16_t status;
|
option_len = ntohs(option_len);
|
||||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
current_pos += 2 * sizeof(uint16_t);
|
||||||
status = ntohs(status);
|
if (option_type == STATUS_CODE)
|
||||||
if (status != SUCCESS){
|
{
|
||||||
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
|
uint16_t status;
|
||||||
fprintf(stderr, "Error: %d %s\n", status, option_value);
|
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||||
return status;
|
status = ntohs(status);
|
||||||
}
|
if (status != SUCCESS)
|
||||||
|
{
|
||||||
|
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
|
||||||
|
fprintf(stderr, "Error: %d %s\n", status, option_value);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Got success status, return that if there's no specific error in an IA_NA. */
|
||||||
|
ret = SUCCESS;
|
||||||
}
|
}
|
||||||
if (option_type == IA_NA ){
|
|
||||||
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
|
|
||||||
if (result){
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_pos += option_len;
|
|
||||||
|
|
||||||
|
if (option_type == IA_NA )
|
||||||
|
{
|
||||||
|
uint16_t result = parse_iana_suboption(buf + current_pos +24, option_len -24);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_pos += option_len;
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usage(const char* arg, FILE* stream){
|
void usage(const char* arg, FILE* stream)
|
||||||
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
|
{
|
||||||
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
const char* usage_string ="--ip IPv6 --iface IFACE --server-id SERVER_ID --client-id CLIENT_ID --iaid IAID [--dry-run] | --help";
|
||||||
|
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_release_packet(const char* iface, struct dhcp6_packet* packet){
|
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||||
|
{
|
||||||
struct sockaddr_in6 server_addr, client_addr;
|
struct sockaddr_in6 server_addr, client_addr;
|
||||||
char response[1400];
|
char response[1400];
|
||||||
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if (sock < 0) {
|
if (sock < 0)
|
||||||
perror("creating socket");
|
{
|
||||||
return -1;
|
perror("creating socket");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
|
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1)
|
||||||
|
{
|
||||||
perror("SO_BINDTODEVICE");
|
perror("SO_BINDTODEVICE");
|
||||||
close(sock);
|
close(sock);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&server_addr, 0, sizeof(server_addr));
|
memset(&server_addr, 0, sizeof(server_addr));
|
||||||
server_addr.sin6_family = AF_INET6;
|
server_addr.sin6_family = AF_INET6;
|
||||||
client_addr.sin6_family = AF_INET6;
|
client_addr.sin6_family = AF_INET6;
|
||||||
@@ -320,126 +348,152 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet){
|
|||||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
||||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||||
int16_t recv_size = 0;
|
int16_t recv_size = 0;
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++)
|
||||||
if (sendto(sock, packet->buf, packet->len, 0,
|
{
|
||||||
(struct sockaddr *)&server_addr,
|
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
||||||
sizeof(server_addr)) < 0) {
|
{
|
||||||
perror("sendto failed");
|
perror("sendto failed");
|
||||||
exit(4);
|
exit(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||||
if (recv_size == -1){
|
if (recv_size == -1)
|
||||||
if (errno == EAGAIN){
|
{
|
||||||
sleep(1);
|
if (errno == EAGAIN)
|
||||||
continue;
|
{
|
||||||
}else {
|
sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
perror("recvfrom");
|
perror("recvfrom");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t result = parse_packet(response, recv_size);
|
int16_t result = parse_packet(response, recv_size);
|
||||||
if (result == NOT_REPLY_CODE){
|
if (result == NOT_REPLY_CODE)
|
||||||
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close(sock);
|
||||||
fprintf(stderr, "Response timed out\n");
|
fprintf(stderr, "Response timed out\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char * const argv[]) {
|
int main(int argc, char * const argv[])
|
||||||
const char* UNINITIALIZED = "";
|
{
|
||||||
const char* iface = UNINITIALIZED;
|
const char* UNINITIALIZED = "";
|
||||||
const char* ip = UNINITIALIZED;
|
const char* iface = UNINITIALIZED;
|
||||||
const char* client_id = UNINITIALIZED;
|
const char* ip = UNINITIALIZED;
|
||||||
const char* server_id = UNINITIALIZED;
|
const char* client_id = UNINITIALIZED;
|
||||||
const char* iaid = UNINITIALIZED;
|
const char* server_id = UNINITIALIZED;
|
||||||
int dry_run = 0;
|
const char* iaid = UNINITIALIZED;
|
||||||
while (1) {
|
int dry_run = 0;
|
||||||
int option_index = 0;
|
while (1)
|
||||||
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
{
|
||||||
if (c == -1){
|
int option_index = 0;
|
||||||
break;
|
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
||||||
}
|
if (c == -1)
|
||||||
switch(c){
|
break;
|
||||||
case 0:
|
|
||||||
if (longopts[option_index].flag !=0){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf ("option %s", longopts[option_index].name);
|
|
||||||
if (optarg)
|
|
||||||
printf (" with arg %s", optarg);
|
|
||||||
printf ("\n");
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
iaid = optarg;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
iface = optarg;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
ip = optarg;
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
client_id = optarg;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
dry_run = 1;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
server_id = optarg;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
usage(argv[0], stdout);
|
|
||||||
return 0;
|
|
||||||
case '?':
|
|
||||||
usage(argv[0], stderr);
|
|
||||||
return -1;
|
|
||||||
default:
|
|
||||||
abort();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
if (longopts[option_index].flag !=0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
printf ("option %s", longopts[option_index].name);
|
||||||
|
if (optarg)
|
||||||
|
printf (" with arg %s", optarg);
|
||||||
|
printf ("\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
iaid = optarg;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
iface = optarg;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
ip = optarg;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
client_id = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
dry_run = 1;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
server_id = optarg;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0], stdout);
|
||||||
|
return 0;
|
||||||
|
case '?':
|
||||||
|
usage(argv[0], stderr);
|
||||||
|
return -1;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (iaid == UNINITIALIZED){
|
|
||||||
fprintf(stderr, "Missing required iaid parameter\n");
|
if (iaid == UNINITIALIZED)
|
||||||
usage(argv[0], stderr);
|
{
|
||||||
return -1;
|
fprintf(stderr, "Missing required iaid parameter\n");
|
||||||
|
usage(argv[0], stderr);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
if (server_id == UNINITIALIZED){
|
|
||||||
|
if (server_id == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required server-id parameter\n");
|
fprintf(stderr, "Missing required server-id parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (client_id == UNINITIALIZED){
|
|
||||||
|
if (client_id == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required client-id parameter\n");
|
fprintf(stderr, "Missing required client-id parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ip == UNINITIALIZED){
|
|
||||||
|
if (ip == UNINITIALIZED)
|
||||||
|
{
|
||||||
fprintf(stderr, "Missing required ip parameter\n");
|
fprintf(stderr, "Missing required ip parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (iface == UNINITIALIZED){
|
|
||||||
fprintf(stderr, "Missing required iface parameter\n");
|
if (iface == UNINITIALIZED)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Missing required iface parameter\n");
|
||||||
usage(argv[0], stderr);
|
usage(argv[0], stderr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
||||||
if (dry_run){
|
|
||||||
|
if (dry_run)
|
||||||
|
{
|
||||||
uint16_t i;
|
uint16_t i;
|
||||||
for(i=0;i<packet.len;i++){
|
|
||||||
printf("%hhx", packet.buf[i]);
|
for(i=0; i<packet.len; i++)
|
||||||
}
|
printf("%hhx", packet.buf[i]);
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return send_release_packet(iface, &packet);
|
return send_release_packet(iface, &packet);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
|
STATUS_FILE="/tmp/dnsmasq-ip-mac.status"
|
||||||
|
|
||||||
# Script for dnsmasq lease-change hook.
|
# Script for dnsmasq lease-change hook.
|
||||||
# Maintains the above file with a IP address/MAC address pairs,
|
# Maintains the above file with an IP address/MAC address pairs,
|
||||||
# one lease per line. Works with IPv4 and IPv6 leases, file is
|
# one lease per line. Works with IPv4 and IPv6 leases, file is
|
||||||
# atomically updated, so no races for users of the data.
|
# atomically updated, so no races for users of the data.
|
||||||
|
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ log-facility=/var/log/dnsmasq.log
|
|||||||
|
|
||||||
in the dnsmasq configuration.
|
in the dnsmasq configuration.
|
||||||
|
|
||||||
The script runs on debian (with ash installed) and on busybox.
|
The script runs on debian (with dash installed) and on busybox.
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/bin/ash
|
#!/bin/dash
|
||||||
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
|
# $Id: reverse_replace.sh 18 2015-03-01 16:12:35Z jo $
|
||||||
#
|
#
|
||||||
# Usage e.g.: netstat -n -4 | reverse_replace.sh
|
# Usage e.g.: netstat -n -4 | reverse_replace.sh
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||||
|
After=network.target
|
||||||
|
Before=network-online.target nss-lookup.target
|
||||||
|
Wants=nss-lookup.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=dbus
|
Type=dbus
|
||||||
|
|||||||
@@ -243,6 +243,10 @@ IPv4 or IPv6 address of the lease to remove.
|
|||||||
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
||||||
configured DHCP lease script will be run with the "del" action.
|
configured DHCP lease script will be run with the "del" action.
|
||||||
|
|
||||||
|
GetMetrics
|
||||||
|
----------
|
||||||
|
|
||||||
|
Returns an array with various metrics for DNS and DHCP.
|
||||||
|
|
||||||
|
|
||||||
2. SIGNALS
|
2. SIGNALS
|
||||||
|
|||||||
Vendored
+78
-2
@@ -1,8 +1,84 @@
|
|||||||
|
dnsmasq (2.82-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 22:22:41 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.81-4) unstable; urgency=low
|
||||||
|
|
||||||
|
* Remove runit support when building for Ubuntu. (closes: #960401)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 21:52:44 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.81-3) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fixes to control file for bug 958100
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 19 Apr 2020 21:44:12 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.81-2) unstable; urgency=low
|
||||||
|
|
||||||
|
* Fix FTBFS on kFreeBSD. (closes: #958100)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 18 Apr 2020 18:34:15 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.81-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream.
|
||||||
|
* Fix nodocs/nodoc confusion in rules. (closes: #922758)
|
||||||
|
* Add Vcs-* fields to control. (closes: #922422)
|
||||||
|
* Add systemd support for multiple daemon instances. (closes: #914305)
|
||||||
|
* Add note explaining that ENABLED is SYSV-init only. (closes: #914755)
|
||||||
|
* Replace ash with dash in contrib/reverse-dns. (closes: #920224)
|
||||||
|
* Move to libidn2. (closes: #932695)
|
||||||
|
* Fix RA problem with two interfaces on same net, but RA service on
|
||||||
|
only one of the interfaces. (closes: #949565)
|
||||||
|
* Fix breakage of dig +trace. (closes: #942363)
|
||||||
|
* Fix build faliure with newer Nettle libraries. (closes: #940985)
|
||||||
|
* Support runscript init-system (closes: #929884)
|
||||||
|
* Security fix for CVE-2019-14834 (closes: #948373)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 8 Apr 2020 17:33:15 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.80-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream. (closes: #837602) (closes: #794640) (closes: #794636)
|
||||||
|
* Close old bugs, long agp fixed. (closes: #802845) (closes: #754299)
|
||||||
|
* Provide usr/lib/tmpfiles.d/dnsmasq.conf. (closes: #872396)
|
||||||
|
* Run restorecon on /run/dnsmasq for SE Linux. (closes: #872397)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 17 Sep 2018 23:11:25 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.79-1) unstable; urgency=low
|
||||||
|
|
||||||
|
* New upstream. (closes: #888200)
|
||||||
|
* Fix trust-anchor regex in init script. (closes: #884347)
|
||||||
|
* Fix exit code for dhcp_release6 (closes: #883596)
|
||||||
|
* Add project homepage to control file. (closes: #887764)
|
||||||
|
* New binary package dnsmasq-base-lua, includes Lua support.
|
||||||
|
* Remove hardwired shlibs dependency for libnettle 3.3 and
|
||||||
|
fix code to avoid ABI breakage as long as compiled against
|
||||||
|
libnettle 3.4 or later. (closes: #891315)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 16 Feb 2018 19:54:22 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.78-3) unstable; urgency=high
|
||||||
|
|
||||||
|
* Make failure of pidfile chown a warning. (closes: #889857)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 8 Feb 2018 21:26:30 +0000
|
||||||
|
|
||||||
|
dnsmasq (2.78-2) unstable; urgency=high
|
||||||
|
|
||||||
|
* Change ownership of pid file, to keep systemd happy. (closes: #889336)
|
||||||
|
|
||||||
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 6 Feb 2018 17:21:30 +0000
|
||||||
|
|
||||||
dnsmasq (2.78-1) unstable; urgency=high
|
dnsmasq (2.78-1) unstable; urgency=high
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
Security fixes for CVE-2017-13704 (closes: #877102)
|
Security fixes for CVE-2017-13704 (closes: #877102)
|
||||||
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
||||||
|
|
||||||
@@ -19,7 +95,7 @@ dnsmasq (2.77-1) unstable; urgency=low
|
|||||||
includes port=0 to disable DNS.
|
includes port=0 to disable DNS.
|
||||||
* Handle gratuitous format change in /usr/share/dns/root.ds
|
* Handle gratuitous format change in /usr/share/dns/root.ds
|
||||||
(closes: #858506) (closes: #860064)
|
(closes: #858506) (closes: #860064)
|
||||||
* Add lsb-base dependancy.
|
* Add lsb-base dependency.
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
|
||||||
|
|
||||||
|
|||||||
Vendored
+28
-6
@@ -2,17 +2,23 @@ Source: dnsmasq
|
|||||||
Section: net
|
Section: net
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||||
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
|
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
|
||||||
|
liblua5.2-dev, dh-runit, debhelper-compat (= 10),
|
||||||
|
pkg-config
|
||||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||||
|
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
||||||
|
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
|
||||||
|
Vcs-Browser: http://thekelleys.org.uk/gitweb/?p=dnsmasq.git
|
||||||
Standards-Version: 3.9.8
|
Standards-Version: 3.9.8
|
||||||
|
|
||||||
Package: dnsmasq
|
Package: dnsmasq
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
|
Depends: netbase, dnsmasq-base,
|
||||||
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
|
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6), ${misc:Depends}
|
||||||
Suggests: resolvconf
|
Suggests: resolvconf
|
||||||
Conflicts: resolvconf (<<1.15)
|
Breaks: ${runit:Breaks}
|
||||||
|
Conflicts: resolvconf (<<1.15), ${runit:Conflicts}
|
||||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP
|
Dnsmasq is a lightweight, easy to configure, DNS forwarder and DHCP
|
||||||
server. It is designed to provide DNS and optionally, DHCP, to a
|
server. It is designed to provide DNS and optionally, DHCP, to a
|
||||||
@@ -27,13 +33,29 @@ Package: dnsmasq-base
|
|||||||
Architecture: any
|
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~), dnsmasq-base
|
||||||
Recommends: dns-root-data
|
Recommends: dns-root-data
|
||||||
|
Provides: dnsmasq-base
|
||||||
|
Conflicts: dnsmasq-base-lua
|
||||||
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
|
||||||
that, install the dnsmasq package.
|
that, install the dnsmasq package.
|
||||||
|
|
||||||
|
Package: dnsmasq-base-lua
|
||||||
|
Architecture: any
|
||||||
|
Depends: adduser, ${shlibs:Depends}
|
||||||
|
Breaks: dnsmasq (<< 2.63-1~)
|
||||||
|
Replaces: dnsmasq (<< 2.63-1~), dnsmasq-base
|
||||||
|
Recommends: dns-root-data
|
||||||
|
Provides: dnsmasq-base
|
||||||
|
Conflicts: dnsmasq-base
|
||||||
|
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||||
|
This package contains the dnsmasq executable and documentation, but
|
||||||
|
not the infrastructure required to run it as a system daemon. For
|
||||||
|
that, install the dnsmasq package. This package is an alternative
|
||||||
|
to dnsmasq-base which includes the LUA interpreter.
|
||||||
|
|
||||||
Package: dnsmasq-utils
|
Package: dnsmasq-utils
|
||||||
Architecture: linux-any
|
Architecture: linux-any
|
||||||
Depends: ${shlibs:Depends}
|
Depends: ${shlibs:Depends}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
dnsmasq is Copyright (c) 2000-2016 Simon Kelley
|
dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||||
|
|
||||||
|
|||||||
Vendored
+16
-7
@@ -1,13 +1,15 @@
|
|||||||
# This file has five functions:
|
# This file has six functions:
|
||||||
# 1) to completely disable starting dnsmasq,
|
# 1) to completely disable starting this dnsmasq instance
|
||||||
# 2) to set DOMAIN_SUFFIX by running `dnsdomainname`
|
# 2) to set DOMAIN_SUFFIX by running `dnsdomainname`
|
||||||
# 3) to select an alternative config file
|
# 3) to select an alternative config file
|
||||||
# by setting DNSMASQ_OPTS to --conf-file=<file>
|
# by setting DNSMASQ_OPTS to --conf-file=<file>
|
||||||
# 4) to tell dnsmasq to read the files in /etc/dnsmasq.d for
|
# 4) to tell dnsmasq to read the files in /etc/dnsmasq.d for
|
||||||
# more configuration variables.
|
# more configuration variables.
|
||||||
# 5) to stop the resolvconf package from controlling dnsmasq's
|
# 5) to stop the resolvconf package from controlling dnsmasq's
|
||||||
# idea of which upstream nameservers to use.
|
# idea of which upstream nameservers to use.
|
||||||
# For upgraders from very old versions, all the shell variables set
|
# 6) to avoid using this dnsmasq instance as the system's default resolver
|
||||||
|
# by setting DNSMASQ_EXCEPT="lo"
|
||||||
|
# For upgraders from very old versions, all the shell variables set
|
||||||
# here in previous versions are still honored by the init script
|
# here in previous versions are still honored by the init script
|
||||||
# so if you just keep your old version of this file nothing will break.
|
# so if you just keep your old version of this file nothing will break.
|
||||||
|
|
||||||
@@ -15,6 +17,8 @@
|
|||||||
#DNSMASQ_OPTS="--conf-file=/etc/dnsmasq.alt"
|
#DNSMASQ_OPTS="--conf-file=/etc/dnsmasq.alt"
|
||||||
|
|
||||||
# Whether or not to run the dnsmasq daemon; set to 0 to disable.
|
# Whether or not to run the dnsmasq daemon; set to 0 to disable.
|
||||||
|
# Note that this is only valid when using SYSV init. For systemd,
|
||||||
|
# use "systemctl disable dnsmasq"
|
||||||
ENABLED=1
|
ENABLED=1
|
||||||
|
|
||||||
# By default search this drop directory for configuration options.
|
# By default search this drop directory for configuration options.
|
||||||
@@ -24,10 +28,15 @@ ENABLED=1
|
|||||||
# in backups made by dpkg.
|
# in backups made by dpkg.
|
||||||
CONFIG_DIR=/etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new
|
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.
|
||||||
# Note 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
|
||||||
|
|
||||||
|
# If the resolvconf package is installed, dnsmasq will tell resolvconf
|
||||||
|
# to use dnsmasq under 127.0.0.1 as the system's default resolver.
|
||||||
|
# Uncommenting this line inhibits this behaviour.
|
||||||
|
#DNSMASQ_EXCEPT="lo"
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
debian/dnsmasq.runscript name=dnsmasq,logscript,presubj
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh -eu
|
||||||
|
if [ -x /sbin/resolvconf ] ; then
|
||||||
|
/sbin/resolvconf -d lo.dnsmasq
|
||||||
|
fi
|
||||||
|
|
||||||
Vendored
+43
@@ -0,0 +1,43 @@
|
|||||||
|
#!/lib/runit/invoke-run
|
||||||
|
|
||||||
|
readonly name=dnsmasq
|
||||||
|
readonly daemon=/usr/sbin/dnsmasq
|
||||||
|
readonly marker=/usr/share/dnsmasq/installed-marker
|
||||||
|
|
||||||
|
test -e "${marker}" || exec sv down "${name}"
|
||||||
|
test -x "${daemon}" || exec sv down "${name}"
|
||||||
|
|
||||||
|
if [ ! "${RESOLV_CONF:-}" ] &&
|
||||||
|
[ "${IGNORE_RESOLVCONF:-}" != "yes" ] &&
|
||||||
|
[ -x /sbin/resolvconf ]
|
||||||
|
then
|
||||||
|
RESOLV_CONF=/run/dnsmasq/resolv.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This tells dnsmasq to ignore DNS requests that don't come from a local network.
|
||||||
|
# It's automatically ignored if --interface --except-interface, --listen-address
|
||||||
|
# or --auth-server exist in the configuration, so for most installations, it will
|
||||||
|
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
|
||||||
|
# from being vulnerable to DNS-reflection attacks.
|
||||||
|
|
||||||
|
DNSMASQ_OPTS="${DNSMASQ_OPTS:-} --local-service"
|
||||||
|
|
||||||
|
# If the dns-root-data package is installed, then the trust anchors will be
|
||||||
|
# available in $ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
|
||||||
|
# --trust-anchor options.
|
||||||
|
|
||||||
|
ROOT_DS="/usr/share/dns/root.ds"
|
||||||
|
|
||||||
|
if [ -f $ROOT_DS ]; then
|
||||||
|
DNSMASQ_OPTS="$DNSMASQ_OPTS `env LC_ALL=C sed -rne "s/^([.a-zA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p /run/dnsmasq
|
||||||
|
chown dnsmasq:nogroup /run/dnsmasq
|
||||||
|
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
|
||||||
|
exec "${daemon}" \
|
||||||
|
--keep-in-foreground \
|
||||||
|
--log-facility=/dev/stdout \
|
||||||
|
${RESOLV_CONF:+ -r $RESOLV_CONF} \
|
||||||
|
${DNSMASQ_OPTS} \
|
||||||
|
-u dnsmasq
|
||||||
Vendored
+212
-207
@@ -15,53 +15,54 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
|||||||
DAEMON=/usr/sbin/dnsmasq
|
DAEMON=/usr/sbin/dnsmasq
|
||||||
NAME=dnsmasq
|
NAME=dnsmasq
|
||||||
DESC="DNS forwarder and DHCP server"
|
DESC="DNS forwarder and DHCP server"
|
||||||
|
INSTANCE="${2}"
|
||||||
|
|
||||||
# Most configuration options in /etc/default/dnsmasq are deprecated
|
# Most configuration options in /etc/default/dnsmasq are deprecated
|
||||||
# but still honoured.
|
# but still honoured.
|
||||||
ENABLED=1
|
ENABLED=1
|
||||||
if [ -r /etc/default/$NAME ]; then
|
if [ -r /etc/default/${NAME}${INSTANCE:+.${INSTANCE}} ]; then
|
||||||
. /etc/default/$NAME
|
. /etc/default/${NAME}${INSTANCE:+.${INSTANCE}}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the system locale, so that messages are in the correct language, and the
|
# Get the system locale, so that messages are in the correct language, and the
|
||||||
# charset for IDN is correct
|
# charset for IDN is correct
|
||||||
if [ -r /etc/default/locale ]; then
|
if [ -r /etc/default/locale ]; then
|
||||||
. /etc/default/locale
|
. /etc/default/locale
|
||||||
export LANG
|
export LANG
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# The following test ensures the dnsmasq service is not started, when the
|
# The following test ensures the dnsmasq service is not started, when the
|
||||||
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
|
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
|
||||||
# package is still in place.
|
# package is still in place.
|
||||||
test -e /usr/share/dnsmasq/installed-marker || exit 0
|
test -e /usr/share/dnsmasq/installed-marker || 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.
|
||||||
if [ -f /lib/lsb/init-functions ]; then
|
if [ -f /lib/lsb/init-functions ]; then
|
||||||
. /lib/lsb/init-functions
|
. /lib/lsb/init-functions
|
||||||
else
|
else
|
||||||
log_warning_msg () {
|
log_warning_msg () {
|
||||||
echo "${@}."
|
echo "${@}."
|
||||||
}
|
}
|
||||||
|
|
||||||
log_success_msg () {
|
log_success_msg () {
|
||||||
echo "${@}."
|
echo "${@}."
|
||||||
}
|
}
|
||||||
|
|
||||||
log_daemon_msg () {
|
log_daemon_msg () {
|
||||||
echo -n "${1}: $2"
|
echo -n "${1}: ${2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
log_end_msg () {
|
log_end_msg () {
|
||||||
if [ $1 -eq 0 ]; then
|
if [ "${1}" -eq 0 ]; then
|
||||||
echo "."
|
echo "."
|
||||||
elif [ $1 -eq 255 ]; then
|
elif [ "${1}" -eq 255 ]; then
|
||||||
/bin/echo -e " (warning)."
|
/bin/echo -e " (warning)."
|
||||||
else
|
else
|
||||||
/bin/echo -e " failed!"
|
/bin/echo -e " failed!"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# RESOLV_CONF:
|
# RESOLV_CONF:
|
||||||
@@ -73,75 +74,76 @@ fi
|
|||||||
# filename is set there then this inhibits the use of the resolvconf-provided
|
# filename is set there then this inhibits the use of the resolvconf-provided
|
||||||
# information.
|
# information.
|
||||||
#
|
#
|
||||||
# Note that if the resolvconf package is installed it is not possible to
|
# Note that if the resolvconf package is installed it is not possible to
|
||||||
# override it just by configuration in /etc/dnsmasq.conf, it is necessary
|
# override it just by configuration in /etc/dnsmasq.conf, it is necessary
|
||||||
# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
|
# to set IGNORE_RESOLVCONF=yes in /etc/default/dnsmasq.
|
||||||
|
|
||||||
if [ ! "$RESOLV_CONF" ] &&
|
if [ ! "${RESOLV_CONF}" ] &&
|
||||||
[ "$IGNORE_RESOLVCONF" != "yes" ] &&
|
[ "${IGNORE_RESOLVCONF}" != "yes" ] &&
|
||||||
[ -x /sbin/resolvconf ]
|
[ -x /sbin/resolvconf ]
|
||||||
then
|
then
|
||||||
RESOLV_CONF=/run/dnsmasq/resolv.conf
|
RESOLV_CONF=/run/dnsmasq/resolv.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for INTERFACE in $DNSMASQ_INTERFACE; do
|
for INTERFACE in ${DNSMASQ_INTERFACE}; do
|
||||||
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -i $INTERFACE"
|
DNSMASQ_INTERFACES="${DNSMASQ_INTERFACES} -i ${INTERFACE}"
|
||||||
done
|
done
|
||||||
|
|
||||||
for INTERFACE in $DNSMASQ_EXCEPT; do
|
for INTERFACE in ${DNSMASQ_EXCEPT}; do
|
||||||
DNSMASQ_INTERFACES="$DNSMASQ_INTERFACES -I $INTERFACE"
|
DNSMASQ_INTERFACES="${DNSMASQ_INTERFACES} -I ${INTERFACE}"
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ ! "$DNSMASQ_USER" ]; then
|
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.
|
# 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
|
# It's automatically ignored if --interface --except-interface, --listen-address
|
||||||
# or --auth-server exist in the configuration, so for most installations, it will
|
# or --auth-server exist in the configuration, so for most installations, it will
|
||||||
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
|
# have no effect, but for otherwise-unconfigured installations, it stops dnsmasq
|
||||||
# from being vulnerable to DNS-reflection attacks.
|
# from being vulnerable to DNS-reflection attacks.
|
||||||
|
|
||||||
DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
|
DNSMASQ_OPTS="${DNSMASQ_OPTS} --local-service"
|
||||||
|
|
||||||
# If the dns-root-data package is installed, then the trust anchors will be
|
# 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
|
# available in ROOT_DS, in BIND zone-file format. Reformat as dnsmasq
|
||||||
# --trust-anchor options.
|
# --trust-anchor options.
|
||||||
|
|
||||||
ROOT_DS="/usr/share/dns/root.ds"
|
ROOT_DS="/usr/share/dns/root.ds"
|
||||||
|
|
||||||
if [ -f $ROOT_DS ]; then
|
if [ -f ${ROOT_DS} ]; then
|
||||||
DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -rne "s/^([.a-ZA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
|
DNSMASQ_OPTS="$DNSMASQ_OPTS `env LC_ALL=C sed -rne "s/^([.a-zA-Z0-9]+)([[:space:]]+[0-9]+)*([[:space:]]+IN)*[[:space:]]+DS[[:space:]]+/--trust-anchor=\1,/;s/[[:space:]]+/,/gp" $ROOT_DS | tr '\n' ' '`"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
start()
|
start()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been started
|
# 0 if daemon has been started
|
||||||
# 1 if daemon was already running
|
# 1 if daemon was already running
|
||||||
# 2 if daemon could not be started
|
# 2 if daemon could not be started
|
||||||
|
|
||||||
# /run may be volatile, so we need to ensure that
|
# /run may be volatile, so we need to ensure that
|
||||||
# /run/dnsmasq exists here as well as in postinst
|
# /run/dnsmasq exists here as well as in postinst
|
||||||
if [ ! -d /run/dnsmasq ]; then
|
if [ ! -d /run/dnsmasq ]; then
|
||||||
mkdir /run/dnsmasq || return 2
|
mkdir /run/dnsmasq || { [ -d /run/dnsmasq ] || return 2 ; }
|
||||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||||
fi
|
fi
|
||||||
|
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
|
||||||
|
|
||||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
|
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} --test > /dev/null || return 1
|
||||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON -- \
|
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} -- \
|
||||||
-x /run/dnsmasq/$NAME.pid \
|
-x /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid \
|
||||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
${MAILHOSTNAME:+ -m ${MAILHOSTNAME}} \
|
||||||
${MAILTARGET:+ -t $MAILTARGET} \
|
${MAILTARGET:+ -t ${MAILTARGET}} \
|
||||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
${DNSMASQ_USER:+ -u ${DNSMASQ_USER}} \
|
||||||
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
|
${DNSMASQ_INTERFACES:+ ${DNSMASQ_INTERFACES}} \
|
||||||
${DHCP_LEASE:+ -l $DHCP_LEASE} \
|
${DHCP_LEASE:+ -l ${DHCP_LEASE}} \
|
||||||
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
|
${DOMAIN_SUFFIX:+ -s ${DOMAIN_SUFFIX}} \
|
||||||
${RESOLV_CONF:+ -r $RESOLV_CONF} \
|
${RESOLV_CONF:+ -r ${RESOLV_CONF}} \
|
||||||
${CACHESIZE:+ -c $CACHESIZE} \
|
${CACHESIZE:+ -c ${CACHESIZE}} \
|
||||||
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
|
${CONFIG_DIR:+ -7 ${CONFIG_DIR}} \
|
||||||
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} \
|
${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} \
|
||||||
|| return 2
|
|| return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
start_resolvconf()
|
start_resolvconf()
|
||||||
@@ -149,172 +151,175 @@ start_resolvconf()
|
|||||||
# If interface "lo" is explicitly disabled in /etc/default/dnsmasq
|
# If interface "lo" is explicitly disabled in /etc/default/dnsmasq
|
||||||
# Then dnsmasq won't be providing local DNS, so don't add it to
|
# Then dnsmasq won't be providing local DNS, so don't add it to
|
||||||
# the resolvconf server set.
|
# the resolvconf server set.
|
||||||
for interface in $DNSMASQ_EXCEPT
|
for interface in ${DNSMASQ_EXCEPT}; do
|
||||||
do
|
[ ${interface} = lo ] && return
|
||||||
[ $interface = lo ] && return
|
done
|
||||||
done
|
|
||||||
|
|
||||||
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
|
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
|
||||||
if grep -qs '^port=0' /etc/dnsmasq.conf; then
|
if grep -qs '^port=0' /etc/dnsmasq.conf; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -x /sbin/resolvconf ] ; then
|
if [ -x /sbin/resolvconf ] ; then
|
||||||
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
|
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.${NAME}${INSTANCE:+.${INSTANCE}}
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
stop()
|
stop()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon has been stopped
|
# 0 if daemon has been stopped
|
||||||
# 1 if daemon was already stopped
|
# 1 if daemon was already stopped
|
||||||
# 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 /run/dnsmasq/$NAME.pid --name $NAME
|
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --name ${NAME}
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_resolvconf()
|
stop_resolvconf()
|
||||||
{
|
{
|
||||||
if [ -x /sbin/resolvconf ] ; then
|
if [ -x /sbin/resolvconf ] ; then
|
||||||
/sbin/resolvconf -d lo.$NAME
|
/sbin/resolvconf -d lo.${NAME}${INSTANCE:+.${INSTANCE}}
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
status()
|
status()
|
||||||
{
|
{
|
||||||
# Return
|
# Return
|
||||||
# 0 if daemon is running
|
# 0 if daemon is running
|
||||||
# 1 if daemon is dead and pid file exists
|
# 1 if daemon is dead and pid file exists
|
||||||
# 3 if daemon is not running
|
# 3 if daemon is not running
|
||||||
# 4 if daemon status is unknown
|
# 4 if daemon status is unknown
|
||||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
|
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid --exec ${DAEMON} --test > /dev/null
|
||||||
case "$?" in
|
case "${?}" in
|
||||||
0) [ -e "/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
|
0) [ -e "/run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid" ] && return 1 ; return 3 ;;
|
||||||
1) return 0 ;;
|
1) return 0 ;;
|
||||||
*) return 4 ;;
|
*) return 4 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
case "$1" in
|
case "${1}" in
|
||||||
start)
|
start)
|
||||||
test "$ENABLED" != "0" || exit 0
|
test "${ENABLED}" != "0" || exit 0
|
||||||
log_daemon_msg "Starting $DESC" "$NAME"
|
log_daemon_msg "Starting ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
|
||||||
start
|
start
|
||||||
case "$?" in
|
case "${?}" in
|
||||||
0)
|
0)
|
||||||
log_end_msg 0
|
log_end_msg 0
|
||||||
start_resolvconf
|
start_resolvconf
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
1)
|
1)
|
||||||
log_success_msg "(already running)"
|
log_success_msg "(already running)"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log_end_msg 1
|
log_end_msg 1
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
stop_resolvconf
|
stop_resolvconf
|
||||||
if [ "$ENABLED" != "0" ]; then
|
if [ "${ENABLED}" != "0" ]; then
|
||||||
log_daemon_msg "Stopping $DESC" "$NAME"
|
log_daemon_msg "Stopping ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
|
||||||
fi
|
fi
|
||||||
stop
|
stop
|
||||||
RETVAL="$?"
|
RETVAL="${?}"
|
||||||
if [ "$ENABLED" = "0" ]; then
|
if [ "${ENABLED}" = "0" ]; then
|
||||||
case "$RETVAL" in
|
case "${RETVAL}" in
|
||||||
0) log_daemon_msg "Stopping $DESC" "$NAME"; log_end_msg 0 ;;
|
0) log_daemon_msg "Stopping ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"; log_end_msg 0 ;;
|
||||||
esac
|
esac
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
case "$RETVAL" in
|
case "${RETVAL}" in
|
||||||
0) log_end_msg 0 ; exit 0 ;;
|
0) log_end_msg 0 ; exit 0 ;;
|
||||||
1) log_warning_msg "(not running)" ; exit 0 ;;
|
1) log_warning_msg "(not running)" ; exit 0 ;;
|
||||||
*) log_end_msg 1; exit 1 ;;
|
*) log_end_msg 1; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
|
checkconfig)
|
||||||
|
${DAEMON} --test ${CONFIG_DIR:+ -7 ${CONFIG_DIR}} ${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} >/dev/null 2>&1
|
||||||
|
RETVAL="${?}"
|
||||||
|
exit ${RETVAL}
|
||||||
|
;;
|
||||||
restart|force-reload)
|
restart|force-reload)
|
||||||
test "$ENABLED" != "0" || exit 1
|
test "${ENABLED}" != "0" || exit 1
|
||||||
$DAEMON --test ${CONFIG_DIR:+ -7 $CONFIG_DIR} ${DNSMASQ_OPTS:+ $DNSMASQ_OPTS} >/dev/null 2>&1
|
${DAEMON} --test ${CONFIG_DIR:+ -7 ${CONFIG_DIR}} ${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}} >/dev/null 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
if [ ${?} -ne 0 ]; then
|
||||||
NAME="configuration syntax check"
|
NAME="configuration syntax check"
|
||||||
RETVAL="2"
|
RETVAL="2"
|
||||||
else
|
else
|
||||||
stop_resolvconf
|
stop_resolvconf
|
||||||
stop
|
stop
|
||||||
RETVAL="$?"
|
RETVAL="${?}"
|
||||||
fi
|
fi
|
||||||
log_daemon_msg "Restarting $DESC" "$NAME"
|
log_daemon_msg "Restarting ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
|
||||||
case "$RETVAL" in
|
case "${RETVAL}" in
|
||||||
0|1)
|
0|1)
|
||||||
sleep 2
|
sleep 2
|
||||||
start
|
start
|
||||||
case "$?" in
|
case "${?}" in
|
||||||
0)
|
0)
|
||||||
log_end_msg 0
|
log_end_msg 0
|
||||||
start_resolvconf
|
start_resolvconf
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log_end_msg 1
|
log_end_msg 1
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
log_end_msg 1
|
log_end_msg 1
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
log_daemon_msg "Checking $DESC" "$NAME"
|
log_daemon_msg "Checking ${DESC}" "${NAME}${INSTANCE:+.${INSTANCE}}"
|
||||||
status
|
status
|
||||||
case "$?" in
|
case "${?}" in
|
||||||
0) log_success_msg "(running)" ; exit 0 ;;
|
0) log_success_msg "(running)" ; exit 0 ;;
|
||||||
1) log_success_msg "(dead, pid file exists)" ; exit 1 ;;
|
1) log_success_msg "(dead, pid file exists)" ; exit 1 ;;
|
||||||
3) log_success_msg "(not running)" ; exit 3 ;;
|
3) log_success_msg "(not running)" ; exit 3 ;;
|
||||||
*) log_success_msg "(unknown)" ; exit 4 ;;
|
*) log_success_msg "(unknown)" ; exit 4 ;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
dump-stats)
|
dump-stats)
|
||||||
kill -s USR1 `cat /run/dnsmasq/$NAME.pid`
|
kill -s USR1 `cat /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid`
|
||||||
;;
|
;;
|
||||||
systemd-start-resolvconf)
|
systemd-start-resolvconf)
|
||||||
start_resolvconf
|
start_resolvconf
|
||||||
;;
|
;;
|
||||||
systemd-stop-resolvconf)
|
systemd-stop-resolvconf)
|
||||||
stop_resolvconf
|
stop_resolvconf
|
||||||
;;
|
;;
|
||||||
systemd-exec)
|
systemd-exec)
|
||||||
# /run may be volatile, so we need to ensure that
|
# /run may be volatile, so we need to ensure that
|
||||||
# /run/dnsmasq exists here as well as in postinst
|
# /run/dnsmasq exists here as well as in postinst
|
||||||
if [ ! -d /run/dnsmasq ]; then
|
if [ ! -d /run/dnsmasq ]; then
|
||||||
mkdir /run/dnsmasq || return 2
|
mkdir /run/dnsmasq || { [ -d /run/dnsmasq ] || return 2 ; }
|
||||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||||
fi
|
fi
|
||||||
exec $DAEMON -x /run/dnsmasq/$NAME.pid \
|
exec ${DAEMON} -x /run/dnsmasq/${NAME}${INSTANCE:+.${INSTANCE}}.pid \
|
||||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
${MAILHOSTNAME:+ -m ${MAILHOSTNAME}} \
|
||||||
${MAILTARGET:+ -t $MAILTARGET} \
|
${MAILTARGET:+ -t ${MAILTARGET}} \
|
||||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
${DNSMASQ_USER:+ -u ${DNSMASQ_USER}} \
|
||||||
${DNSMASQ_INTERFACES:+ $DNSMASQ_INTERFACES} \
|
${DNSMASQ_INTERFACES:+ ${DNSMASQ_INTERFACES}} \
|
||||||
${DHCP_LEASE:+ -l $DHCP_LEASE} \
|
${DHCP_LEASE:+ -l ${DHCP_LEASE}} \
|
||||||
${DOMAIN_SUFFIX:+ -s $DOMAIN_SUFFIX} \
|
${DOMAIN_SUFFIX:+ -s ${DOMAIN_SUFFIX}} \
|
||||||
${RESOLV_CONF:+ -r $RESOLV_CONF} \
|
${RESOLV_CONF:+ -r ${RESOLV_CONF}} \
|
||||||
${CACHESIZE:+ -c $CACHESIZE} \
|
${CACHESIZE:+ -c ${CACHESIZE}} \
|
||||||
${CONFIG_DIR:+ -7 $CONFIG_DIR} \
|
${CONFIG_DIR:+ -7 ${CONFIG_DIR}} \
|
||||||
${DNSMASQ_OPTS:+ $DNSMASQ_OPTS}
|
${DNSMASQ_OPTS:+ ${DNSMASQ_OPTS}}
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: /etc/init.d/$NAME {start|stop|restart|force-reload|dump-stats|status}" >&2
|
echo "Usage: /etc/init.d/${NAME} {start|stop|restart|force-reload|dump-stats|status}" >&2
|
||||||
exit 3
|
exit 3
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
||||||
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
# dnsmasq-base and dnsmasq-base-lua are mutually exclusive and both
|
||||||
|
# provide /usr/share/doc/dnsmasq-base
|
||||||
|
dnsmasq-base-lua binary: usr-share-doc-symlink-without-dependency dnsmasq-base
|
||||||
Vendored
+1
-1
@@ -54,7 +54,7 @@ Notes on configuring dnsmasq as packaged for Debian.
|
|||||||
nodhcp : omit DHCP support.
|
nodhcp : omit DHCP support.
|
||||||
nodhcp6 : omit DHCPv6 support.
|
nodhcp6 : omit DHCPv6 support.
|
||||||
noscript : omit lease-change script support.
|
noscript : omit lease-change script support.
|
||||||
use_lua : provide support for lease-change scripts written
|
uselua : provide support for lease-change scripts written
|
||||||
in Lua.
|
in Lua.
|
||||||
noipv6 : omit IPv6 support.
|
noipv6 : omit IPv6 support.
|
||||||
nodbus : omit DBus support.
|
nodbus : omit DBus support.
|
||||||
|
|||||||
Vendored
+172
-114
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
# debian/rules file - for dnsmasq.
|
# debian/rules file - for dnsmasq.
|
||||||
# Copyright 2001-2011 by Simon Kelley
|
# Copyright 2001-2020 by Simon Kelley
|
||||||
# Based on the sample in the debian hello package which carries the following:
|
# Based on the sample in the debian hello package which carries the following:
|
||||||
# Copyright 1994,1995 by Ian Jackson.
|
# Copyright 1994,1995 by Ian Jackson.
|
||||||
# I hereby give you perpetual unlimited permission to copy,
|
# I hereby give you perpetual unlimited permission to copy,
|
||||||
@@ -49,7 +49,7 @@ ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
||||||
DEB_COPTS += -DHAVE_IDN
|
DEB_COPTS += -DHAVE_LIBIDN2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||||
@@ -98,133 +98,191 @@ ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
|
|||||||
DEB_COPTS += -DHAVE_DNSSEC
|
DEB_COPTS += -DHAVE_DNSSEC
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(DEB_HOST_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
|
||||||
# For strlcpy in FreeBSD
|
# For strlcpy in FreeBSD
|
||||||
LDFLAGS += -lbsd
|
LIBS += $(shell ${PKG_CONFIG} --libs libbsd-overlay)
|
||||||
|
CFLAGS += $(shell ${PKG_CONFIG} --cflags libbsd-overlay)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
clean:
|
define build_tree
|
||||||
$(checkdir)
|
rm -rf $1
|
||||||
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
|
|
||||||
make clean
|
|
||||||
make -C contrib/lease-tools clean
|
|
||||||
|
|
||||||
binary-indep: checkroot
|
|
||||||
$(checkdir)
|
|
||||||
rm -rf debian/daemon
|
|
||||||
install -m 755 \
|
install -m 755 \
|
||||||
-d debian/daemon/DEBIAN \
|
-d $1/DEBIAN \
|
||||||
-d debian/daemon/usr/share/doc \
|
-d $1/etc/dbus-1/system.d \
|
||||||
-d debian/daemon/etc/init.d \
|
-d $1/usr/share/doc/$(package) \
|
||||||
-d debian/daemon/etc/dnsmasq.d \
|
-d $1/usr/share/doc/$(package)/examples \
|
||||||
-d debian/daemon/etc/resolvconf/update.d \
|
-d $1/usr/share/$(package) \
|
||||||
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
|
-d $1/var/lib/misc
|
||||||
-d debian/daemon/usr/share/dnsmasq \
|
|
||||||
-d debian/daemon/etc/default \
|
|
||||||
-d debian/daemon/lib/systemd/system \
|
|
||||||
-d debian/daemon/etc/insserv.conf.d
|
|
||||||
install -m 644 debian/conffiles debian/daemon/DEBIAN
|
|
||||||
install -m 755 debian/postinst debian/postrm debian/prerm debian/daemon/DEBIAN
|
|
||||||
install -m 755 debian/init debian/daemon/etc/init.d/dnsmasq
|
|
||||||
install -m 755 debian/resolvconf debian/daemon/etc/resolvconf/update.d/dnsmasq
|
|
||||||
install -m 755 debian/resolvconf-package debian/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
|
|
||||||
install -m 644 debian/installed-marker debian/daemon/usr/share/dnsmasq
|
|
||||||
install -m 644 debian/default debian/daemon/etc/default/dnsmasq
|
|
||||||
install -m 644 dnsmasq.conf.example debian/daemon/etc/dnsmasq.conf
|
|
||||||
install -m 644 debian/readme.dnsmasq.d debian/daemon/etc/dnsmasq.d/README
|
|
||||||
install -m 644 debian/systemd.service debian/daemon/lib/systemd/system/dnsmasq.service
|
|
||||||
install -m 644 debian/insserv debian/daemon/etc/insserv.conf.d/dnsmasq
|
|
||||||
ln -s $(package) debian/daemon/usr/share/doc/dnsmasq
|
|
||||||
cd debian/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
|
||||||
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
|
|
||||||
chmod -R g-ws debian/daemon
|
|
||||||
dpkg --build debian/daemon ..
|
|
||||||
|
|
||||||
binary-arch: checkroot
|
endef
|
||||||
$(checkdir)
|
|
||||||
rm -rf debian/base
|
define add_docs
|
||||||
install -m 755 \
|
|
||||||
-d debian/base/DEBIAN \
|
|
||||||
-d debian/base/etc/dbus-1/system.d \
|
|
||||||
-d debian/base/usr/share/doc/$(package) \
|
|
||||||
-d debian/base/usr/share/doc/$(package)/examples \
|
|
||||||
-d debian/base/usr/share/$(package) \
|
|
||||||
-d debian/base/var/lib/misc
|
|
||||||
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
|
||||||
ifeq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS)))
|
|
||||||
# Need to remove paypal links in Debian Package for policy reasons.
|
# 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
|
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >$1/usr/share/doc/$(package)/doc.html
|
||||||
echo "</BODY>" >>debian/base/usr/share/doc/$(package)/doc.html
|
echo "</BODY>" >>$1/usr/share/doc/$(package)/doc.html
|
||||||
install -m 644 setup.html debian/base/usr/share/doc/$(package)/.
|
install -m 644 setup.html $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 dnsmasq.conf.example debian/base/usr/share/doc/$(package)/examples/.
|
install -m 644 dnsmasq.conf.example $1/usr/share/doc/$(package)/examples/.
|
||||||
install -m 644 trust-anchors.conf debian/base/usr/share/$(package)/.
|
install -m 644 FAQ $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 FAQ debian/base/usr/share/doc/$(package)/.
|
gzip -9n $1/usr/share/doc/$(package)/FAQ
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/FAQ
|
install -m 644 CHANGELOG $1/usr/share/doc/$(package)/changelog
|
||||||
install -m 644 CHANGELOG debian/base/usr/share/doc/$(package)/changelog
|
gzip -9n $1/usr/share/doc/$(package)/changelog
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/changelog
|
install -m 644 CHANGELOG.archive $1/usr/share/doc/$(package)/changelog.archive
|
||||||
install -m 644 CHANGELOG.archive debian/base/usr/share/doc/$(package)/changelog.archive
|
gzip -9n $1/usr/share/doc/$(package)/changelog.archive
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/changelog.archive
|
install -m 644 dbus/DBus-interface $1/usr/share/doc/$(package)/.
|
||||||
install -m 644 dbus/DBus-interface debian/base/usr/share/doc/$(package)/.
|
gzip -9n $1/usr/share/doc/$(package)/DBus-interface
|
||||||
gzip -9n debian/base/usr/share/doc/$(package)/DBus-interface
|
install -m 644 debian/systemd_howto $1/usr/share/doc/$(package)/.
|
||||||
endif
|
gzip -9n $1/usr/share/doc/$(package)/systemd_howto
|
||||||
install -m 644 debian/dnsmasq-base.conffiles debian/base/DEBIAN/conffiles
|
gzip -9n $1/usr/share/man/man8/dnsmasq.8
|
||||||
install -m 755 debian/dnsmasq-base.postinst debian/base/DEBIAN/postinst
|
for f in $1/usr/share/man/*; do \
|
||||||
install -m 755 debian/dnsmasq-base.postrm debian/base/DEBIAN/postrm
|
|
||||||
install -m 644 debian/changelog debian/base/usr/share/doc/$(package)/changelog.Debian
|
|
||||||
gzip -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/copyright debian/base/usr/share/doc/$(package)/copyright
|
|
||||||
install -m 644 debian/dbus.conf debian/base/etc/dbus-1/system.d/dnsmasq.conf
|
|
||||||
gzip -9n debian/base/usr/share/man/man8/dnsmasq.8
|
|
||||||
for f in debian/base/usr/share/man/*; do \
|
|
||||||
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
if [ -f $$f/man8/dnsmasq.8 ]; then \
|
||||||
gzip -9n $$f/man8/dnsmasq.8 ; \
|
gzip -9n $$f/man8/dnsmasq.8 ; \
|
||||||
fi \
|
fi \
|
||||||
done
|
done
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
endef
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
|
||||||
|
define add_files
|
||||||
|
install -m 644 trust-anchors.conf $1/usr/share/$(package)/.
|
||||||
|
install -m 644 debian/dnsmasq-base.conffiles $1/DEBIAN/conffiles
|
||||||
|
install -m 755 debian/dnsmasq-base.postinst $1/DEBIAN/postinst
|
||||||
|
install -m 755 debian/dnsmasq-base.postrm $1/DEBIAN/postrm
|
||||||
|
install -m 644 debian/changelog $1/usr/share/doc/$(package)/changelog.Debian
|
||||||
|
gzip -9n $1/usr/share/doc/$(package)/changelog.Debian
|
||||||
|
install -m 644 debian/readme $1/usr/share/doc/$(package)/README.Debian
|
||||||
|
install -m 644 debian/copyright $1/usr/share/doc/$(package)/copyright
|
||||||
|
install -m 644 debian/dbus.conf $1/etc/dbus-1/system.d/dnsmasq.conf
|
||||||
|
endef
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(checkdir)
|
||||||
|
make BUILDDIR=debian/build/no-lua clean
|
||||||
|
make BUILDDIR=debian/build/lua clean
|
||||||
|
make -C contrib/lease-tools clean
|
||||||
|
rm -rf debian/build debian/trees debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||||
|
|
||||||
|
binary-indep: checkroot
|
||||||
|
$(checkdir)
|
||||||
|
rm -rf debian/trees/daemon
|
||||||
|
install -m 755 \
|
||||||
|
-d debian/trees/daemon/DEBIAN \
|
||||||
|
-d debian/trees/daemon/usr/share/doc/dnsmasq \
|
||||||
|
-d debian/trees/daemon/etc/init.d \
|
||||||
|
-d debian/trees/daemon/etc/dnsmasq.d \
|
||||||
|
-d debian/trees/daemon/etc/resolvconf/update.d \
|
||||||
|
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||||
|
-d debian/trees/daemon/usr/share/dnsmasq \
|
||||||
|
-d debian/trees/daemon/usr/share/doc/dnsmasq \
|
||||||
|
-d debian/trees/daemon/etc/default \
|
||||||
|
-d debian/trees/daemon/lib/systemd/system \
|
||||||
|
-d debian/trees/daemon/usr/lib/tmpfiles.d \
|
||||||
|
-d debian/trees/daemon/etc/insserv.conf.d
|
||||||
|
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
|
||||||
|
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
|
||||||
|
if ! dpkg-vendor --derives-from Ubuntu; then \
|
||||||
|
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper; \
|
||||||
|
dh_runit -pdnsmasq -Pdebian/trees/daemon; \
|
||||||
|
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst; \
|
||||||
|
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm; \
|
||||||
|
cd debian/trees/daemon && find etc/sv -type f -printf '/%p\n' >>DEBIAN/conffiles; \
|
||||||
|
fi
|
||||||
|
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
|
||||||
|
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
|
||||||
|
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
|
||||||
|
install -m 644 debian/installed-marker debian/trees/daemon/usr/share/dnsmasq
|
||||||
|
install -m 644 debian/default debian/trees/daemon/etc/default/dnsmasq
|
||||||
|
install -m 644 dnsmasq.conf.example debian/trees/daemon/etc/dnsmasq.conf
|
||||||
|
install -m 644 debian/readme.dnsmasq.d debian/trees/daemon/etc/dnsmasq.d/README
|
||||||
|
install -m 644 debian/systemd.service debian/trees/daemon/lib/systemd/system/dnsmasq.service
|
||||||
|
install -m 644 debian/systemd@.service debian/trees/daemon/lib/systemd/system/dnsmasq@.service
|
||||||
|
install -m 644 debian/tmpfiles.conf debian/trees/daemon/usr/lib/tmpfiles.d/dnsmasq.conf
|
||||||
|
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
|
||||||
|
install -m 644 debian/copyright debian/trees/daemon/usr/share/doc/dnsmasq/copyright
|
||||||
|
install -m 644 debian/changelog debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
|
||||||
|
gzip -9n debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
|
||||||
|
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
|
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/dnsmasq.substvars -pdnsmasq -Pdebian/trees/daemon
|
||||||
|
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/daemon
|
||||||
|
chmod -R g-ws debian/trees/daemon
|
||||||
|
dpkg --build debian/trees/daemon ..
|
||||||
|
|
||||||
|
binary-arch: checkroot
|
||||||
|
$(call build_tree,debian/trees/base)
|
||||||
|
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||||
|
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(call add_docs,debian/trees/base)
|
||||||
|
else
|
||||||
|
rm -rf debian/trees/base/usr/share/man
|
||||||
endif
|
endif
|
||||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
$(call add_files,debian/trees/base)
|
||||||
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/base
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/base/usr/sbin/dnsmasq
|
||||||
find debian/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
endif
|
||||||
chown -R root.root debian/base
|
cd debian/trees/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
chmod -R g-ws debian/base
|
dpkg-shlibdeps --warnings=1 debian/trees/base/usr/sbin/dnsmasq
|
||||||
dpkg --build debian/base ..
|
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base -Pdebian/trees/base
|
||||||
|
find debian/trees/base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/base
|
||||||
|
chmod -R g-ws debian/trees/base
|
||||||
|
dpkg --build debian/trees/base ..
|
||||||
|
|
||||||
|
$(call build_tree,debian/trees/lua-base)
|
||||||
|
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||||
|
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(call add_docs,debian/trees/lua-base)
|
||||||
|
else
|
||||||
|
rm -rf debian/trees/lua-base/usr/share/man
|
||||||
|
endif
|
||||||
|
$(call add_files,debian/trees/lua-base)
|
||||||
|
install -m 755 -d debian/trees/lua-base/usr/share/lintian/overrides
|
||||||
|
install -m 644 debian/lintian-override debian/trees/lua-base/usr/share/lintian/overrides/dnsmasq-base-lua
|
||||||
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/lua-base/usr/sbin/dnsmasq
|
||||||
|
endif
|
||||||
|
ln -s $(package) debian/trees/lua-base/usr/share/doc/dnsmasq-base-lua
|
||||||
|
cd debian/trees/lua-base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
|
dpkg-shlibdeps --warnings=1 debian/trees/lua-base/usr/sbin/dnsmasq
|
||||||
|
dpkg-gencontrol $(PACKAGE_VERSION) -pdnsmasq-base-lua -Pdebian/trees/lua-base
|
||||||
|
find debian/trees/lua-base -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
||||||
|
chown -R root.root debian/trees/lua-base
|
||||||
|
chmod -R g-ws debian/trees/lua-base
|
||||||
|
dpkg --build debian/trees/lua-base ..
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
rm -rf debian/utils
|
rm -rf debian/trees/utils
|
||||||
install -m 755 -d debian/utils/DEBIAN \
|
install -m 755 -d debian/trees/utils/DEBIAN \
|
||||||
-d debian/utils/usr/share/man/man1 \
|
-d debian/trees/utils/usr/bin \
|
||||||
-d debian/utils/usr/bin \
|
-d debian/trees/utils/usr/share/doc/dnsmasq-utils
|
||||||
-d debian/utils/usr/share/doc/dnsmasq-utils
|
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||||
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
|
install -m 755 -d debian/trees/utils/usr/share/man/man1
|
||||||
install -m 755 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
|
endif
|
||||||
install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
|
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
|
||||||
install -m 755 contrib/lease-tools/dhcp_release6 debian/utils/usr/bin/dhcp_release6
|
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
|
||||||
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/utils/usr/share/man/man1/dhcp_release6.1
|
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release6.1
|
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
|
||||||
install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
install -m 644 contrib/lease-tools/dhcp_release.1 debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||||
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release.1
|
||||||
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
|
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||||
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_release6.1
|
||||||
gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
gzip -9n debian/trees/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||||
|
endif
|
||||||
|
install -m 644 debian/copyright debian/trees/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||||
|
install -m 644 debian/changelog debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
|
gzip -9n debian/trees/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_release6
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_release6
|
||||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
endif
|
endif
|
||||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
cd debian/trees/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||||
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
|
dpkg-shlibdeps -Tdebian/utils-substvars debian/trees/utils/usr/bin/dhcp_release debian/trees/utils/usr/bin/dhcp_release6 debian/trees/utils/usr/bin/dhcp_lease_time
|
||||||
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/utils
|
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/utils-substvars -pdnsmasq-utils -Pdebian/trees/utils
|
||||||
find debian/utils -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
|
find debian/trees/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/trees/utils
|
||||||
chmod -R g-ws debian/utils
|
chmod -R g-ws debian/trees/utils
|
||||||
dpkg --build debian/utils ..
|
dpkg --build debian/trees/utils ..
|
||||||
endif
|
endif
|
||||||
|
|
||||||
define checkdir
|
define checkdir
|
||||||
|
|||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
libnettle 6 libnettle6 (>= 3.3)
|
|
||||||
Vendored
+3
-3
@@ -10,7 +10,7 @@ Type=forking
|
|||||||
PIDFile=/run/dnsmasq/dnsmasq.pid
|
PIDFile=/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=/etc/init.d/dnsmasq checkconfig
|
||||||
|
|
||||||
# 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
|
||||||
@@ -19,8 +19,8 @@ ExecStart=/etc/init.d/dnsmasq systemd-exec
|
|||||||
|
|
||||||
# The systemd-*-resolvconf functions configure (and deconfigure)
|
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||||
# resolvconf to work with the dnsmasq DNS server. They're called like
|
# resolvconf to work with the dnsmasq DNS server. They're called like
|
||||||
# this to get correct error handling (ie don't start-resolvconf if the
|
# this to get correct error handling (ie don't start-resolvconf if the
|
||||||
# dnsmasq daemon fails to start.
|
# dnsmasq daemon fails to start).
|
||||||
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
|
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf
|
||||||
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
|
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf
|
||||||
|
|
||||||
|
|||||||
Vendored
+31
@@ -0,0 +1,31 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=dnsmasq (%i) - A lightweight DHCP and caching DNS server
|
||||||
|
Requires=network.target
|
||||||
|
Wants=nss-lookup.target
|
||||||
|
Before=nss-lookup.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
PIDFile=/run/dnsmasq/dnsmasq.%i.pid
|
||||||
|
|
||||||
|
# Test the config file and refuse starting if it is not valid.
|
||||||
|
ExecStartPre=/etc/init.d/dnsmasq checkconfig "%i"
|
||||||
|
|
||||||
|
# We run dnsmasq via the /etc/init.d/dnsmasq script which acts as a
|
||||||
|
# wrapper picking up extra configuration files and then execs dnsmasq
|
||||||
|
# itself, when called with the "systemd-exec" function.
|
||||||
|
ExecStart=/etc/init.d/dnsmasq systemd-exec "%i"
|
||||||
|
|
||||||
|
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||||
|
# resolvconf to work with the dnsmasq DNS server. They're called like
|
||||||
|
# this to get correct error handling (ie don't start-resolvconf if the
|
||||||
|
# dnsmasq daemon fails to start).
|
||||||
|
ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf "%i"
|
||||||
|
ExecStop=/etc/init.d/dnsmasq systemd-stop-resolvconf "%i"
|
||||||
|
|
||||||
|
|
||||||
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
Vendored
+41
@@ -0,0 +1,41 @@
|
|||||||
|
HOWTO
|
||||||
|
=====
|
||||||
|
dnsmasq comes with the possibility to run multiple systemd service instances on the same machine.
|
||||||
|
There is the main service which is enabled by default via `systemctl enable dnsmasq.service` and uses the configuration from `/etc/default/dnsmasq`.
|
||||||
|
|
||||||
|
Additional service instances can be enabled via `systemctl enable dnsmasq@<instance name>.service` that use the configuration from `/etc/default/dnsmasq.<instance name>`.
|
||||||
|
It is recommended to use a separate configuration file and directory for each instance.
|
||||||
|
Additionally make sure that all instances use either different ports and/or ip addresses to avoid binding collisions.
|
||||||
|
|
||||||
|
Example setup for an instance called "alt"
|
||||||
|
#1 File `/etc/dnsmasq.alt.conf` copied from `/etc/dnsmasq.conf`
|
||||||
|
#2 Directory `/etc/dnsmasq.alt.d`
|
||||||
|
#3 File `/etc/default/dnsmasq.alt` copied from `/etc/default/dnsmasq` with following adaptions:
|
||||||
|
* The options DNSMASQ_OPTS and CONFIG_DIR point to the correct configuration file and directory.
|
||||||
|
DNSMASQ_OPTS="... --conf-file=/etc/dnsmasq.alt.conf ..."
|
||||||
|
CONFIG_DIR=/etc/dnsmasq.alt.d,.dpkg-dist,.dpkg-old,.dpkg-new
|
||||||
|
* The option DNSMASQ_EXCEPT must contain "lo" to avoid that an instance becomes the machine's DNS resolver.
|
||||||
|
DNSMASQ_EXCEPT="lo"
|
||||||
|
* If the additional instance should bind to all IP addresses of a specific interface, e.g. "dnsalt01", then the following addition could be used:
|
||||||
|
DNSMASQ_OPTS="... --bind-dynamic --interface=dnsalt01 ..."
|
||||||
|
Additionally the main instance must be stopped from binding to interfaces that are used by other instances:
|
||||||
|
DNSMASQ_OPTS="... --bind-dynamic --except-interface=dnsalt* ..."
|
||||||
|
* If the additional instance should not use the machine's DNS resolver, normally that's the dnsmasq main instance, as upstream server, then the following addition could be used:
|
||||||
|
IGNORE_RESOLVCONF=yes
|
||||||
|
#4 Enable additional instance via `systemctl enable dnsmasq@alt.service`
|
||||||
|
#5 Start additional instance without reboot via `systemctl start dnsmasq@alt.service`
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TODO
|
||||||
|
====
|
||||||
|
#1 - Found shortcoming on 2019-03-10
|
||||||
|
Only the option DNSMASQ_EXCEPT="lo" avoids that an DNS instance will be set as the machine's DNS resolver.
|
||||||
|
This may interfere with the wish to run an additional instance on a different port on the localhost addresses.
|
||||||
|
My suggestion in the initial Debian report [1] was to specify an explicit variable for this.
|
||||||
|
|
||||||
|
[1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=914305#5
|
||||||
|
|
||||||
|
|
||||||
|
#2 - Preferred configuration way
|
||||||
|
Should the variables DNSMASQ_INTERFACE and DNSMASQ_EXCEPT be used instead of --interface and --except-interface? (while "lo" still has to be in DNSMASQ_EXCEPT as of now)
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
d /run/dnsmasq 755 dnsmasq nogroup
|
||||||
+26
-13
@@ -90,7 +90,7 @@
|
|||||||
# server=10.1.2.3@eth1
|
# server=10.1.2.3@eth1
|
||||||
|
|
||||||
# and this sets the source (ie local) address used to talk to
|
# and this sets the source (ie local) address used to talk to
|
||||||
# 10.1.2.3 to 192.168.1.1 port 55 (there must be a interface with that
|
# 10.1.2.3 to 192.168.1.1 port 55 (there must be an interface with that
|
||||||
# IP on the machine, obviously).
|
# IP on the machine, obviously).
|
||||||
# server=10.1.2.3@192.168.1.1#55
|
# server=10.1.2.3@192.168.1.1#55
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@
|
|||||||
# Give a fixed IPv6 address and name to client with
|
# Give a fixed IPv6 address and name to client with
|
||||||
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
|
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
|
||||||
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
|
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
|
||||||
# Note also the they [] around the IPv6 address are obligatory.
|
# Note also that the [] around the IPv6 address are obligatory.
|
||||||
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
|
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
|
||||||
|
|
||||||
# Ignore any clients which are not specified in dhcp-host lines
|
# Ignore any clients which are not specified in dhcp-host lines
|
||||||
@@ -354,11 +354,11 @@
|
|||||||
|
|
||||||
# Set option 58 client renewal time (T1). Defaults to half of the
|
# Set option 58 client renewal time (T1). Defaults to half of the
|
||||||
# lease time if not specified. (RFC2132)
|
# lease time if not specified. (RFC2132)
|
||||||
#dhcp-option=option:T1:1m
|
#dhcp-option=option:T1,1m
|
||||||
|
|
||||||
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
# Set option 59 rebinding time (T2). Defaults to 7/8 of the
|
||||||
# lease time if not specified. (RFC2132)
|
# lease time if not specified. (RFC2132)
|
||||||
#dhcp-option=option:T2:2m
|
#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
|
||||||
@@ -436,22 +436,22 @@
|
|||||||
#dhcp-option-force=211,30i
|
#dhcp-option-force=211,30i
|
||||||
|
|
||||||
# Set the boot filename for netboot/PXE. You will only need
|
# Set the boot filename for netboot/PXE. You will only need
|
||||||
# this is you want to boot machines over the network and you will need
|
# this if you want to boot machines over the network and you will need
|
||||||
# a TFTP server; either dnsmasq's built in TFTP server or an
|
# a TFTP server; either dnsmasq's built-in TFTP server or an
|
||||||
# external one. (See below for how to enable the TFTP server.)
|
# external one. (See below for how to enable the TFTP server.)
|
||||||
#dhcp-boot=pxelinux.0
|
#dhcp-boot=pxelinux.0
|
||||||
|
|
||||||
# The same as above, but use custom tftp-server instead machine running dnsmasq
|
# The same as above, but use custom tftp-server instead machine running dnsmasq
|
||||||
#dhcp-boot=pxelinux,server.name,192.168.1.100
|
#dhcp-boot=pxelinux,server.name,192.168.1.100
|
||||||
|
|
||||||
# Boot for Etherboot gPXE. The idea is to send two different
|
# Boot for iPXE. The idea is to send two different
|
||||||
# filenames, the first loads gPXE, and the second tells gPXE what to
|
# filenames, the first loads iPXE, and the second tells iPXE what to
|
||||||
# load. The dhcp-match sets the gpxe tag for requests from gPXE.
|
# load. The dhcp-match sets the ipxe tag for requests from iPXE.
|
||||||
#dhcp-match=set:gpxe,175 # gPXE sends a 175 option.
|
#dhcp-boot=undionly.kpxe
|
||||||
#dhcp-boot=tag:!gpxe,undionly.kpxe
|
#dhcp-match=set:ipxe,175 # iPXE sends a 175 option.
|
||||||
#dhcp-boot=mybootimage
|
#dhcp-boot=tag:ipxe,http://boot.ipxe.org/demo/boot.php
|
||||||
|
|
||||||
# Encapsulated options for Etherboot gPXE. All the options are
|
# Encapsulated options for iPXE. All the options are
|
||||||
# encapsulated within option 175
|
# encapsulated within option 175
|
||||||
#dhcp-option=encap:175, 1, 5b # priority code
|
#dhcp-option=encap:175, 1, 5b # priority code
|
||||||
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
#dhcp-option=encap:175, 176, 1b # no-proxydhcp
|
||||||
@@ -547,6 +547,14 @@
|
|||||||
# http://www.isc.org/files/auth.html
|
# http://www.isc.org/files/auth.html
|
||||||
#dhcp-authoritative
|
#dhcp-authoritative
|
||||||
|
|
||||||
|
# Set the DHCP server to enable DHCPv4 Rapid Commit Option per RFC 4039.
|
||||||
|
# In this mode it will respond to a DHCPDISCOVER message including a Rapid Commit
|
||||||
|
# option with a DHCPACK including a Rapid Commit option and fully committed address
|
||||||
|
# and configuration information. This must only be enabled if either the server is
|
||||||
|
# the only server for the subnet, or multiple servers are present and they each
|
||||||
|
# commit a binding for all clients.
|
||||||
|
#dhcp-rapid-commit
|
||||||
|
|
||||||
# Run an executable when a DHCP lease is created or destroyed.
|
# Run an executable when a DHCP lease is created or destroyed.
|
||||||
# The arguments sent to the script are "add" or "del",
|
# The arguments sent to the script are "add" or "del",
|
||||||
# then the MAC address, the IP address and finally the hostname
|
# then the MAC address, the IP address and finally the hostname
|
||||||
@@ -664,3 +672,8 @@
|
|||||||
|
|
||||||
# Include all files in a directory which end in .conf
|
# Include all files in a directory which end in .conf
|
||||||
#conf-dir=/etc/dnsmasq.d/,*.conf
|
#conf-dir=/etc/dnsmasq.d/,*.conf
|
||||||
|
|
||||||
|
# If a DHCP client claims that its name is "wpad", ignore that.
|
||||||
|
# This fixes a security hole. see CERT Vulnerability VU#598349
|
||||||
|
#dhcp-name-match=set:wpad-ignore,wpad
|
||||||
|
#dhcp-ignore-names=tag:wpad-ignore
|
||||||
@@ -66,6 +66,10 @@ the repo, or get a copy using git protocol with the command
|
|||||||
|
|
||||||
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
<PRE><TT>git clone git://thekelleys.org.uk/dnsmasq.git </TT></PRE>
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
<PRE><TT>git clone http://thekelleys.org.uk/git/dnsmasq.git </TT></PRE>
|
||||||
|
|
||||||
<H2>License.</H2>
|
<H2>License.</H2>
|
||||||
Dnsmasq is distributed under the GPL, version 2 or version 3 at your discretion. See the files COPYING and COPYING-v3 in the distribution
|
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.
|
||||||
|
|||||||
+306
-204
File diff suppressed because it is too large.
Load diff
+2
-1
@@ -478,7 +478,8 @@ la traza reversa direcci
|
|||||||
.TP
|
.TP
|
||||||
.B \-c, --cache-size=<tamaño de caché>
|
.B \-c, --cache-size=<tamaño de caché>
|
||||||
Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
|
Fijar el tamaño del caché de dnsmasq. El predeterminado es 150 nombres.
|
||||||
Fijar el tamaño a cero deshabilita el caché.
|
Fijar el tamaño a cero deshabilita el caché. Nota: el gran tamaño de
|
||||||
|
caché afecta el rendimiento.
|
||||||
.TP
|
.TP
|
||||||
.B \-N, --no-negcache
|
.B \-N, --no-negcache
|
||||||
Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
|
Deshabilitar caché negativo. El caché negativo le permite a dnsmasq
|
||||||
|
|||||||
+131
-116
@@ -10,7 +10,7 @@ est un serveur à faible empreinte mémoire faisant DNS, TFTP, PXE, annonces de
|
|||||||
routeurs et DHCP. Il offre à la fois les services DNS et DHCP pour un réseau
|
routeurs et DHCP. Il offre à la fois les services DNS et DHCP pour un réseau
|
||||||
local (LAN).
|
local (LAN).
|
||||||
.PP
|
.PP
|
||||||
Dnsmasq accepte les requêtes DNS et y réponds soit en utilisant un petit cache
|
Dnsmasq accepte les requêtes DNS et y répond soit en utilisant un petit cache
|
||||||
local, soit en effectuant une requête à un serveur DNS récursif externe (par
|
local, soit en effectuant une requête à un serveur DNS récursif externe (par
|
||||||
exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
|
exemple celui de votre fournisseur d'accès internet). Il charge le contenu du
|
||||||
fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
|
fichier /etc/hosts afin que les noms locaux n'apparaissant pas dans les DNS
|
||||||
@@ -19,25 +19,25 @@ pour les hôtes présents dans le service DHCP. Il peut aussi agir en temps que
|
|||||||
serveur DNS faisant autorité pour un ou plusieurs domaines, permettant à des
|
serveur DNS faisant autorité pour un ou plusieurs domaines, permettant à des
|
||||||
noms locaux d'apparaitre dans le DNS global.
|
noms locaux d'apparaitre dans le DNS global.
|
||||||
.PP
|
.PP
|
||||||
Le serveur DHCP Dnsmasq DHCP supporte les définitions d'adresses statiques et les
|
Le serveur DHCP de Dnsmasq supporte les définitions d'adresses statiques et les
|
||||||
réseaux multiples. Il fournit par défaut un jeu raisonnable de paramètres DHCP,
|
réseaux multiples. Il fournit par défaut un jeu raisonnable de paramètres DHCP,
|
||||||
et peut être configuré pour fournir n'importe quelle option DHCP.
|
et peut être configuré pour fournir n'importe quelle option DHCP.
|
||||||
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
|
Il inclut un serveur TFTP sécurisé en lecture seule permettant le démarrage via
|
||||||
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. Le
|
le réseau/PXE de clients DHCP et supporte également le protocole BOOTP. Le
|
||||||
support PXE est complet, et comprend un mode proxy permettant de fournir des
|
support PXE est complet, et comprend un mode proxy permettant de fournir des
|
||||||
informations PXE aux clients alors que l'allocation DHCP est effectuée par un
|
informations PXE aux clients alors que l'allocation d'adresse via DHCP est
|
||||||
autre serveur.
|
effectuée par un autre serveur.
|
||||||
.PP
|
.PP
|
||||||
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionalités
|
Le serveur DHCPv6 de dnsmasq possède non seulement les mêmes fonctionnalités
|
||||||
que le serveur DHCPv4, mais aussi le support des annonces de routeurs ainsi
|
que le serveur DHCPv4, mais aussi le support des annonces de routeurs ainsi
|
||||||
qu'une fonctionalité permettant l'addition de ressources AAAA pour des
|
qu'une fonctionnalité permettant l'addition de ressources AAAA pour des
|
||||||
clients utilisant DHCPv4 et la configuration IPv6 sans état (stateless
|
clients utilisant DHCPv4 et la configuration IPv6 sans état (stateless
|
||||||
autoconfiguration).
|
autoconfiguration).
|
||||||
Il inclut le support d'allocations d'adresses (à la fois en DHCPv6 et en
|
Il inclut le support d'allocations d'adresses (à la fois en DHCPv6 et en
|
||||||
annonces de routeurs - RA) pour des sous-réseaux dynamiquement délégués via
|
annonces de routeurs - RA) pour des sous-réseaux dynamiquement délégués via
|
||||||
une délégation de préfixe DHCPv6.
|
une délégation de préfixe DHCPv6.
|
||||||
.PP
|
.PP
|
||||||
Dnsmasq est developpé pour de petits systèmes embarqués. It tends à avoir
|
Dnsmasq est développé pour de petits systèmes embarqués. Il tend à avoir
|
||||||
l'empreinte mémoire la plus faible possible pour les fonctions supportées,
|
l'empreinte mémoire la plus faible possible pour les fonctions supportées,
|
||||||
et permet d'exclure les fonctions inutiles du binaire compilé.
|
et permet d'exclure les fonctions inutiles du binaire compilé.
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
@@ -46,16 +46,23 @@ Dans ce cas, la fonction correspondante sera désactivée. Par exemple
|
|||||||
.B --pid-file=
|
.B --pid-file=
|
||||||
(sans paramètre après le =) désactive l'écriture du fichier PID.
|
(sans paramètre après le =) désactive l'écriture du fichier PID.
|
||||||
Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU
|
Sur BSD, à moins que le logiciel ne soit compilé avec la bibliothèque GNU
|
||||||
getopt, la forme longue des options ne fonctionne pas en ligne de commande; Elle
|
getopt, la forme longue des options ne fonctionne pas en ligne de commande; elle
|
||||||
est toujours supportée dans le fichier de configuration.
|
est toujours supportée dans le fichier de configuration.
|
||||||
.TP
|
.TP
|
||||||
.B --test
|
.B --test
|
||||||
Vérifie la syntaxe du ou des fichiers de configurations. Se termine avec le
|
Vérifie la syntaxe du ou des fichiers de configuration. Se termine avec le
|
||||||
code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
|
code de retour 0 si tout est OK, ou un code différent de 0 dans le cas
|
||||||
contraire. Ne démarre pas Dnsmasq.
|
contraire. Ne démarre pas Dnsmasq.
|
||||||
.TP
|
.TP
|
||||||
|
.B \-w, --help
|
||||||
|
Affiche toutes les options de ligne de commande.
|
||||||
|
.B --help dhcp
|
||||||
|
affiche les options de configuration connues pour DHCPv4, et
|
||||||
|
.B --help dhcp6
|
||||||
|
affiche les options de configuration connues pour DHCPv6.
|
||||||
|
.TP
|
||||||
.B \-h, --no-hosts
|
.B \-h, --no-hosts
|
||||||
Ne pas charger les noms du fichier /etc/hosts.
|
Ne pas charger les noms d'hôtes du fichier /etc/hosts.
|
||||||
.TP
|
.TP
|
||||||
.B \-H, --addn-hosts=<fichier>
|
.B \-H, --addn-hosts=<fichier>
|
||||||
Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts.
|
Fichiers d'hôtes additionnels. Lire le fichier spécifié en plus de /etc/hosts.
|
||||||
@@ -68,7 +75,7 @@ fichiers contenus dans ce répertoire.
|
|||||||
.B \-E, --expand-hosts
|
.B \-E, --expand-hosts
|
||||||
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
|
Ajoute le nom de domaine aux noms simples (ne contenant pas de point dans le
|
||||||
nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
|
nom) contenus dans le fichier /etc/hosts, de la même façon que pour le service
|
||||||
DHCP. Notez que cela ne s'applique pas au nom de domaine dans les CNAME, les
|
DHCP. Notez que cela ne s'applique pas aux noms de domaine dans les CNAME, les
|
||||||
enregistrements PTR, TXT, etc...
|
enregistrements PTR, TXT, etc...
|
||||||
.TP
|
.TP
|
||||||
.B \-T, --local-ttl=<durée>
|
.B \-T, --local-ttl=<durée>
|
||||||
@@ -86,7 +93,7 @@ Les réponses négatives provenant des serveurs amonts contiennent normalement
|
|||||||
une information de durée de vie (time-to-live) dans les enregistrements SOA,
|
une information de durée de vie (time-to-live) dans les enregistrements SOA,
|
||||||
information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
|
information dont dnsmasq se sert pour mettre la réponse en cache. Si la réponse
|
||||||
du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
|
du serveur amont omet cette information, dnsmasq ne cache pas la réponse. Cette
|
||||||
option permet de doner une valeur de durée de vie par défaut (en secondes) que
|
option permet de donner une valeur de durée de vie par défaut (en secondes) que
|
||||||
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
|
dnsmasq utilise pour mettre les réponses négatives dans son cache, même en
|
||||||
l'absence d'enregistrement SOA.
|
l'absence d'enregistrement SOA.
|
||||||
.TP
|
.TP
|
||||||
@@ -194,7 +201,7 @@ au dessus de la valeur spécifiée. Utile pour des systèmes derrière des dispo
|
|||||||
garde-barrières ("firewalls").
|
garde-barrières ("firewalls").
|
||||||
.TP
|
.TP
|
||||||
.B \-i, --interface=<nom d'interface>
|
.B \-i, --interface=<nom d'interface>
|
||||||
N'écouter que sur l'interface réseau spécifiée. Dnsmasq aujoute automatiquement
|
N'écouter que sur l'interface réseau spécifiée. Dnsmasq ajoute automatiquement
|
||||||
l'interface locale ("loopback") à la liste des interfaces lorsque l'option
|
l'interface locale ("loopback") à la liste des interfaces lorsque l'option
|
||||||
.B --interface
|
.B --interface
|
||||||
est utilisée.
|
est utilisée.
|
||||||
@@ -205,13 +212,13 @@ ou
|
|||||||
n'est donnée, Dnsmasq écoutera sur toutes les interfaces disponibles sauf
|
n'est donnée, Dnsmasq écoutera sur toutes les interfaces disponibles sauf
|
||||||
celle(s) spécifiée(s) par l'option
|
celle(s) spécifiée(s) par l'option
|
||||||
.B --except-interface.
|
.B --except-interface.
|
||||||
Les alias d'interfaces IP (e-g "eth1:0") ne peuvent être utilisés ni avec
|
Les alias d'interfaces IP (par exemple "eth1:0") ne peuvent être utilisés ni avec
|
||||||
.B --interface
|
.B --interface
|
||||||
ni
|
ni
|
||||||
.B \--except-interface.
|
.B \--except-interface.
|
||||||
Utiliser l'option
|
Utiliser l'option
|
||||||
.B --listen-address
|
.B --listen-address
|
||||||
à la place. Un simple joker, consistant d'un '*' final, peut-être utilisé dans
|
à la place. Un simple joker, consistant en un '*' final, peut être utilisé dans
|
||||||
les options
|
les options
|
||||||
.B \--interface
|
.B \--interface
|
||||||
et
|
et
|
||||||
@@ -229,10 +236,10 @@ sont fournies n'importe pas, et que l'option
|
|||||||
.B --except-interface
|
.B --except-interface
|
||||||
l'emporte toujours sur les autres.
|
l'emporte toujours sur les autres.
|
||||||
.TP
|
.TP
|
||||||
.B --auth-server=<domaine>,<interface>|<addresse IP>
|
.B --auth-server=<domaine>,<interface>|<adresse IP>
|
||||||
Active le mode DNS faisant autorité pour les requêtes arrivant sur cette
|
Active le mode DNS faisant autorité pour les requêtes arrivant sur cette
|
||||||
interface ou sur cette adresse. Noter que l'interface ou l'adresse n'ont
|
interface ou sur cette adresse. Noter que l'interface ou l'adresse n'ont
|
||||||
pas besoin d'être mentionées ni dans
|
pas besoin d'être mentionnées ni dans
|
||||||
.B --interface
|
.B --interface
|
||||||
ni dans
|
ni dans
|
||||||
.B --listen-address
|
.B --listen-address
|
||||||
@@ -253,7 +260,7 @@ Ecouter sur la ou les adresse(s) IP spécifiée(s). Les options
|
|||||||
.B \--interface
|
.B \--interface
|
||||||
et
|
et
|
||||||
.B \--listen-address
|
.B \--listen-address
|
||||||
peuvent-être spécifiées simultanément, auquel cas un jeu d'interfaces et
|
peuvent être spécifiées simultanément, auquel cas un jeu d'interfaces et
|
||||||
d'adresses seront utilisées. Notez que si
|
d'adresses seront utilisées. Notez que si
|
||||||
aucune option
|
aucune option
|
||||||
.B \--interface
|
.B \--interface
|
||||||
@@ -265,7 +272,7 @@ nécessaire de fournir explicitement son adresse IP, 127.0.0.1 via l'option
|
|||||||
.B \--listen-address.
|
.B \--listen-address.
|
||||||
.TP
|
.TP
|
||||||
.B \-z, --bind-interfaces
|
.B \-z, --bind-interfaces
|
||||||
Sur les systèmes qui le supporte, Dnsmasq s'associe avec l'interface joker
|
Sur les systèmes qui le supportent, Dnsmasq s'associe avec l'interface joker
|
||||||
("wildcard"), même lorsqu'il ne doit écouter que sur certaines interfaces. Par
|
("wildcard"), même lorsqu'il ne doit écouter que sur certaines interfaces. Par
|
||||||
la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette
|
la suite, il rejette les requêtes auxquelles il ne doit pas répondre. Cette
|
||||||
situation présente l'avantage de fonctionner même lorsque les interfaces vont
|
situation présente l'avantage de fonctionner même lorsque les interfaces vont
|
||||||
@@ -302,7 +309,7 @@ le réseau auquel ils sont attachés). Cette possibilité est actuellement limit
|
|||||||
.TP
|
.TP
|
||||||
.B \-b, --bogus-priv
|
.B \-b, --bogus-priv
|
||||||
Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS
|
Fausse résolution inverse pour les réseaux privés. Toutes les requêtes DNS
|
||||||
inverses pour des adresses IP privées (ie 192.168.x.x, etc...) qui ne sont pas
|
inverses pour des adresses IP privées (192.168.x.x, etc...) qui ne sont pas
|
||||||
trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
|
trouvées dans /etc/hosts ou dans le fichier de baux DHCP se voient retournées
|
||||||
une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
|
une réponse "pas de tel domaine" ("no such domain") au lieu d'être transmises
|
||||||
aux serveurs de nom amont ("upstream server").
|
aux serveurs de nom amont ("upstream server").
|
||||||
@@ -317,7 +324,7 @@ modifiera 1.2.3.56 en 6.7.8.56 et 1.2.3.67 en 6.7.8.67.
|
|||||||
Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent
|
Cette fonctionnalité correspond à ce que les routeurs Cisco PIX appellent
|
||||||
"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
|
"bidouillage DNS" ("DNS doctoring"). Si l'ancienne IP est donnée sous la forme
|
||||||
d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
|
d'une gamme d'adresses, alors seules les adresses dans cette gamme seront
|
||||||
réecrites, et non le sous-réseau dans son ensemble. Ainsi,
|
réécrites, et non le sous-réseau dans son ensemble. Ainsi,
|
||||||
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
.B --alias=192.168.0.10-192.168.0.40,10.0.0.0,255.255.255.0
|
||||||
fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40
|
fait correspondre 192.168.0.10->192.168.0.40 à 10.0.0.10->10.0.0.40
|
||||||
.TP
|
.TP
|
||||||
@@ -380,7 +387,7 @@ effectuer ses requêtes à tous les serveurs disponibles. Le résultat renvoyé
|
|||||||
au client sera celui fournit par le premier serveur ayant répondu.
|
au client sera celui fournit par le premier serveur ayant répondu.
|
||||||
.TP
|
.TP
|
||||||
.B --stop-dns-rebind
|
.B --stop-dns-rebind
|
||||||
Rejete (et enregistre dans le journal d'activité) les adresses dans la gamme
|
Rejette (et enregistre dans le journal d'activité) les adresses dans la gamme
|
||||||
d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les
|
d'adresses IP privée (au sens RFC1918) qui pourraient être renvoyées par les
|
||||||
serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant
|
serveurs amonts suite à une résolution de nom. Cela bloque les attaques cherchant
|
||||||
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
|
à détourner de leur usage les logiciels de navigation web ('browser') en s'en
|
||||||
@@ -389,13 +396,13 @@ servant pour découvrir les machines situées sur le réseau local.
|
|||||||
.B --rebind-localhost-ok
|
.B --rebind-localhost-ok
|
||||||
Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
|
Exclue 127.0.0/8 des vérifications de réassociation DNS. Cette gamme d'adresses
|
||||||
est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
|
est retournée par les serveurs Realtime Blackhole (RBL, utilisés dans la
|
||||||
lutte contre le spam), la bloquer peut entraîner des disfonctionnements de ces
|
lutte contre le spam), la bloquer peut entraîner des dysfonctionnements de ces
|
||||||
services.
|
services.
|
||||||
.TP
|
.TP
|
||||||
.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
|
.B --rebind-domain-ok=[<domaine>]|[[/<domaine>/[<domaine>/]
|
||||||
Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
|
Ne pas détecter ni bloquer les actions de type dns-rebind pour ces domaines.
|
||||||
Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
|
Cette option peut prendre comme valeur soit un nom de domaine soit plusieurs
|
||||||
noms de domains entourés par des '/', selon une syntaxe similaire à l'option
|
noms de domaine entourés par des '/', selon une syntaxe similaire à l'option
|
||||||
--server, c-à-d :
|
--server, c-à-d :
|
||||||
.B --rebind-domain-ok=/domaine1/domaine2/domaine3/
|
.B --rebind-domain-ok=/domaine1/domaine2/domaine3/
|
||||||
.TP
|
.TP
|
||||||
@@ -474,7 +481,7 @@ serveur de nom. Il doit s'agir d'une des adresses IP appartenant à la machine s
|
|||||||
laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
|
laquelle tourne Dnsmasq ou sinon la ligne sera ignorée et une erreur sera
|
||||||
consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom
|
consignée dans le journal des événements, ou alors d'un nom d'interface. Si un nom
|
||||||
d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
|
d'interface est donné, alors les requêtes vers le serveur de nom seront envoyées
|
||||||
depuis cette interface; si une adresse ip est donnée, alors l'adresse source de
|
depuis cette interface; si une adresse IP est donnée, alors l'adresse source de
|
||||||
la requête sera l'adresse en question. L'option query-port est ignorée pour tous
|
la requête sera l'adresse en question. L'option query-port est ignorée pour tous
|
||||||
les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
|
les serveurs ayant une adresse source spécifiée, mais il est possible de la donner
|
||||||
directement dans la spécification de l'adresse source. Forcer les requêtes à être
|
directement dans la spécification de l'adresse source. Forcer les requêtes à être
|
||||||
@@ -510,7 +517,7 @@ d'IP netfilter (ipset) indiqués. Domaines et sous-domaines sont résolus de la
|
|||||||
même façon que pour --address. Ces groupes d'IP doivent déjà exister. Voir
|
même façon que pour --address. Ces groupes d'IP doivent déjà exister. Voir
|
||||||
ipset(8) pour plus de détails.
|
ipset(8) pour plus de détails.
|
||||||
.TP
|
.TP
|
||||||
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préference>]
|
.B \-m, --mx-host=<nom de l'hôte>[[,<nom du MX>],<préférence>]
|
||||||
Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
|
Spécifie un enregistrement de type MX pour <nom de l'hôte> retournant le nom
|
||||||
donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
|
donné dans <nom du MX> (s'il est présent), ou sinon le nom spécifié dans
|
||||||
l'option
|
l'option
|
||||||
@@ -612,7 +619,7 @@ l'enregistrement est donnée dans les données hexadécimales, qui peuvent
|
|||||||
être de la forme 01:23:45, 01 23 45,+012345 ou n'importe quelle combinaison.
|
être de la forme 01:23:45, 01 23 45,+012345 ou n'importe quelle combinaison.
|
||||||
.TP
|
.TP
|
||||||
.B --interface-name=<nom>,<interface>
|
.B --interface-name=<nom>,<interface>
|
||||||
Définit un entregistrement DNS associant le nom avec l'adresse primaire sur
|
Définit un enregistrement DNS associant le nom avec l'adresse primaire sur
|
||||||
l'interface donnée en argument. Cette option spécifie un enregistrement de type
|
l'interface donnée en argument. Cette option spécifie un enregistrement de type
|
||||||
A pour le nom donné en argument de la même façon que s'il était défini par une
|
A pour le nom donné en argument de la même façon que s'il était défini par une
|
||||||
ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de
|
ligne de /etc/hosts, sauf que l'adresse n'est pas constante mais dépendante de
|
||||||
@@ -638,7 +645,7 @@ IPv6 pouvant commencer par '::', mais les noms DNS ne pouvant pas commencer
|
|||||||
par '-', si aucun préfixe n'est donné, un zéro est ajouté en début de nom.
|
par '-', si aucun préfixe n'est donné, un zéro est ajouté en début de nom.
|
||||||
Ainsi, ::1 devient 0--1.
|
Ainsi, ::1 devient 0--1.
|
||||||
|
|
||||||
La plage d'adresses peut-être de la forme
|
La plage d'adresses peut être de la forme
|
||||||
<adresse IP>,<adresse IP> ou <adresse IP>/<masque réseau>
|
<adresse IP>,<adresse IP> ou <adresse IP>/<masque réseau>
|
||||||
.TP
|
.TP
|
||||||
.B --add-mac
|
.B --add-mac
|
||||||
@@ -647,7 +654,7 @@ amonts. Cela peut être utilisé dans un but de filtrage DNS par les serveurs
|
|||||||
amonts. L'adresse MAC peut uniquement être ajoutée si le requêteur est sur le
|
amonts. L'adresse MAC peut uniquement être ajoutée si le requêteur est sur le
|
||||||
même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
|
même sous-réseau que le serveur dnsmasq. Veuillez noter que le mécanisme
|
||||||
utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
|
utilisé pour effectuer cela (une option EDNS0) n'est pas encore standardisée,
|
||||||
aussi cette fonctionalité doit être considérée comme expérimentale. Notez
|
aussi cette fonctionnalité doit être considérée comme expérimentale. Notez
|
||||||
également qu'exposer les adresses MAC de la sorte peut avoir des implications
|
également qu'exposer les adresses MAC de la sorte peut avoir des implications
|
||||||
en termes de sécurité et de vie privée. L'avertissement donné pour --add-subnet
|
en termes de sécurité et de vie privée. L'avertissement donné pour --add-subnet
|
||||||
s'applique également ici.
|
s'applique également ici.
|
||||||
@@ -659,19 +666,20 @@ longueur du préfixe : 32 (ou 128 dans le cas d'IPv6) transmet la totalité
|
|||||||
de l'adresse, 0 n'en transmet aucun mais marque néanmoins la requête ce qui
|
de l'adresse, 0 n'en transmet aucun mais marque néanmoins la requête ce qui
|
||||||
fait qu'aucun serveur amont ne rajoutera d'adresse client. La valeur par
|
fait qu'aucun serveur amont ne rajoutera d'adresse client. La valeur par
|
||||||
défaut est zéro et pour IPv4 et pour IPv6. A noter que les serveurs amonts
|
défaut est zéro et pour IPv4 et pour IPv6. A noter que les serveurs amonts
|
||||||
peuvent-être configurés pour retourner des valeurs différentes en fonction
|
peuvent être configurés pour retourner des valeurs différentes en fonction
|
||||||
de cette information mais que le cache de dnsmasq n'en tient pas compte.
|
de cette information mais que le cache de dnsmasq n'en tient pas compte.
|
||||||
Si une instance de dnsmasq est configurée de telle maniêre que des valeurs
|
Si une instance de dnsmasq est configurée de telle manière que des valeurs
|
||||||
différentes pourraient-être rencontrés, alors le cache devrait être désactivé.
|
différentes pourraient être rencontrées, alors le cache devrait être désactivé.
|
||||||
.TP
|
.TP
|
||||||
.B \-c, --cache-size=<taille>
|
.B \-c, --cache-size=<taille>
|
||||||
Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
|
Définit la taille du cache de Dnsmasq. La valeur par défaut est de 150 noms.
|
||||||
Définir une valeur de zéro désactive le cache.
|
Définir une valeur de zéro désactive le cache. Remarque: la taille importante
|
||||||
|
du cache a un impact sur les performances.
|
||||||
.TP
|
.TP
|
||||||
.B \-N, --no-negcache
|
.B \-N, --no-negcache
|
||||||
Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir
|
Désactive le "cache négatif". Le "cache négatif" permet à Dnsmasq de se souvenir
|
||||||
des réponses de type "no such domain" fournies par les serveurs DNS en amont et
|
des réponses de type "no such domain" fournies par les serveurs DNS en amont et
|
||||||
de fournir les réponses sans avoir à re-transmettre les requêtes aux serveurs
|
de fournir les réponses sans avoir à retransmettre les requêtes aux serveurs
|
||||||
amont.
|
amont.
|
||||||
.TP
|
.TP
|
||||||
.B \-0, --dns-forward-max=<nombre de requêtes>
|
.B \-0, --dns-forward-max=<nombre de requêtes>
|
||||||
@@ -683,17 +691,17 @@ son journal des requêtes, ce qui peut générer un nombre important de requête
|
|||||||
simultanées.
|
simultanées.
|
||||||
.TP
|
.TP
|
||||||
.B --proxy-dnssec
|
.B --proxy-dnssec
|
||||||
Un resolveur sur une machine cliente peut effectuer la validation DNSSEC de
|
Un résolveur sur une machine cliente peut effectuer la validation DNSSEC de
|
||||||
deux façons : il peut effectuer lui-même les opérations de chiffrements sur
|
deux façons : il peut effectuer lui-même les opérations de chiffrements sur
|
||||||
la réponse reçue, ou il peut laisser le serveur récursif amont faire la
|
la réponse reçue, ou il peut laisser le serveur récursif amont faire la
|
||||||
validation et positionner un drapeau dans la réponse au cas où celle-ci est
|
validation et positionner un drapeau dans la réponse au cas où celle-ci est
|
||||||
correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer
|
correcte. Dnsmasq n'est pas un validateur DNSSEC, aussi il ne peut effectuer
|
||||||
la validation comme un serveur de nom récursif, cependant il peut retransmettre
|
la validation comme un serveur de nom récursif, cependant il peut retransmettre
|
||||||
les résultats de validation de ses serveurs amonts. Cette option permet
|
les résultats de validation de ses serveurs amonts. Cette option permet
|
||||||
l'activation de cette fonctionalité. Vous ne devriez utiliser cela que si vous
|
l'activation de cette fonctionnalité. Vous ne devriez utiliser cela que si vous
|
||||||
faites confiance aux serveurs amonts
|
faites confiance aux serveurs amonts
|
||||||
.I ainsi que le réseau entre vous et eux.
|
.I ainsi que le réseau entre vous et eux.
|
||||||
Si vous utilisez le premier mode DNSSEC, la validation par le resolveur des
|
Si vous utilisez le premier mode DNSSEC, la validation par le résolveur des
|
||||||
clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
|
clients, cette option n'est pas requise. Dnsmasq retourne toujours toutes les
|
||||||
données nécessaires par un client pour effectuer la validation lui-même.
|
données nécessaires par un client pour effectuer la validation lui-même.
|
||||||
.TP
|
.TP
|
||||||
@@ -703,12 +711,12 @@ Définie une zone DNS pour laquelle dnsmasq agit en temps que serveur faisant
|
|||||||
autorité. Les enregistrements DNS définis localement et correspondant à ce
|
autorité. Les enregistrements DNS définis localement et correspondant à ce
|
||||||
domaine seront fournis. Les enregistrements A et AAAA doivent se situer dans
|
domaine seront fournis. Les enregistrements A et AAAA doivent se situer dans
|
||||||
l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage DHCP
|
l'un des sous-réseaux définis, ou dans un réseau correspondant à une plage DHCP
|
||||||
(ce comportement peut-être désactivé par
|
(ce comportement peut être désactivé par
|
||||||
.B constructor-noauth:
|
.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 ip6.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
|
||||||
conforme au RFC 2317.
|
conforme au RFC 2317.
|
||||||
.TP
|
.TP
|
||||||
@@ -719,7 +727,7 @@ optionnel, les valeurs par défaut devant convenir à la majorité des cas.
|
|||||||
.TP
|
.TP
|
||||||
.B --auth-sec-servers=<domaine>[,<domaine>[,<domaine>...]]
|
.B --auth-sec-servers=<domaine>[,<domaine>[,<domaine>...]]
|
||||||
Spécifie un ou plusieurs serveur de nom secondaires pour une zone pour
|
Spécifie un ou plusieurs serveur de nom secondaires pour une zone pour
|
||||||
laquelle dnsmasq fait autorité. Ces serveurs doivent-être configurés pour
|
laquelle dnsmasq fait autorité. Ces serveurs doivent être configurés pour
|
||||||
récupérer auprès de dnsmasq les informations liées à la zone au travers d'un
|
récupérer auprès de dnsmasq les informations liées à la zone au travers d'un
|
||||||
transfert de zone, et répondre aux requêtes pour toutes les zones pour
|
transfert de zone, et répondre aux requêtes pour toutes les zones pour
|
||||||
lesquelles dnsmasq fait autorité.
|
lesquelles dnsmasq fait autorité.
|
||||||
@@ -733,7 +741,7 @@ seront acceptées pour tous les serveurs secondaires.
|
|||||||
.B --conntrack
|
.B --conntrack
|
||||||
Lis le marquage de suivi de connexion Linux associé aux requêtes DNS entrantes
|
Lis le marquage de suivi de connexion Linux associé aux requêtes DNS entrantes
|
||||||
et positionne la même marque au trafic amont utilisé pour répondre à ces
|
et positionne la même marque au trafic amont utilisé pour répondre à ces
|
||||||
requétes. Cela permet au trafic généré par Dnsmasq d'étre associé aux requêtes
|
requêtes. Cela permet au trafic généré par Dnsmasq d'être associé aux requêtes
|
||||||
l'ayant déclenché, ce qui est pratique pour la gestion de la bande passante
|
l'ayant déclenché, ce qui est pratique pour la gestion de la bande passante
|
||||||
(accounting) et le filtrage (firewall). Dnsmasq doit pour cela être compilé
|
(accounting) et le filtrage (firewall). Dnsmasq doit pour cela être compilé
|
||||||
avec le support conntrack, le noyau doit également inclure conntrack et être
|
avec le support conntrack, le noyau doit également inclure conntrack et être
|
||||||
@@ -742,7 +750,7 @@ configuré pour cela. Cette option ne peut pas être combinée avec
|
|||||||
.TP
|
.TP
|
||||||
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
|
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse de début>[,<adresse de fin>][,<mode>][,<masque de réseau>[,<broadcast>]][,<durée de bail>]
|
||||||
.TP
|
.TP
|
||||||
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<addresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
|
.B \-F, --dhcp-range=[tag:<label>[,tag:<label>],][set:<label>],]<adresse IPv6 de début>[,<adresse IPv6 de fin>|constructor:<interface>][,<mode>][,<longueur de préfixe>][,<durée de bail>]
|
||||||
|
|
||||||
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
|
Active le serveur DHCP. Les adresses seront données dans la plage comprise entre
|
||||||
<adresse de début> et <adresse de fin> et à partir des adresses définies
|
<adresse de début> et <adresse de fin> et à partir des adresses définies
|
||||||
@@ -755,7 +763,7 @@ durée indéterminée. Si aucune valeur n'est donnée, une durée de bail par d
|
|||||||
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
|
de une heure est appliquée. La valeur minimum pour un bail DHCP est de 2
|
||||||
minutes.
|
minutes.
|
||||||
|
|
||||||
Pour les plages IPv6, la durée de bail peut-être égale au mot-clef "deprecated"
|
Pour les plages IPv6, la durée de bail peut être égale au mot-clef "deprecated"
|
||||||
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
|
(obsolète); Cela positionne la durée de vie préférée envoyée dans les baux DHCP
|
||||||
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
|
ou les annonces routeurs à zéro, ce qui incite les clients à utiliser d'autres
|
||||||
adresses autant que possible, pour toute nouvelle connexion, en préalable à
|
adresses autant que possible, pour toute nouvelle connexion, en préalable à
|
||||||
@@ -795,7 +803,7 @@ adresses assignées à l'interface. Par exemple
|
|||||||
provoque la recherche d'adresses de la forme <réseau>::1 sur eth0 et crée une
|
provoque la recherche d'adresses de la forme <réseau>::1 sur eth0 et crée une
|
||||||
plage allant de <réseau>::1 à <réseau>:400. Si une interface est assignée à
|
plage allant de <réseau>::1 à <réseau>:400. Si une interface est assignée à
|
||||||
plus d'un réseau, les plages correspondantes seront automatiquement créées,
|
plus d'un réseau, les plages correspondantes seront automatiquement créées,
|
||||||
rendues obsolètes puis supprimées lorsque l'adress est rendue obsolète puis
|
rendues obsolètes puis supprimées lorsque l'adresse est rendue obsolète puis
|
||||||
supprimée. Le nom de l'interface peut être spécifié avec un caractère joker '*'
|
supprimée. Le nom de l'interface peut être spécifié avec un caractère joker '*'
|
||||||
final.
|
final.
|
||||||
|
|
||||||
@@ -809,7 +817,7 @@ obsolètes ne conviennent pas.
|
|||||||
|
|
||||||
Si une plage dhcp-range est uniquement utilisée pour du DHCP sans-état
|
Si une plage dhcp-range est uniquement utilisée pour du DHCP sans-état
|
||||||
("stateless") ou de l'autoconfiguration sans état ("SLAAC"), alors l'adresse
|
("stateless") ou de l'autoconfiguration sans état ("SLAAC"), alors l'adresse
|
||||||
peut-être indiquée sous la forme '::'
|
peut être indiquée sous la forme '::'
|
||||||
|
|
||||||
.B --dhcp-range=::,constructor:eth0
|
.B --dhcp-range=::,constructor:eth0
|
||||||
|
|
||||||
@@ -851,7 +859,7 @@ et
|
|||||||
.B pxe-service
|
.B pxe-service
|
||||||
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, off-link.
|
.B ra-only, slaac, ra-names, ra-stateless, off-link.
|
||||||
|
|
||||||
.B ra-only
|
.B ra-only
|
||||||
@@ -883,7 +891,7 @@ connectés (et non ceux pour lesquels DHCP se fait via relai), et ne
|
|||||||
fonctionnera pas si un hôte utilise les "extensions de vie privée"
|
fonctionnera pas si un hôte utilise les "extensions de vie privée"
|
||||||
("privacy extensions").
|
("privacy extensions").
|
||||||
.B ra-names
|
.B ra-names
|
||||||
peut-être combiné avec
|
peut être combiné avec
|
||||||
.B ra-stateless
|
.B ra-stateless
|
||||||
et
|
et
|
||||||
.B slaac.
|
.B slaac.
|
||||||
@@ -914,7 +922,7 @@ sous-réseau qu'une plage dhcp-range valide. Pour les sous-réseaux qui n'ont pa
|
|||||||
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
|
besoin d'adresses dynamiquement allouées, utiliser le mot-clef "static" dans la
|
||||||
déclaration de plage d'adresses dhcp-range.
|
déclaration de plage d'adresses dhcp-range.
|
||||||
|
|
||||||
Il est possible d'utiliser des identifiants clients (appellé "DUID client" dans
|
Il est possible d'utiliser des identifiants clients (appelés "DUID client" dans
|
||||||
le monde IPv6) plutôt que des adresses matérielles pour identifier les hôtes,
|
le monde IPv6) plutôt que des adresses matérielles pour identifier les hôtes,
|
||||||
en préfixant ceux-ci par 'id:'. Ainsi,
|
en préfixant ceux-ci par 'id:'. Ainsi,
|
||||||
.B --dhcp-host=id:01:02:03:04,.....
|
.B --dhcp-host=id:01:02:03:04,.....
|
||||||
@@ -926,7 +934,7 @@ ceci :
|
|||||||
Un seul
|
Un seul
|
||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
peut contenir une adresse IPv4, une adresse IPv6, ou les deux en même temps.
|
peut contenir une adresse IPv4, une adresse IPv6, ou les deux en même temps.
|
||||||
Les adresses IPv6 doivent-être mises entre crochets comme suit :
|
Les adresses IPv6 doivent être mises entre crochets comme suit :
|
||||||
.B --dhcp-host=laptop,[1234::56]
|
.B --dhcp-host=laptop,[1234::56]
|
||||||
Les adresses IPv6 peuvent ne contenir que la partie identifiant de client :
|
Les adresses IPv6 peuvent ne contenir que la partie identifiant de client :
|
||||||
.B --dhcp-host=laptop,[::56]
|
.B --dhcp-host=laptop,[::56]
|
||||||
@@ -945,7 +953,7 @@ identifiant client mais pas les autres.
|
|||||||
Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un
|
Si un nom apparaît dans /etc/hosts, l'adresse associée peut être allouée à un
|
||||||
bail DHCP mais seulement si une option
|
bail DHCP mais seulement si une option
|
||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut-être donné dans
|
spécifiant le nom existe par ailleurs. Seul un nom d'hôte peut être donné dans
|
||||||
une option
|
une option
|
||||||
.B dhcp-host
|
.B dhcp-host
|
||||||
, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
|
, mais les alias sont possibles au travers de l'utilisation des CNAMEs. (Voir
|
||||||
@@ -973,7 +981,7 @@ Les adresses ethernet (mais pas les identifiants clients) peuvent être définie
|
|||||||
avec des octets joker, ainsi par exemple
|
avec des octets joker, ainsi par exemple
|
||||||
.B --dhcp-host=00:20:e0:3b:13:*,ignore
|
.B --dhcp-host=00:20:e0:3b:13:*,ignore
|
||||||
demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter
|
demande à Dnsmasq d'ignorer une gamme d'adresses matérielles. Il est à noter
|
||||||
que "*" doit-être précédé d'un caractère d'échappement ou mis entre guillemets
|
que "*" doit être précédé d'un caractère d'échappement ou mis entre guillemets
|
||||||
lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
|
lorsque spécifié en option de ligne de commande, mais pas dans le fichier de
|
||||||
configuration.
|
configuration.
|
||||||
|
|
||||||
@@ -1059,14 +1067,14 @@ qu'aux réseaux dont tous les labels coïncident avec ceux de la requête.
|
|||||||
Un traitement spécial est effectué sur les chaînes de caractères fournies pour
|
Un traitement spécial est effectué sur les chaînes de caractères fournies pour
|
||||||
l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les
|
l'option 119, conformément à la RFC 3397. Les chaînes de caractères ou les
|
||||||
adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments
|
adresses IP sous forme de 4 chiffres séparés par des points donnés en arguments
|
||||||
de l'option 120 sont traités conforméments à la RFC 3361. Les adresses IP sous
|
de l'option 120 sont traités conformément à la RFC 3361. Les adresses IP sous
|
||||||
forme de 4 chiffres séparés par des points suivies par une barre montante "/",
|
forme de 4 chiffres séparés par des points suivies par une barre montante "/",
|
||||||
puis une taille de masque sont encodés conforméments à la RFC 3442.
|
puis une taille de masque sont encodés conformément à la RFC 3442.
|
||||||
|
|
||||||
Les options IPv6 sont fournies en utilisant le mot-clef
|
Les options IPv6 sont fournies en utilisant le mot-clef
|
||||||
.B option6:
|
.B option6:
|
||||||
suivi par le numéro d'option ou le nom d'option. L'espace de nommage des options
|
suivi par le numéro d'option ou le nom d'option. L'espace de nommage des options
|
||||||
IPv6 est disjint de l'espace de nommage des options IPv4. Les adresses IPv6
|
IPv6 est disjoint de l'espace de nommage des options IPv4. Les adresses IPv6
|
||||||
en option doivent être entourées de crochets, comme par exemple :
|
en option doivent être entourées de crochets, comme par exemple :
|
||||||
.B --dhcp-option=option6:ntp-server,[1234::56]
|
.B --dhcp-option=option6:ntp-server,[1234::56]
|
||||||
|
|
||||||
@@ -1075,7 +1083,7 @@ adéquat sont envoyées pour un numéro d'option donné, il est tout à fait pos
|
|||||||
de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation
|
de persuader Dnsmasq de générer des paquets DHCP illégaux par une utilisation
|
||||||
incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq
|
incorrecte de cette option. Lorsque la valeur est un nombre décimal, Dnsmasq
|
||||||
doit déterminer la taille des données. Cela est fait en examinant le numéro de
|
doit déterminer la taille des données. Cela est fait en examinant le numéro de
|
||||||
l'option et/ou la valeur, mais peut-être évité en rajoutant un suffixe d'une
|
l'option et/ou la valeur, mais peut être évité en rajoutant un suffixe d'une
|
||||||
lettre comme suit :
|
lettre comme suit :
|
||||||
b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des
|
b = un octet, s = 2 octets, i = 4 octets. Cela sert essentiellement pour des
|
||||||
options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles
|
options encapsulées de classes de vendeurs (voir plus bas), pour lesquelles
|
||||||
@@ -1088,7 +1096,7 @@ d'une chaîne de caractères comme nom de serveur TFTP, il est nécessaire de fa
|
|||||||
comme suit :
|
comme suit :
|
||||||
.B --dhcp-option=66,"1.2.3.4"
|
.B --dhcp-option=66,"1.2.3.4"
|
||||||
|
|
||||||
Les options encapsulées de classes de vendeurs peuvent-être aussi spécifiées
|
Les options encapsulées de classes de vendeurs peuvent être aussi spécifiées
|
||||||
(pour IPv4 seulement) en utilisant
|
(pour IPv4 seulement) en utilisant
|
||||||
.B --dhcp-option
|
.B --dhcp-option
|
||||||
: par exemple
|
: par exemple
|
||||||
@@ -1105,7 +1113,7 @@ par le client. Il est possible d'omettre complètement une classe de vendeur :
|
|||||||
.B --dhcp-option=vendor:,1,0.0.0.0
|
.B --dhcp-option=vendor:,1,0.0.0.0
|
||||||
Dans ce cas l'option encapsulée est toujours envoyée.
|
Dans ce cas l'option encapsulée est toujours envoyée.
|
||||||
|
|
||||||
En IPv4, les options peuvent-être encapsulées au sein d'autres options :
|
En IPv4, les options peuvent être encapsulées au sein d'autres options :
|
||||||
par exemple
|
par exemple
|
||||||
.B --dhcp-option=encap:175, 190, "iscsi-client0"
|
.B --dhcp-option=encap:175, 190, "iscsi-client0"
|
||||||
enverra l'option 175, au sein de laquelle se trouve l'option 190.
|
enverra l'option 175, au sein de laquelle se trouve l'option 190.
|
||||||
@@ -1128,7 +1136,7 @@ une option encapsulée.
|
|||||||
Cela fonctionne exactement de la même façon que
|
Cela fonctionne exactement de la même façon que
|
||||||
.B --dhcp-option
|
.B --dhcp-option
|
||||||
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
|
sauf que cette option sera toujours envoyée, même si le client ne la demande pas
|
||||||
dans la liste de paramêtres requis. Cela est parfois nécessaire, par exemple lors
|
dans la liste de paramètres requis. Cela est parfois nécessaire, par exemple lors
|
||||||
de la fourniture d'options à PXELinux.
|
de la fourniture d'options à PXELinux.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-no-override
|
.B --dhcp-no-override
|
||||||
@@ -1149,10 +1157,10 @@ Toutes les requêtes DHCP arrivant sur cette interface seront relayées au
|
|||||||
serveur DHCP distant correspondant à l'adresse de serveur indiquée. Il est
|
serveur DHCP distant correspondant à l'adresse de serveur indiquée. Il est
|
||||||
possible de relayer depuis une unique adresse locale vers différents serveurs
|
possible de relayer depuis une unique adresse locale vers différents serveurs
|
||||||
distant en spécifiant plusieurs fois l'option dhcp-relay avec la même adresse
|
distant en spécifiant plusieurs fois l'option dhcp-relay avec la même adresse
|
||||||
locale et différentes adresses de serveur. L'adresse de serveur doit-être
|
locale et différentes adresses de serveur. L'adresse de serveur doit être
|
||||||
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut-être
|
sous forme numérique. Dans le cas de DHCPv6, l'adresse de serveur peut être
|
||||||
l'adresse de multicast ff05::1:3 correspondant à tous les serveurs DHCP. Dans
|
l'adresse de multicast ff05::1:3 correspondant à tous les serveurs DHCP. Dans
|
||||||
ce cas, l'interface doit-étre spécifiée et ne peut comporter de caractère
|
ce cas, l'interface doit être spécifiée et ne peut comporter de caractère
|
||||||
joker. Elle sera utilisée pour indiquer l'interface à partir de laquelle le
|
joker. Elle sera utilisée pour indiquer l'interface à partir de laquelle le
|
||||||
multicast pourra atteindre le serveur DHCP.
|
multicast pourra atteindre le serveur DHCP.
|
||||||
|
|
||||||
@@ -1181,14 +1189,14 @@ vice-versa.
|
|||||||
Associe une chaîne de classe de vendeur à un label. La plupart
|
Associe une chaîne de classe de vendeur à un label. La plupart
|
||||||
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
|
des clients DHCP fournissent une "classe de vendeur" ("vendor class") qui
|
||||||
représente, d'une certaine façon, le type d'hôte. Cette option associe des
|
représente, d'une certaine façon, le type d'hôte. Cette option associe des
|
||||||
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent-être
|
classes de vendeur à des labels, de telle sorte que des options DHCP peuvent être
|
||||||
fournie de manière sélective aux différentes classes d'hôtes. Par exemple,
|
fournies de manière sélective aux différentes classes d'hôtes. Par exemple,
|
||||||
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
|
.B dhcp-vendorclass=set:printers,Hewlett-Packard JetDirect
|
||||||
ou
|
ou
|
||||||
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
|
.B dhcp-vendorclass=printers,Hewlett-Packard JetDirect
|
||||||
permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
|
permet de n'allouer des options qu'aux imprimantes HP de la manière suivante :
|
||||||
.B --dhcp-option=tag:printers,3,192.168.4.4
|
.B --dhcp-option=tag:printers,3,192.168.4.4
|
||||||
La chaîne de caractères de la classe de vendeur founie en argument est cherchée
|
La chaîne de caractères de la classe de vendeur fournie en argument est cherchée
|
||||||
en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
|
en temps que sous-chaîne de caractères au sein de la classe de vendeur fournie
|
||||||
par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne
|
par le client, de façon à permettre la recherche d'un sous-ensemble de la chaîne
|
||||||
de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
|
de caractères ("fuzzy matching"). Le préfixe set: est optionnel mais autorisé
|
||||||
@@ -1218,7 +1226,7 @@ matérielle coïncide avec les critères définis.
|
|||||||
.TP
|
.TP
|
||||||
.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
|
.B --dhcp-circuitid=set:<label>,<identifiant de circuit>, --dhcp-remoteid=set:<label>,<identifiant distant>
|
||||||
Associe des options de relais DHCP issus de la RFC3046 à des labels.
|
Associe des options de relais DHCP issus de la RFC3046 à des labels.
|
||||||
Cette information peut-être fournie par des relais DHCP. L'identifiant
|
Cette information peut être fournie par des relais DHCP. L'identifiant
|
||||||
de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
|
de circuit ou l'identifiant distant est normalement fourni sous la forme d'une
|
||||||
chaîne de valeurs hexadécimales séparées par des ":", mais il est également
|
chaîne de valeurs hexadécimales séparées par des ":", mais il est également
|
||||||
possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
|
possible qu'elle le soit sous la forme d'une simple chaîne de caractères. Si
|
||||||
@@ -1231,7 +1239,7 @@ est supporté en IPv6 (mais non dhcp-circuitid).
|
|||||||
(IPv4 et IPv6) Associe des options de relais DHCP issues de la RFC3993 à des
|
(IPv4 et IPv6) Associe des options de relais DHCP issues de la RFC3993 à des
|
||||||
labels.
|
labels.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-proxy[=<adresse ip>]......
|
.B --dhcp-proxy[=<adresse IP>]......
|
||||||
(IPv4 seulement) Un agent relai DHCP normal est uniquement utilisé pour faire
|
(IPv4 seulement) Un agent relai DHCP normal est uniquement utilisé pour faire
|
||||||
suivre les éléments initiaux de l'interaction avec le serveur DHCP. Une fois
|
suivre les éléments initiaux de l'interaction avec le serveur DHCP. Une fois
|
||||||
que le client est configuré, il communique directement avec le serveur. Cela
|
que le client est configuré, il communique directement avec le serveur. Cela
|
||||||
@@ -1252,7 +1260,7 @@ interactions avec les relais dont l'adresse est dans la liste seront affectées.
|
|||||||
Si aucune valeur n'est spécifiée, associe le label si le client
|
Si aucune valeur n'est spécifiée, associe le label si le client
|
||||||
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
|
envoie une option DHCP avec le numéro ou le nom spécifié. Lorsqu'une valeur est
|
||||||
fournie, positionne le label seulement dans le cas où l'option est fournie et
|
fournie, positionne le label seulement dans le cas où l'option est fournie et
|
||||||
correspond à la valeur. La valeur peut-être de la forme "01:ff:*:02", auquel
|
correspond à la valeur. La valeur peut être de la forme "01:ff:*:02", auquel
|
||||||
cas le début de l'option doit correspondre (en respectant les jokers). La
|
cas le début de l'option doit correspondre (en respectant les jokers). La
|
||||||
valeur peut aussi être de la même forme que dans
|
valeur peut aussi être de la même forme que dans
|
||||||
.B dhcp-option
|
.B dhcp-option
|
||||||
@@ -1262,14 +1270,14 @@ valeur peut aussi être de la même forme que dans
|
|||||||
--dhcp-match=set:efi-ia32,option:client-arch,6
|
--dhcp-match=set:efi-ia32,option:client-arch,6
|
||||||
|
|
||||||
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
|
spécifie le label "efi-ia32" si le numéro 6 apparaît dnas la liste
|
||||||
d'architectures envoyé par le client au sein de l'option 93. (se réferer
|
d'architectures envoyé par le client au sein de l'option 93. (se référer
|
||||||
au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
|
au RFC 4578 pour plus de détails). Si la valeur est un chaine de caractères,
|
||||||
celle-ci est recherchée (correspondance en temps que sous-chaîne).
|
celle-ci est recherchée (correspondance en temps que sous-chaîne).
|
||||||
|
|
||||||
Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se
|
Pour la forme particulière vi-encap:<numéro d'entreprise>, la comparaison se
|
||||||
fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
|
fait avec les classes de vendeur "identifiant de vendeur" ("vendor-identifying
|
||||||
vendor classes") pour l'entreprise dont le numéro est fourni en option.
|
vendor classes") pour l'entreprise dont le numéro est fourni en option.
|
||||||
Veuillez vous réferer à la RFC 3925 pour plus de détail.
|
Veuillez vous référer à la RFC 3925 pour plus de détails.
|
||||||
.TP
|
.TP
|
||||||
.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
|
.B --tag-if=set:<label>[,set:<label>[,tag:<label>[,tag:<label>]]]
|
||||||
Effectue une opération booléenne sur les labels. Si tous les labels
|
Effectue une opération booléenne sur les labels. Si tous les labels
|
||||||
@@ -1280,7 +1288,7 @@ Si aucun tag:<label> n'est spécifié, alors tous les labels fournis par
|
|||||||
set:<label> sont positionnés.
|
set:<label> sont positionnés.
|
||||||
N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans
|
N'importe quel nombre de set: ou tag: peuvent être fournis, et l'ordre est sans
|
||||||
importance.
|
importance.
|
||||||
Les lignes tag-if sont executées dans l'ordre, ce qui fait que si un label dans
|
Les lignes tag-if sont exécutées dans l'ordre, ce qui fait que si un label dans
|
||||||
tag:<label> est un label positionné par une rêgle
|
tag:<label> est un label positionné par une rêgle
|
||||||
.B tag-if,
|
.B tag-if,
|
||||||
la ligne qui positionne le label doit précéder celle qui le teste.
|
la ligne qui positionne le label doit précéder celle qui le teste.
|
||||||
@@ -1320,17 +1328,17 @@ le cas de certains vieux clients BOOTP.
|
|||||||
(IPv4 seulement) Spécifie les options BOOTP devant être retournées par le
|
(IPv4 seulement) Spécifie les options BOOTP devant être retournées par le
|
||||||
serveur DHCP. Le nom de serveur ainsi que l'adresse sont optionnels : s'ils
|
serveur DHCP. Le nom de serveur ainsi que l'adresse sont optionnels : s'ils
|
||||||
ne sont pas fournis, le nom est laissé vide et l'adresse fournie est celle de
|
ne sont pas fournis, le nom est laissé vide et l'adresse fournie est celle de
|
||||||
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq founit un service TFTP (voir
|
la machine sur laquelle s'exécute Dnsmasq. Si Dnsmasq fournit un service TFTP (voir
|
||||||
.B --enable-tftp
|
.B --enable-tftp
|
||||||
), alors seul un nom de fichier est requis ici pour permettre un démarrage par
|
), alors seul un nom de fichier est requis ici pour permettre un démarrage par
|
||||||
le réseau.
|
le réseau.
|
||||||
Si d'éventuels labels sont fournis, ils doivent coïncider avec
|
Si d'éventuels labels sont fournis, ils doivent coïncider avec
|
||||||
ceux du client pour que cet élement de configuration lui soit envoyé.
|
ceux du client pour que cet élément de configuration lui soit envoyé.
|
||||||
Une adresse de serveur TFTP peut être spécifiée à la place de l'adresse IP,
|
Une adresse de serveur TFTP peut être spécifiée à la place de l'adresse IP,
|
||||||
sous la forme d'un nom de domaine qui sera cherché dans le fichier /etc/hosts.
|
sous la forme d'un nom de domaine qui sera cherché dans le fichier /etc/hosts.
|
||||||
Ce nom peut être associé dans /etc/hosts avec plusieurs adresses IP, auquel cas
|
Ce nom peut être associé dans /etc/hosts avec plusieurs adresses IP, auquel cas
|
||||||
celles-ci seront utilisées tour à tour (algorithme round-robin).
|
celles-ci seront utilisées tour à tour (algorithme round-robin).
|
||||||
Cela peut-être utiliser pour équilibrer la charge tftp sur plusieurs serveurs.
|
Cela peut être utilisé pour équilibrer la charge tftp sur plusieurs serveurs.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-sequential-ip
|
.B --dhcp-sequential-ip
|
||||||
Dnsmasq est conçu pour choisir l'adresse IP des clients DHCP en utilisant
|
Dnsmasq est conçu pour choisir l'adresse IP des clients DHCP en utilisant
|
||||||
@@ -1346,6 +1354,13 @@ Veuillez noter que dans ce mode séquentiel, les clients qui laissent expirer
|
|||||||
leur bail ont beaucoup plus de chance de voir leur adresse IP changer, aussi
|
leur bail ont beaucoup plus de chance de voir leur adresse IP changer, aussi
|
||||||
cette option ne devrait pas être utilisée dans un cas général.
|
cette option ne devrait pas être utilisée dans un cas général.
|
||||||
.TP
|
.TP
|
||||||
|
.B --dhcp-ignore-clid
|
||||||
|
Dnsmasq lit l'option 'client identifier' (RFC 2131) envoyée par les clients
|
||||||
|
(si disponible) afin d'identifier les clients. Cela permet de distribuer la
|
||||||
|
même adresse IP à un client utilisant plusieurs interfaces. Activer cette option
|
||||||
|
désactive la lecture du 'client identifier', afin de toujours identifier un client
|
||||||
|
en utilisant l'adresse MAC.
|
||||||
|
.TP
|
||||||
.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>|<nom de serveur>]
|
.B --pxe-service=[tag:<label>,]<CSA>,<entrée de menu>[,<nom de fichier>|<type de service de démarrage>][,<adresse de serveur>|<nom de serveur>]
|
||||||
La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
|
La plupart des ROMS de démarrage PXE ne permettent au système PXE que la simple
|
||||||
obtention d'une adresse IP, le téléchargement du fichier spécifié dans
|
obtention d'une adresse IP, le téléchargement du fichier spécifié dans
|
||||||
@@ -1357,7 +1372,7 @@ Ceci spécifie l'option de démarrage qui apparaitra dans un menu de démarrage
|
|||||||
PXE. <CSA> est le type du système client. Seuls des types de services valides
|
PXE. <CSA> est le type du système client. Seuls des types de services valides
|
||||||
apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
|
apparaitront dans un menu. Les types connus sont x86PC, PC98, IA64_EFI, Alpha,
|
||||||
Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
|
Arc_x86, Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI et X86-64_EFI;
|
||||||
D'autres types peuvent-être spécifiés sous la forme d'une valeur entière. Le
|
D'autres types peuvent être spécifiés sous la forme d'une valeur entière. Le
|
||||||
paramètre après le texte correspondant à l'entrée dans le menu peut être un nom
|
paramètre après le texte correspondant à l'entrée dans le menu peut être un nom
|
||||||
de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
|
de fichier, auquel cas Dnsmasq agit comme un serveur de démarrage et indique au
|
||||||
client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
|
client PXE qu'il faut télécharger ce fichier via TFTP, soit depuis ce serveur
|
||||||
@@ -1376,7 +1391,7 @@ démarrage n'est fournie (ou qu'une valeur de 0 est donnée pour le type de
|
|||||||
service), alors l'entrée de menu provoque l'interruption du démarrage par
|
service), alors l'entrée de menu provoque l'interruption du démarrage par
|
||||||
le réseau et la poursuite du démarrage sur un média local. L'adresse de serveur
|
le réseau et la poursuite du démarrage sur un média local. L'adresse de serveur
|
||||||
peut être donnée sous la forme de nom de domaine qui est recherché dans
|
peut être donnée sous la forme de nom de domaine qui est recherché dans
|
||||||
/etc/hosts. Ce nom peut-être associé à plusieurs adresses IP, qui dans ce cas
|
/etc/hosts. Ce nom peut être associé à plusieurs adresses IP, qui dans ce cas
|
||||||
sont utilisées à tour de rôle (en "round-robin").
|
sont utilisées à tour de rôle (en "round-robin").
|
||||||
.TP
|
.TP
|
||||||
.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
|
.B --pxe-prompt=[tag:<label>,]<invite>[,<délai>]
|
||||||
@@ -1435,7 +1450,7 @@ Utiliser cette option avec précaution, une adresse allouée à un client BOOTP
|
|||||||
étant perpétuelle, et de fait n'est plus disponibles pour d'autres hôtes. Si
|
étant perpétuelle, et de fait n'est plus disponibles pour d'autres hôtes. Si
|
||||||
aucun argument n'est donné, alors cette option permet une allocation dynamique
|
aucun argument n'est donné, alors cette option permet une allocation dynamique
|
||||||
dans tous les cas. Si des arguments sont spécifiés, alors l'allocation ne se
|
dans tous les cas. Si des arguments sont spécifiés, alors l'allocation ne se
|
||||||
fait que lorsque tous les identifiants coïncident. Il est possible de répeter
|
fait que lorsque tous les identifiants coïncident. Il est possible de répéter
|
||||||
cette option avec plusieurs jeux d'arguments.
|
cette option avec plusieurs jeux d'arguments.
|
||||||
.TP
|
.TP
|
||||||
.B \-5, --no-ping
|
.B \-5, --no-ping
|
||||||
@@ -1560,7 +1575,7 @@ Tous les descripteurs de fichiers sont fermés, sauf stdin, stdout et stderr qui
|
|||||||
sont ouverts sur /dev/null (sauf en mode déverminage).
|
sont ouverts sur /dev/null (sauf en mode déverminage).
|
||||||
|
|
||||||
Le script n'est pas lancé de manière concurrente : au plus une instance du
|
Le script n'est pas lancé de manière concurrente : au plus une instance du
|
||||||
script est executée à la fois (dnsmasq attends qu'une instance de script se
|
script est exécutée à la fois (dnsmasq attend qu'une instance de script se
|
||||||
termine avant de lancer la suivante). Les changements dans la base des baux
|
termine avant de lancer la suivante). Les changements dans la base des baux
|
||||||
nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
|
nécessitant le lancement du script sont placé en attente dans une queue jusqu'à
|
||||||
terminaison d'une instance du script en cours. Si cette mise en queue fait que
|
terminaison d'une instance du script en cours. Si cette mise en queue fait que
|
||||||
@@ -1575,7 +1590,7 @@ le script sera invoqué avec une action "old" pour tous les baux existants.
|
|||||||
|
|
||||||
Il existe deux autres actions pouvant apparaître comme argument au script :
|
Il existe deux autres actions pouvant apparaître comme argument au script :
|
||||||
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
|
"init" et "tftp". D'autres sont susceptibles d'être rajoutées dans le futur,
|
||||||
aussi les scripts devraient-être écrits de sorte à ignorer les actions
|
aussi les scripts devraient être écrits de sorte à ignorer les actions
|
||||||
inconnues. "init" est décrite ci-dessous dans
|
inconnues. "init" est décrite ci-dessous dans
|
||||||
.B --leasefile-ro.
|
.B --leasefile-ro.
|
||||||
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
|
L'action "tftp" est invoquée lorsqu'un transfert de fichier TFTP s'est
|
||||||
@@ -1588,7 +1603,7 @@ Spécifie un script écrit en Lua, devant être exécuté lorsque des baux sont
|
|||||||
créés, détruits ou modifiés. Pour utiliser cette option, dnsmasq doit être
|
créés, détruits ou modifiés. Pour utiliser cette option, dnsmasq doit être
|
||||||
compilé avec avec le support de Lua. L'interpréteur Lua est initialisé une
|
compilé avec avec le support de Lua. L'interpréteur Lua est initialisé une
|
||||||
seule fois, lorsque dnsmasq démarre, ce qui fait que les variables globales
|
seule fois, lorsque dnsmasq démarre, ce qui fait que les variables globales
|
||||||
persistent entre les évênements liés aux baux. Le code Lua doit définir une
|
persistent entre les événements liés aux baux. Le code Lua doit définir une
|
||||||
fonction
|
fonction
|
||||||
.B lease
|
.B lease
|
||||||
et peut fournir des fonctions
|
et peut fournir des fonctions
|
||||||
@@ -1637,7 +1652,7 @@ et
|
|||||||
.B --dhcp-scriptuser
|
.B --dhcp-scriptuser
|
||||||
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
|
Spécifie l'utilisateur sous lequel le script shell lease-change ou le script
|
||||||
doivent être exécutés. La valeur par défaut correspond à l'utilisateur root
|
doivent être exécutés. La valeur par défaut correspond à l'utilisateur root
|
||||||
mais peut-être changée par le biais de cette option.
|
mais peut être changée par le biais de cette option.
|
||||||
.TP
|
.TP
|
||||||
.B \-9, --leasefile-ro
|
.B \-9, --leasefile-ro
|
||||||
Supprimer complètement l'usage du fichier servant de base de donnée pour les
|
Supprimer complètement l'usage du fichier servant de base de donnée pour les
|
||||||
@@ -1649,8 +1664,8 @@ biais de l'option
|
|||||||
être complètement gérée par le script sur un stockage externe. En addition aux
|
être complètement gérée par le script sur un stockage externe. En addition aux
|
||||||
actions décrites dans
|
actions décrites dans
|
||||||
.B --dhcp-script,
|
.B --dhcp-script,
|
||||||
le script de changement d'état de bail est appellé une fois, au lancement de
|
le script de changement d'état de bail est appelé une fois, au lancement de
|
||||||
Dnsmasq, avec pour seul argument "init". Lorsqu'appellé de la sorte, le script
|
Dnsmasq, avec pour seul argument "init". Lorsqu'appelé de la sorte, le script
|
||||||
doit fournir l'état de la base de baux, dans le format de fichier de baux de
|
doit fournir l'état de la base de baux, dans le format de fichier de baux de
|
||||||
Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0.
|
Dnsmasq, sur sa sortie standard (stdout) et retourner un code de retour de 0.
|
||||||
Positionner cette option provoque également une invocation du script de
|
Positionner cette option provoque également une invocation du script de
|
||||||
@@ -1692,20 +1707,20 @@ positionné à la première valeur de la directive "search" du fichier
|
|||||||
/etc/resolv.conf (ou équivalent).
|
/etc/resolv.conf (ou équivalent).
|
||||||
|
|
||||||
La gamme d'adresses peut être de la forme
|
La gamme d'adresses peut être de la forme
|
||||||
<adresse ip>,<adresse ip> ou <adresse ip>/<masque de réseau> voire une simple
|
<adresse IP>,<adresse IP> ou <adresse IP>/<masque de réseau> voire une simple
|
||||||
<adresse ip>. Voir
|
<adresse IP>. Voir
|
||||||
.B --dhcp-fqdn
|
.B --dhcp-fqdn
|
||||||
qui peut changer le comportement de dnsmasq relatif aux domaines.
|
qui peut changer le comportement de dnsmasq relatif aux domaines.
|
||||||
|
|
||||||
Si la gamme d'adresse est fournie sous la forme
|
Si la gamme d'adresse est fournie sous la forme
|
||||||
<adresse ip>/<taille de réseau>, alors le drapeau "local" peut-être rajouté
|
<adresse IP>/<taille de réseau>, alors le drapeau "local" peut être rajouté
|
||||||
qui a pour effect d'ajouter --local-declarations aux requêtes DNS directes et
|
qui a pour effet d'ajouter --local-declarations aux requêtes DNS directes et
|
||||||
inverses. C-à-d
|
inverses. C-à-d
|
||||||
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
|
.B --domain=thekelleys.org.uk,192.168.0.0/24,local
|
||||||
est identique à
|
est identique à
|
||||||
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
||||||
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
--local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
||||||
La taille de réseau doit-être de 8, 16 ou 24 pour être valide.
|
La taille de réseau doit être de 8, 16 ou 24 pour être valide.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-fqdn
|
.B --dhcp-fqdn
|
||||||
Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
|
Dans le mode par défaut, dnsmasq insère les noms non-qualifiés des clients
|
||||||
@@ -1717,8 +1732,8 @@ ce nom est transféré au nouveau client. Si
|
|||||||
est spécifié, ce comportement change : les noms non qualifiés ne sont plus
|
est spécifié, ce comportement change : les noms non qualifiés ne sont plus
|
||||||
rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
|
rajoutés dans le DNS, seuls les noms qualifiés le sont. Deux clients DHCP
|
||||||
avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
|
avec le même nom peuvent tous les deux garder le nom, pour peu que la partie
|
||||||
relative au domaine soit différente (c-à-d que les noms pleinements qualifiés
|
relative au domaine soit différente (c-à-d que les noms pleinement qualifiés
|
||||||
diffèrent). Pour d'assurer que tous les noms ont une partie domaine, il doit-y
|
diffèrent). Pour s'assurer que tous les noms ont une partie domaine, il doit y
|
||||||
avoir au moins un
|
avoir au moins un
|
||||||
.B --domain
|
.B --domain
|
||||||
sans gamme d'adresses de spécifié lorsque l'option
|
sans gamme d'adresses de spécifié lorsque l'option
|
||||||
@@ -1735,7 +1750,7 @@ Windows de la mise à jour de serveurs Active Directory. Voir la RFC 4702 pour
|
|||||||
plus de détails.
|
plus de détails.
|
||||||
.TP
|
.TP
|
||||||
.B --enable-ra
|
.B --enable-ra
|
||||||
Active la fonctionalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
|
Active la fonctionnalité d'annonces routeurs IPv6 ("IPv6 Router Advertisement").
|
||||||
DHCPv6 ne gère pas la configuration complète du réseau de la même façon que
|
DHCPv6 ne gère pas la configuration complète du réseau de la même façon que
|
||||||
DHCPv4. La découverte de routeurs et la découverte (éventuelle) de préfixes pour
|
DHCPv4. La découverte de routeurs et la découverte (éventuelle) de préfixes pour
|
||||||
la création autonome d'adresse sont gérées par un protocole différent.
|
la création autonome d'adresse sont gérées par un protocole différent.
|
||||||
@@ -1747,7 +1762,7 @@ dhcp-range et, par défaut, fournir comme valeur de routeur et de DNS récursif
|
|||||||
la valeur d'adresse link-local appropriée parmi celles de la machine sur
|
la valeur d'adresse link-local appropriée parmi celles de la machine sur
|
||||||
laquelle tourne dnsmasq.
|
laquelle tourne dnsmasq.
|
||||||
Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
|
Par défaut, les bits "managed address" sont positionnés, et le bit "use SLAAC"
|
||||||
("utiliser SLAAC") est réinitialisé. Cela peut-être changé pour des
|
("utiliser SLAAC") est réinitialisé. Cela peut être changé pour des
|
||||||
sous-réseaux donnés par le biais du mot clef de mode décris dans
|
sous-réseaux donnés par le biais du mot clef de mode décris dans
|
||||||
.B --dhcp-range.
|
.B --dhcp-range.
|
||||||
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
|
Les paramètres DNS du RFC6106 sont inclus dans les annonces. Par défaut,
|
||||||
@@ -1759,16 +1774,16 @@ DNSSL.
|
|||||||
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
|
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
|
||||||
Configure pour une interface donnée des valeurs pour les annonces routeurs
|
Configure pour une interface donnée des valeurs pour les annonces routeurs
|
||||||
différentes des valeurs par défaut. La valeur par défaut du champ priorité
|
différentes des valeurs par défaut. La valeur par défaut du champ priorité
|
||||||
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
|
pour le routeur peut être changée de "medium" (moyen) à "high" (haute) ou
|
||||||
"low" (basse). Par exemple :
|
"low" (basse). Par exemple :
|
||||||
.B --ra-param=eth0,high,0.
|
.B --ra-param=eth0,high,0.
|
||||||
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
|
Un intervalle (en secondes) entre les annonces routeur peut être fourni par :
|
||||||
.B --ra-param=eth0,60.
|
.B --ra-param=eth0,60.
|
||||||
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
|
La durée de vie de la route peut être changée ou mise à zéro, auquel cas
|
||||||
le routeur peut annoncer les préfixes mais pas de route :
|
le routeur peut annoncer les préfixes mais pas de route :
|
||||||
.B --ra-parm=eth0,0,0
|
.B --ra-param=eth0,0,0
|
||||||
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
|
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
|
||||||
Ces quatre paramètres peuvent-être configurés en une fois :
|
Ces quatre paramètres peuvent être configurés en une fois :
|
||||||
.B --ra-param=eth0,mtu:1280,low,60,1200
|
.B --ra-param=eth0,mtu:1280,low,60,1200
|
||||||
La valeur pour l'interface peut inclure un caractère joker.
|
La valeur pour l'interface peut inclure un caractère joker.
|
||||||
.TP
|
.TP
|
||||||
@@ -1776,7 +1791,7 @@ La valeur pour l'interface peut inclure un caractère joker.
|
|||||||
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
|
Active la fonction serveur TFTP. Celui-ci est de manière délibérée limité aux
|
||||||
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
|
fonctions nécessaires au démarrage par le réseau ("net-boot") d'un client. Seul
|
||||||
un accès en lecture est possible; les extensions tsize et blksize sont supportées
|
un accès en lecture est possible; les extensions tsize et blksize sont supportées
|
||||||
(tsize est seulement supporté en mode octet). Sans argument optionel, le service
|
(tsize est seulement supportée en mode octet). Sans argument optionnel, le service
|
||||||
TFTP est fourni sur les mêmes interfaces que le service DHCP. Si une liste
|
TFTP est fourni sur les mêmes interfaces que le service DHCP. Si une liste
|
||||||
d'interfaces est fournie, cela définit les interfaces sur lesquelles le
|
d'interfaces est fournie, cela définit les interfaces sur lesquelles le
|
||||||
service TFTP sera activé.
|
service TFTP sera activé.
|
||||||
@@ -1847,9 +1862,9 @@ Un serveur TFTP écoute sur le port prédéfini 69 ("well-known port") pour
|
|||||||
l'initiation de la connexion, mais utilise également un port dynamiquement
|
l'initiation de la connexion, mais utilise également un port dynamiquement
|
||||||
alloué pour chaque connexion. Normalement, ces ports sont alloués par
|
alloué pour chaque connexion. Normalement, ces ports sont alloués par
|
||||||
le système d'exploitation, mais cette option permet de spécifier une gamme
|
le système d'exploitation, mais cette option permet de spécifier une gamme
|
||||||
de ports à utiliser pour les transferts TFTP. Cela peut-être utile si
|
de ports à utiliser pour les transferts TFTP. Cela peut être utile si
|
||||||
TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
|
TFTP doit traverser un dispositif garde-barrière ("firewall"). La valeur
|
||||||
de début pour la plage de port ne peut-être inférieure à 1025 sauf si
|
de début pour la plage de port ne peut être inférieure à 1025 sauf si
|
||||||
dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
|
dnsmasq tourne en temps que super-utilisateur ("root"). Le nombre de
|
||||||
connexions TFTP concurrentes est limitée par la taille de la gamme de
|
connexions TFTP concurrentes est limitée par la taille de la gamme de
|
||||||
ports ainsi spécifiée.
|
ports ainsi spécifiée.
|
||||||
@@ -1859,8 +1874,8 @@ Un serveur TFTP écoute sur un numéro de port bien connu (69) pour l'initiation
|
|||||||
de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
|
de la connexion, et alloue dynamiquement un port pour chaque connexion. Ces
|
||||||
numéros de ports sont en principe alloués par le système d'exploitation, mais
|
numéros de ports sont en principe alloués par le système d'exploitation, mais
|
||||||
cette option permet de spécifier une gamme de ports à utiliser pour les
|
cette option permet de spécifier une gamme de ports à utiliser pour les
|
||||||
transferts TFTP. Cela peut-être utile lorsque ceux-ci doivent traverser un
|
transferts TFTP. Cela peut être utile lorsque ceux-ci doivent traverser un
|
||||||
dispositif garde-barrière ("firewall"). Le début de la plage ne peut-être
|
dispositif garde-barrière ("firewall"). Le début de la plage ne peut être
|
||||||
inférieur à 1024 à moins que Dnsmasq ne fonctionne en temps que
|
inférieur à 1024 à moins que Dnsmasq ne fonctionne en temps que
|
||||||
super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes
|
super-utilisateur ("root"). Le nombre maximal de connexions TFTP concurrentes
|
||||||
est limitée par la taille de la plage de ports ainsi définie.
|
est limitée par la taille de la plage de ports ainsi définie.
|
||||||
@@ -1895,7 +1910,7 @@ par "--". Les lignes commençant par # sont des commentaires et sont ignorées.
|
|||||||
Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
|
Pour les options qui ne peuvent-être spécifiées qu'une seule fois, celle du
|
||||||
fichier de configuration prends le pas sur celle fournie en ligne de commande.
|
fichier de configuration prends le pas sur celle fournie en ligne de commande.
|
||||||
Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
|
Il est possible d'utiliser des guillemets afin d'éviter que les ",",":","." et
|
||||||
"#" ne soit interprêtés, et il est possible d'utiliser les séquences
|
"#" ne soient interprétés, et il est possible d'utiliser les séquences
|
||||||
d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
|
d'échappement suivantes : \\\\ \\" \\t \\e \\b \\r et \\n. Elles correspondent
|
||||||
respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles,
|
respectivement à la barre oblique descendante ("anti-slash"), guillemets doubles,
|
||||||
tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
|
tabulation, caractère d'échappement ("escape"), suppression ("backspace"), retour ("return") et
|
||||||
@@ -1940,8 +1955,8 @@ traces dans un fichier (voir
|
|||||||
.B --log-facility
|
.B --log-facility
|
||||||
), alors
|
), alors
|
||||||
.B Dnsmasq
|
.B Dnsmasq
|
||||||
ferme et re-rouvre le fichier de traces. Il faut noter que pendant cette
|
ferme et rouvre le fichier de traces. Il faut noter que pendant cette
|
||||||
opération Dnsmasq ne s'exécute pas en temps que "root". Lorsqu'il créé un
|
opération Dnsmasq ne s'exécute pas en tant que "root". Lorsqu'il créé un
|
||||||
fichier de traces pour la première fois, Dnsmasq change le propriétaire du
|
fichier de traces pour la première fois, Dnsmasq change le propriétaire du
|
||||||
fichier afin de le faire appartenir à l'utilisateur non "root" sous lequel
|
fichier afin de le faire appartenir à l'utilisateur non "root" sous lequel
|
||||||
Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit
|
Dnsmasq s'exécute. Le logiciel de rotation de fichiers de trace logrotate doit
|
||||||
@@ -1983,7 +1998,7 @@ qu'une connexion PPP ne soit établie. Dans ce cas, Dnsmasq vérifie régulière
|
|||||||
pour voir si un fichier
|
pour voir si un fichier
|
||||||
.I /etc/resolv.conf
|
.I /etc/resolv.conf
|
||||||
est créé. Dnsmasq peut être configuré pour lire plus d'un fichier resolv.conf.
|
est créé. Dnsmasq peut être configuré pour lire plus d'un fichier resolv.conf.
|
||||||
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent-être utilisés :
|
Cela est utile sur un ordinateur portable où PPP et DHCP peuvent être utilisés :
|
||||||
Dnsmasq peut alors être configuré pour lire à la fois
|
Dnsmasq peut alors être configuré pour lire à la fois
|
||||||
.I /etc/ppp/resolv.conf
|
.I /etc/ppp/resolv.conf
|
||||||
et
|
et
|
||||||
@@ -2007,7 +2022,7 @@ ou alors en mettant leurs adresses dans un autre fichier, par exemple
|
|||||||
.I /etc/resolv.dnsmasq
|
.I /etc/resolv.dnsmasq
|
||||||
et en lançant Dnsmasq avec l'option
|
et en lançant Dnsmasq avec l'option
|
||||||
.B \-r /etc/resolv.dnsmasq.
|
.B \-r /etc/resolv.dnsmasq.
|
||||||
Cette deuxième technique permet la mise-à-jour dynamique des addresses de
|
Cette deuxième technique permet la mise-à-jour dynamique des adresses de
|
||||||
serveurs DNS amont par le biais de PPP ou DHCP.
|
serveurs DNS amont par le biais de PPP ou DHCP.
|
||||||
.PP
|
.PP
|
||||||
Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le
|
Les adresses dans /etc/hosts prennent le dessus sur celles fournies par le
|
||||||
@@ -2067,10 +2082,10 @@ et pour affecter l'option envoyée, sur la base de la plage sélectionnée.
|
|||||||
|
|
||||||
Ce système a évolué d'un système plus ancien et aux possibilités plus limitées,
|
Ce système a évolué d'un système plus ancien et aux possibilités plus limitées,
|
||||||
et pour des raisons de compatibilité "net:" peut être utilisé à la place de
|
et pour des raisons de compatibilité "net:" peut être utilisé à la place de
|
||||||
"tag:" et "set:" peut-être omis (à l'exception de
|
"tag:" et "set:" peut être omis (à l'exception de
|
||||||
.B dhcp-host,
|
.B dhcp-host,
|
||||||
où "net:" peut-être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
|
où "net:" peut être utilisé à la place de "set:"). Pour les mêmes raisons, '#'
|
||||||
peut-être utilisé à la place de '!' pour indiquer la négation.
|
peut être utilisé à la place de '!' pour indiquer la négation.
|
||||||
.PP
|
.PP
|
||||||
Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur
|
Le serveur DHCP intégré dans Dnsmasq fonctionne également en temps que serveur
|
||||||
BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
|
BOOTP, pour peu que l'adresse MAC et l'adresse IP des clients soient fournies,
|
||||||
@@ -2097,7 +2112,7 @@ scénarios de complexité croissante. Le pré-requis pour chacun de ces scénari
|
|||||||
est l'existence d'une adresse IP globalement disponible, d'un enregistrement de
|
est l'existence d'une adresse IP globalement disponible, d'un enregistrement de
|
||||||
type A ou AAAA pointant vers cette adresse, ainsi que d'un serveur DNS externe
|
type A ou AAAA pointant vers cette adresse, ainsi que d'un serveur DNS externe
|
||||||
capable d'effectuer la délégation de la zone en question. Pour la première
|
capable d'effectuer la délégation de la zone en question. Pour la première
|
||||||
partie de ces explications, nous allons appeller serveur.exemple.com
|
partie de ces explications, nous allons appeler serveur.exemple.com
|
||||||
l'enregistrement A (ou AAAA) de l'adresse globalement accessible, et
|
l'enregistrement A (ou AAAA) de l'adresse globalement accessible, et
|
||||||
notre.zone.com la zone pour laquelle dnsmasq fait autorité.
|
notre.zone.com la zone pour laquelle dnsmasq fait autorité.
|
||||||
|
|
||||||
@@ -2138,11 +2153,11 @@ notre.zone.com NS our.zone.com
|
|||||||
.fi
|
.fi
|
||||||
|
|
||||||
L'enregistrement A pour notre.zone.com est dorénavant un enregistrement "colle"
|
L'enregistrement A pour notre.zone.com est dorénavant un enregistrement "colle"
|
||||||
qui résoud le problème de poule et d'oeuf consistant à trouver l'adresse IP
|
qui résout le problème de poule et d'oeuf consistant à trouver l'adresse IP
|
||||||
du serveur de nom pour notre.zone.com lorsque l'enregistrement se trouve dans
|
du serveur de nom pour notre.zone.com lorsque l'enregistrement se trouve dans
|
||||||
la zone en question. Il s'agit du seul rôle de cet enregistrement : comme dnsmasq
|
la zone en question. Il s'agit du seul rôle de cet enregistrement : comme dnsmasq
|
||||||
fait désormais autorité pour notre.zone.com, il doit également fournir cet
|
fait désormais autorité pour notre.zone.com, il doit également fournir cet
|
||||||
enregistrement. Si l'adresse externe est statique, cela peut-être réalisé par
|
enregistrement. Si l'adresse externe est statique, cela peut être réalisé par
|
||||||
le biais d'une entrée dans
|
le biais d'une entrée dans
|
||||||
.B /etc/hosts
|
.B /etc/hosts
|
||||||
ou via un
|
ou via un
|
||||||
@@ -2194,7 +2209,7 @@ spécifiques, vous pouvez le faire via :
|
|||||||
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
|
Dnsmasq joue le rôle de serveur faisant autorité pour les domaines in-addr.arpa
|
||||||
et ip6.arpa associés aux sous-réseaux définis dans la déclaration de zone
|
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
|
||||||
1.2.3.0/24 :
|
1.2.3.0/24 :
|
||||||
.nf
|
.nf
|
||||||
@@ -2243,7 +2258,7 @@ celui fourni par
|
|||||||
.B --domain.
|
.B --domain.
|
||||||
Si l'option
|
Si l'option
|
||||||
.B --dhcp-fqdn
|
.B --dhcp-fqdn
|
||||||
est fournie, alors les noms pleinemenet qualifiés associés aux baux DHCP
|
est fournie, alors les noms pleinement qualifiés associés aux baux DHCP
|
||||||
sont utilisés, dès lors qu'ils correspondent au nom de domaine associé
|
sont utilisés, dès lors qu'ils correspondent au nom de domaine associé
|
||||||
à la zone.
|
à la zone.
|
||||||
|
|
||||||
@@ -2282,7 +2297,7 @@ Dnsmasq est capable de gérer le DNS et DHCP pour au moins un millier de clients
|
|||||||
Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure).
|
Pour cela, la durée des bail ne doit pas être très courte (moins d'une heure).
|
||||||
La valeur de
|
La valeur de
|
||||||
.B --dns-forward-max
|
.B --dns-forward-max
|
||||||
peut-être augmentée : commencer par la rendre égale au nombre de clients et
|
peut être augmentée : commencer par la rendre égale au nombre de clients et
|
||||||
l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends
|
l'augmenter si le DNS semble lent. Noter que la performance du DNS dépends
|
||||||
également de la performance des serveurs amonts. La taille du cache DNS peut-
|
également de la performance des serveurs amonts. La taille du cache DNS peut-
|
||||||
être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut
|
être augmentée : la limite en dur est de 10000 entrées et la valeur par défaut
|
||||||
@@ -2306,7 +2321,7 @@ Il est possible d'utiliser Dnsmasq pour bloquer la publicité sur la toile
|
|||||||
en associant des serveurs de publicité bien connus à l'adresse 127.0.0.1 ou
|
en associant des serveurs de publicité bien connus à l'adresse 127.0.0.1 ou
|
||||||
0.0.0.0 par le biais du fichier
|
0.0.0.0 par le biais du fichier
|
||||||
.B /etc/hosts
|
.B /etc/hosts
|
||||||
ou d'un fichier d'hôte additionnel. Cette liste peut-être très longue, Dnsmasq
|
ou d'un fichier d'hôte additionnel. Cette liste peut être très longue, Dnsmasq
|
||||||
ayant été testé avec succès avec un million de noms. Cette taille de fichier
|
ayant été testé avec succès avec un million de noms. Cette taille de fichier
|
||||||
nécessite un processeur à 1 Ghz et environ 60 Mo de RAM.
|
nécessite un processeur à 1 Ghz et environ 60 Mo de RAM.
|
||||||
|
|
||||||
|
|||||||
+790
-627
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -125,7 +125,7 @@ address of its ethernet card. For the former to work, a machine needs to know it
|
|||||||
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
|
requests a DHCP lease. For dhcpcd, the -h option specifies this. The
|
||||||
names may be anything as far as DHCP is concerned, but dnsmasq adds
|
names may be anything as far as DHCP is concerned, but dnsmasq adds
|
||||||
some limitations. By default the names must no have a domain part, ie
|
some limitations. By default the names must no have a domain part, ie
|
||||||
they must just be a alphanumeric name, without any dots. This is a
|
they must just be alphanumeric names, without any dots. This is a
|
||||||
security feature to stop a machine on your network telling DHCP that
|
security feature to stop a machine on your network telling DHCP that
|
||||||
its name is "www.microsoft.com" and thereby grabbing traffic which
|
its name is "www.microsoft.com" and thereby grabbing traffic which
|
||||||
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
|
shouldn't go to it. A domain part is only allowed by dnsmasq in DHCP machine names
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,7 +28,7 @@ struct arp_record {
|
|||||||
unsigned short hwlen, status;
|
unsigned short hwlen, status;
|
||||||
int family;
|
int family;
|
||||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
struct arp_record *next;
|
struct arp_record *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,11 +44,6 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
|
|||||||
if (maclen > DHCP_CHADDR_MAX)
|
if (maclen > DHCP_CHADDR_MAX)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifndef HAVE_IPV6
|
|
||||||
if (family != AF_INET)
|
|
||||||
return 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Look for existing entry */
|
/* Look for existing entry */
|
||||||
for (arp = arps; arp; arp = arp->next)
|
for (arp = arps; arp; arp = arp->next)
|
||||||
{
|
{
|
||||||
@@ -57,16 +52,14 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
|
|||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
{
|
{
|
||||||
if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
|
if (arp->addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp))
|
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr6, (struct in6_addr *)addrp))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (arp->status == ARP_EMPTY)
|
if (arp->status == ARP_EMPTY)
|
||||||
{
|
{
|
||||||
@@ -102,11 +95,9 @@ static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *p
|
|||||||
arp->family = family;
|
arp->family = family;
|
||||||
memcpy(arp->hwaddr, mac, maclen);
|
memcpy(arp->hwaddr, mac, maclen);
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
|
arp->addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ);
|
memcpy(&arp->addr.addr6, addrp, IN6ADDRSZ);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -133,14 +124,12 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (arp->family == AF_INET &&
|
if (arp->family == AF_INET &&
|
||||||
arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
|
arp->addr.addr4.s_addr != addr->in.sin_addr.s_addr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (arp->family == AF_INET6 &&
|
if (arp->family == AF_INET6 &&
|
||||||
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
|
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr6, &addr->in6.sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Only accept positive entries unless in lazy mode. */
|
/* Only accept positive entries unless in lazy mode. */
|
||||||
if (arp->status != ARP_EMPTY || lazy || updated)
|
if (arp->status != ARP_EMPTY || lazy || updated)
|
||||||
@@ -202,11 +191,9 @@ int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
|
|||||||
arp->hwlen = 0;
|
arp->hwlen = 0;
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET)
|
if (addr->sa.sa_family == AF_INET)
|
||||||
arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
|
arp->addr.addr4.s_addr = addr->in.sin_addr.s_addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
|
memcpy(&arp->addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+66
-83
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -18,32 +18,30 @@
|
|||||||
|
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
|
|
||||||
static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
|
static struct addrlist *find_addrlist(struct addrlist *list, int flag, union all_addr *addr_u)
|
||||||
{
|
{
|
||||||
do {
|
do {
|
||||||
if (!(list->flags & ADDRLIST_IPV6))
|
if (!(list->flags & ADDRLIST_IPV6))
|
||||||
{
|
{
|
||||||
struct in_addr netmask, addr = addr_u->addr.addr4;
|
struct in_addr netmask, addr = addr_u->addr4;
|
||||||
|
|
||||||
if (!(flag & F_IPV4))
|
if (!(flag & F_IPV4))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
|
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
|
||||||
|
|
||||||
if (is_same_net(addr, list->addr.addr.addr4, netmask))
|
if (is_same_net(addr, list->addr.addr4, netmask))
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
else if (is_same_net6(&(addr_u->addr6), &list->addr.addr6, list->prefixlen))
|
||||||
else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
|
|
||||||
return list;
|
return list;
|
||||||
#endif
|
|
||||||
|
|
||||||
} while ((list = list->next));
|
} while ((list = list->next));
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, union all_addr *addr_u)
|
||||||
{
|
{
|
||||||
if (!zone->subnet)
|
if (!zone->subnet)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -51,7 +49,7 @@ static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all
|
|||||||
return find_addrlist(zone->subnet, flag, addr_u);
|
return find_addrlist(zone->subnet, flag, addr_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, union all_addr *addr_u)
|
||||||
{
|
{
|
||||||
if (!zone->exclude)
|
if (!zone->exclude)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -59,7 +57,7 @@ static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct al
|
|||||||
return find_addrlist(zone->exclude, flag, addr_u);
|
return find_addrlist(zone->exclude, flag, addr_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
static int filter_zone(struct auth_zone *zone, int flag, union all_addr *addr_u)
|
||||||
{
|
{
|
||||||
if (find_exclude(zone, flag, addr_u))
|
if (find_exclude(zone, flag, addr_u))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -103,7 +101,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
char *name = daemon->namebuff;
|
char *name = daemon->namebuff;
|
||||||
unsigned char *p, *ansp;
|
unsigned char *p, *ansp;
|
||||||
int qtype, qclass;
|
int qtype, qclass, rc;
|
||||||
int nameoffset, axfroffset = 0;
|
int nameoffset, axfroffset = 0;
|
||||||
int q, anscount = 0, authcount = 0;
|
int q, anscount = 0, authcount = 0;
|
||||||
struct crec *crecp;
|
struct crec *crecp;
|
||||||
@@ -115,7 +113,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
struct txt_record *txt;
|
struct txt_record *txt;
|
||||||
struct interface_name *intr;
|
struct interface_name *intr;
|
||||||
struct naptr *na;
|
struct naptr *na;
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
struct cname *a, *candidate;
|
struct cname *a, *candidate;
|
||||||
unsigned int wclen;
|
unsigned int wclen;
|
||||||
|
|
||||||
@@ -131,7 +129,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
for (q = ntohs(header->qdcount); q != 0; q--)
|
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||||
{
|
{
|
||||||
unsigned short flag = 0;
|
unsigned int flag = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
int cname_wildcard = 0;
|
int cname_wildcard = 0;
|
||||||
|
|
||||||
@@ -180,7 +178,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
struct addrlist *addrlist;
|
struct addrlist *addrlist;
|
||||||
|
|
||||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||||
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr.addr4.s_addr == addrlist->addr.addr.addr4.s_addr)
|
if (!(addrlist->flags & ADDRLIST_IPV6) && addr.addr4.s_addr == addrlist->addr.addr4.s_addr)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (addrlist)
|
if (addrlist)
|
||||||
@@ -189,14 +187,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||||
intr = intr->next;
|
intr = intr->next;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (flag == F_IPV6)
|
else if (flag == F_IPV6)
|
||||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||||
{
|
{
|
||||||
struct addrlist *addrlist;
|
struct addrlist *addrlist;
|
||||||
|
|
||||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||||
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr.addr6, &addrlist->addr.addr.addr6))
|
if ((addrlist->flags & ADDRLIST_IPV6) && IN6_ARE_ADDR_EQUAL(&addr.addr6, &addrlist->addr.addr6))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (addrlist)
|
if (addrlist)
|
||||||
@@ -205,7 +202,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||||
intr = intr->next;
|
intr = intr->next;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (intr)
|
if (intr)
|
||||||
{
|
{
|
||||||
@@ -283,11 +279,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
if (!rec->issrv && hostname_isequal(name, rec->name))
|
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
if (qtype == T_MX)
|
if (rc == 2 && qtype == T_MX)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||||
@@ -298,11 +294,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
||||||
if (rec->issrv && hostname_isequal(name, rec->name))
|
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
if (qtype == T_SRV)
|
if (rc == 2 && qtype == T_SRV)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||||
@@ -333,13 +329,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (txt = daemon->rr; txt; txt = txt->next)
|
for (txt = daemon->rr; txt; txt = txt->next)
|
||||||
if (hostname_isequal(name, txt->name))
|
if ((rc = hostname_issubdomain(name, txt->name)))
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if (txt->class == qtype)
|
if (rc == 2 && txt->class == qtype)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||||
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||||
anscount++;
|
anscount++;
|
||||||
@@ -347,10 +343,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (txt = daemon->txt; txt; txt = txt->next)
|
for (txt = daemon->txt; txt; txt = txt->next)
|
||||||
if (txt->class == C_IN && hostname_isequal(name, txt->name))
|
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if (qtype == T_TXT)
|
if (rc == 2 && qtype == T_TXT)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||||
@@ -361,10 +357,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (na = daemon->naptr; na; na = na->next)
|
for (na = daemon->naptr; na; na = na->next)
|
||||||
if (hostname_isequal(name, na->name))
|
if ((rc = hostname_issubdomain(name, na->name)))
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if (qtype == T_NAPTR)
|
if (rc == 2 && qtype == T_NAPTR)
|
||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||||
@@ -378,27 +374,24 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (qtype == T_A)
|
if (qtype == T_A)
|
||||||
flag = F_IPV4;
|
flag = F_IPV4;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (qtype == T_AAAA)
|
if (qtype == T_AAAA)
|
||||||
flag = F_IPV6;
|
flag = F_IPV6;
|
||||||
#endif
|
|
||||||
|
|
||||||
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 ((rc = hostname_issubdomain(name, intr->name)))
|
||||||
{
|
{
|
||||||
struct addrlist *addrlist;
|
struct addrlist *addrlist;
|
||||||
|
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
if (flag)
|
if (rc == 2 && flag)
|
||||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||||
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)
|
if (addrlist->flags & ADDRLIST_REVONLY)
|
||||||
continue;
|
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,
|
||||||
@@ -424,27 +417,24 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (peer_addr->sa.sa_family == AF_INET)
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
peer_addr->in.sin_port = 0;
|
peer_addr->in.sin_port = 0;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
peer_addr->in6.sin6_port = 0;
|
peer_addr->in6.sin6_port = 0;
|
||||||
peer_addr->in6.sin6_scope_id = 0;
|
peer_addr->in6.sin6_scope_id = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
for (peers = daemon->auth_peers; peers; peers = peers->next)
|
||||||
if (sockaddr_isequal(peer_addr, &peers->addr))
|
if (sockaddr_isequal(peer_addr, &peers->addr))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Refuse all AXFR unless --auth-sec-servers is set */
|
/* Refuse all AXFR unless --auth-sec-servers or auth-peers is set */
|
||||||
if ((!peers && daemon->auth_peers) || !daemon->secondary_forward_server)
|
if ((!daemon->secondary_forward_server && !daemon->auth_peers) ||
|
||||||
|
(daemon->auth_peers && !peers))
|
||||||
{
|
{
|
||||||
if (peer_addr->sa.sa_family == AF_INET)
|
if (peer_addr->sa.sa_family == AF_INET)
|
||||||
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &peer_addr->in.sin_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, &peer_addr->in6.sin6_addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#endif
|
|
||||||
|
|
||||||
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
my_syslog(LOG_WARNING, _("ignoring zone transfer request from %s"), daemon->addrbuff);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -478,10 +468,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if ((crecp->flags & flag) &&
|
if ((crecp->flags & flag) &&
|
||||||
(local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
(local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||||
{
|
{
|
||||||
*cut = '.'; /* restore domain part */
|
*cut = '.'; /* restore domain part */
|
||||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid));
|
||||||
*cut = 0; /* remove domain part */
|
*cut = 0; /* remove domain part */
|
||||||
found = 1;
|
found = 1;
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
@@ -501,9 +491,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr.addr))))
|
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags, name, &crecp->addr.addr, record_source(crecp->uid));
|
log_query(crecp->flags, name, &crecp->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,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
@@ -566,6 +556,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
goto cname_restart;
|
goto cname_restart;
|
||||||
}
|
}
|
||||||
|
else if (cache_find_non_terminal(name, now))
|
||||||
|
nxdomain = 0;
|
||||||
|
|
||||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||||
}
|
}
|
||||||
@@ -588,7 +580,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (!(subnet->flags & ADDRLIST_IPV6))
|
if (!(subnet->flags & ADDRLIST_IPV6))
|
||||||
{
|
{
|
||||||
in_addr_t a = ntohl(subnet->addr.addr.addr4.s_addr) >> 8;
|
in_addr_t a = ntohl(subnet->addr.addr4.s_addr) >> 8;
|
||||||
char *p = name;
|
char *p = name;
|
||||||
|
|
||||||
if (subnet->prefixlen >= 24)
|
if (subnet->prefixlen >= 24)
|
||||||
@@ -600,7 +592,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char *p = name;
|
char *p = name;
|
||||||
@@ -608,13 +599,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
for (i = subnet->prefixlen-1; i >= 0; i -= 4)
|
||||||
{
|
{
|
||||||
int dig = ((unsigned char *)&subnet->addr.addr.addr6)[i>>3];
|
int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
|
||||||
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||||
}
|
}
|
||||||
p += sprintf(p, "ip6.arpa");
|
p += sprintf(p, "ip6.arpa");
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* handle NS and SOA in auth section or for explicit queries */
|
/* handle NS and SOA in auth section or for explicit queries */
|
||||||
@@ -638,16 +628,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
struct name_list *secondary;
|
struct name_list *secondary;
|
||||||
|
|
||||||
newoffset = ansp - (unsigned char *)header;
|
/* Only include the machine running dnsmasq if it's acting as an auth server */
|
||||||
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
|
if (daemon->authinterface)
|
||||||
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
|
|
||||||
{
|
{
|
||||||
if (offset == 0)
|
newoffset = ansp - (unsigned char *)header;
|
||||||
offset = newoffset;
|
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
|
||||||
if (ns)
|
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
|
||||||
anscount++;
|
{
|
||||||
else
|
if (offset == 0)
|
||||||
authcount++;
|
offset = newoffset;
|
||||||
|
if (ns)
|
||||||
|
anscount++;
|
||||||
|
else
|
||||||
|
authcount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!subnet)
|
if (!subnet)
|
||||||
@@ -751,14 +745,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
|
daemon->auth_ttl, NULL, T_A, C_IN, "4", cut ? intr->name : NULL, &addrlist->addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||||
if ((addrlist->flags & ADDRLIST_IPV6) &&
|
if ((addrlist->flags & ADDRLIST_IPV6) &&
|
||||||
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
|
(local_query || filter_zone(zone, F_IPV6, &addrlist->addr)) &&
|
||||||
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
|
daemon->auth_ttl, NULL, T_AAAA, C_IN, "6", cut ? intr->name : NULL, &addrlist->addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* restore config data */
|
/* restore config data */
|
||||||
if (cut)
|
if (cut)
|
||||||
@@ -795,38 +787,26 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
char *cache_name = cache_get_name(crecp);
|
char *cache_name = cache_get_name(crecp);
|
||||||
if (!strchr(cache_name, '.') &&
|
if (!strchr(cache_name, '.') &&
|
||||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))) &&
|
||||||
{
|
add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
qtype = T_A;
|
daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN,
|
||||||
#ifdef HAVE_IPV6
|
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
|
||||||
if (crecp->flags & F_IPV6)
|
anscount++;
|
||||||
qtype = T_AAAA;
|
|
||||||
#endif
|
|
||||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
|
||||||
(crecp->flags & F_IPV4) ? "4" : "6", cache_name, &crecp->addr))
|
|
||||||
anscount++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
if ((crecp->flags & F_HOSTS) || (((crecp->flags & F_DHCP) && option_bool(OPT_DHCP_FQDN))))
|
||||||
{
|
{
|
||||||
strcpy(name, cache_get_name(crecp));
|
strcpy(name, cache_get_name(crecp));
|
||||||
if (in_zone(zone, name, &cut) &&
|
if (in_zone(zone, name, &cut) &&
|
||||||
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr.addr))))
|
(local_query || filter_zone(zone, (crecp->flags & (F_IPV6 | F_IPV4)), &(crecp->addr))))
|
||||||
{
|
{
|
||||||
qtype = T_A;
|
if (cut)
|
||||||
#ifdef HAVE_IPV6
|
*cut = 0;
|
||||||
if (crecp->flags & F_IPV6)
|
|
||||||
qtype = T_AAAA;
|
|
||||||
#endif
|
|
||||||
if (cut)
|
|
||||||
*cut = 0;
|
|
||||||
|
|
||||||
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, -axfroffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, (crecp->flags & F_IPV6) ? T_AAAA : T_A, C_IN,
|
||||||
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
|
(crecp->flags & F_IPV4) ? "4" : "6", cut ? name : NULL, &crecp->addr))
|
||||||
anscount++;
|
anscount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -860,6 +840,9 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
header->hb4 &= ~HB4_RA;
|
header->hb4 &= ~HB4_RA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* data is never DNSSEC signed. */
|
||||||
|
header->hb4 &= ~HB4_AD;
|
||||||
|
|
||||||
/* authoritative */
|
/* authoritative */
|
||||||
if (auth)
|
if (auth)
|
||||||
header->hb3 |= HB3_AA;
|
header->hb3 |= HB3_AA;
|
||||||
|
|||||||
+41
-15
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,8 +16,6 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
|
|
||||||
static struct blockdata *keyblock_free;
|
static struct blockdata *keyblock_free;
|
||||||
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
||||||
|
|
||||||
@@ -25,7 +23,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 (n > 0 && new)
|
if (new)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -49,19 +47,18 @@ void blockdata_init(void)
|
|||||||
|
|
||||||
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
/* Note that daemon->cachesize is enforced to have non-zero size if OPT_DNSSEC_VALID is set */
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
blockdata_expand((daemon->cachesize * 100) / sizeof(struct blockdata));
|
blockdata_expand(daemon->cachesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blockdata_report(void)
|
void blockdata_report(void)
|
||||||
{
|
{
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
|
||||||
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
|
blockdata_count * sizeof(struct blockdata),
|
||||||
blockdata_count * sizeof(struct blockdata),
|
blockdata_hwm * sizeof(struct blockdata),
|
||||||
blockdata_hwm * sizeof(struct blockdata),
|
blockdata_alloced * sizeof(struct blockdata));
|
||||||
blockdata_alloced * sizeof(struct blockdata));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct blockdata *blockdata_alloc(char *data, size_t len)
|
static struct blockdata *blockdata_alloc_real(int fd, char *data, size_t len)
|
||||||
{
|
{
|
||||||
struct blockdata *block, *ret = NULL;
|
struct blockdata *block, *ret = NULL;
|
||||||
struct blockdata **prev = &ret;
|
struct blockdata **prev = &ret;
|
||||||
@@ -89,8 +86,17 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
|
|||||||
blockdata_hwm = blockdata_count;
|
blockdata_hwm = blockdata_count;
|
||||||
|
|
||||||
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||||
memcpy(block->key, data, blen);
|
if (data)
|
||||||
data += blen;
|
{
|
||||||
|
memcpy(block->key, data, blen);
|
||||||
|
data += blen;
|
||||||
|
}
|
||||||
|
else if (!read_write(fd, block->key, blen, 1))
|
||||||
|
{
|
||||||
|
/* failed read free partial chain */
|
||||||
|
blockdata_free(ret);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
len -= blen;
|
len -= blen;
|
||||||
*prev = block;
|
*prev = block;
|
||||||
prev = &block->next;
|
prev = &block->next;
|
||||||
@@ -100,6 +106,11 @@ struct blockdata *blockdata_alloc(char *data, size_t len)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct blockdata *blockdata_alloc(char *data, size_t len)
|
||||||
|
{
|
||||||
|
return blockdata_alloc_real(0, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
void blockdata_free(struct blockdata *blocks)
|
void blockdata_free(struct blockdata *blocks)
|
||||||
{
|
{
|
||||||
struct blockdata *tmp;
|
struct blockdata *tmp;
|
||||||
@@ -147,5 +158,20 @@ void *blockdata_retrieve(struct blockdata *block, size_t len, void *data)
|
|||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
void blockdata_write(struct blockdata *block, size_t len, int fd)
|
||||||
|
{
|
||||||
|
for (; len > 0 && block; block = block->next)
|
||||||
|
{
|
||||||
|
size_t blen = len > KEYBLOCK_LEN ? KEYBLOCK_LEN : len;
|
||||||
|
read_write(fd, block->key, blen, 0);
|
||||||
|
len -= blen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct blockdata *blockdata_read(int fd, size_t len)
|
||||||
|
{
|
||||||
|
return blockdata_alloc_real(fd, NULL, len);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,9 +31,7 @@
|
|||||||
# include <net/if_var.h>
|
# include <net/if_var.h>
|
||||||
#endif
|
#endif
|
||||||
#include <netinet/in_var.h>
|
#include <netinet/in_var.h>
|
||||||
#ifdef HAVE_IPV6
|
#include <netinet6/in6_var.h>
|
||||||
# include <netinet6/in6_var.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SA_SIZE
|
#ifndef SA_SIZE
|
||||||
#define SA_SIZE(sa) \
|
#define SA_SIZE(sa) \
|
||||||
@@ -44,7 +42,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_BSD_NETWORK
|
#ifdef HAVE_BSD_NETWORK
|
||||||
static int del_family = 0;
|
static int del_family = 0;
|
||||||
static struct all_addr del_addr;
|
static union all_addr del_addr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||||
@@ -121,7 +119,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (getifaddrs(&head) == -1)
|
if (getifaddrs(&head) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
#if defined(HAVE_BSD_NETWORK) && defined(HAVE_IPV6)
|
#if defined(HAVE_BSD_NETWORK)
|
||||||
if (family == AF_INET6)
|
if (family == AF_INET6)
|
||||||
fd = socket(PF_INET6, SOCK_DGRAM, 0);
|
fd = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||||
#endif
|
#endif
|
||||||
@@ -141,7 +139,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct in_addr addr, netmask, broadcast;
|
struct in_addr addr, netmask, broadcast;
|
||||||
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
||||||
#ifdef HAVE_BSD_NETWORK
|
#ifdef HAVE_BSD_NETWORK
|
||||||
if (del_family == AF_INET && del_addr.addr.addr4.s_addr == addr.s_addr)
|
if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
||||||
@@ -152,7 +150,6 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (family == AF_INET6)
|
else if (family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
||||||
@@ -162,14 +159,14 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
u32 valid = 0xffffffff, preferred = 0xffffffff;
|
u32 valid = 0xffffffff, preferred = 0xffffffff;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
#ifdef HAVE_BSD_NETWORK
|
#ifdef HAVE_BSD_NETWORK
|
||||||
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr.addr6, addr))
|
if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||||
struct in6_ifreq ifr6;
|
struct in6_ifreq ifr6;
|
||||||
|
|
||||||
memset(&ifr6, 0, sizeof(ifr6));
|
memset(&ifr6, 0, sizeof(ifr6));
|
||||||
strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||||||
|
|
||||||
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||||||
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
||||||
@@ -219,7 +216,6 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
(int) preferred, (int)valid, parm)))
|
(int) preferred, (int)valid, parm)))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_IPV6 */
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (family == AF_LINK)
|
else if (family == AF_LINK)
|
||||||
@@ -426,11 +422,9 @@ void route_sock(void)
|
|||||||
{
|
{
|
||||||
del_family = sa->sa_family;
|
del_family = sa->sa_family;
|
||||||
if (del_family == AF_INET)
|
if (del_family == AF_INET)
|
||||||
del_addr.addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
|
del_addr.addr4 = ((struct sockaddr_in *)sa)->sin_addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (del_family == AF_INET6)
|
else if (del_family == AF_INET6)
|
||||||
del_addr.addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
|
del_addr.addr6 = ((struct sockaddr_in6 *)sa)->sin6_addr;
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
del_family = 0;
|
del_family = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+610
-312
File diff suppressed because it is too large.
Load diff
+38
-54
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#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 UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
||||||
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
|
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
|
||||||
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
|
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
|
||||||
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||||
@@ -39,9 +40,11 @@
|
|||||||
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
|
||||||
#define SMALLDNAME 50 /* 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 CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
|
||||||
|
#define DNSSEC_MIN_TTL 60 /* DNSKEY and DS records in cache last at least this long */
|
||||||
#define HOSTSFILE "/etc/hosts"
|
#define HOSTSFILE "/etc/hosts"
|
||||||
#define ETHERSFILE "/etc/ethers"
|
#define ETHERSFILE "/etc/ethers"
|
||||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
#define DEFLEASE 3600 /* default DHCPv4 lease time, one hour */
|
||||||
|
#define DEFLEASE6 (3600*24) /* default lease time for DHCPv6. One day. */
|
||||||
#define CHUSER "nobody"
|
#define CHUSER "nobody"
|
||||||
#define CHGRP "dip"
|
#define CHGRP "dip"
|
||||||
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
|
||||||
@@ -49,6 +52,7 @@
|
|||||||
#define RANDFILE "/dev/urandom"
|
#define RANDFILE "/dev/urandom"
|
||||||
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
|
||||||
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
|
||||||
|
#define DNSMASQ_UBUS_NAME "dnsmasq" /* Default - may be overridden by config */
|
||||||
#define AUTH_TTL 600 /* default TTL for auth DNS */
|
#define AUTH_TTL 600 /* default TTL for auth DNS */
|
||||||
#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 */
|
||||||
@@ -93,6 +97,9 @@ HAVE_DBUS
|
|||||||
support some methods to allow (re)configuration of the upstream DNS
|
support some methods to allow (re)configuration of the upstream DNS
|
||||||
servers via DBus.
|
servers via DBus.
|
||||||
|
|
||||||
|
HAVE_UBUS
|
||||||
|
define this if you want to link against libubus
|
||||||
|
|
||||||
HAVE_IDN
|
HAVE_IDN
|
||||||
define this if you want international domain name 2003 support.
|
define this if you want international domain name 2003 support.
|
||||||
|
|
||||||
@@ -116,6 +123,9 @@ HAVE_AUTH
|
|||||||
HAVE_DNSSEC
|
HAVE_DNSSEC
|
||||||
include DNSSEC validator.
|
include DNSSEC validator.
|
||||||
|
|
||||||
|
HAVE_DUMPFILE
|
||||||
|
include code to dump packets to a libpcap-format file for debugging.
|
||||||
|
|
||||||
HAVE_LOOP
|
HAVE_LOOP
|
||||||
include functionality to probe for and remove DNS forwarding loops.
|
include functionality to probe for and remove DNS forwarding loops.
|
||||||
|
|
||||||
@@ -124,21 +134,18 @@ HAVE_INOTIFY
|
|||||||
|
|
||||||
NO_ID
|
NO_ID
|
||||||
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
|
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
|
||||||
NO_IPV6
|
|
||||||
NO_TFTP
|
NO_TFTP
|
||||||
NO_DHCP
|
NO_DHCP
|
||||||
NO_DHCP6
|
NO_DHCP6
|
||||||
NO_SCRIPT
|
NO_SCRIPT
|
||||||
NO_LARGEFILE
|
NO_LARGEFILE
|
||||||
NO_AUTH
|
NO_AUTH
|
||||||
|
NO_DUMPFILE
|
||||||
NO_INOTIFY
|
NO_INOTIFY
|
||||||
these are available to explicitly disable compile time options which would
|
these are available to explicitly disable compile time options which would
|
||||||
otherwise be enabled automatically (HAVE_IPV6, >2Gb file sizes) or
|
otherwise be enabled automatically or which are enabled by default
|
||||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
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
|
NO_GMP
|
||||||
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
Don't use and link against libgmp, Useful if nettle is built with --enable-mini-gmp.
|
||||||
|
|
||||||
@@ -166,6 +173,7 @@ RESOLVFILE
|
|||||||
#define HAVE_AUTH
|
#define HAVE_AUTH
|
||||||
#define HAVE_IPSET
|
#define HAVE_IPSET
|
||||||
#define HAVE_LOOP
|
#define HAVE_LOOP
|
||||||
|
#define HAVE_DUMPFILE
|
||||||
|
|
||||||
/* Build options which require external libraries.
|
/* Build options which require external libraries.
|
||||||
|
|
||||||
@@ -234,27 +242,13 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
defined if struct sockaddr has sa_len field (*BSD)
|
defined if struct sockaddr has sa_len field (*BSD)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Must precede __linux__ since uClinux defines __linux__ too. */
|
#if defined(__UCLIBC__)
|
||||||
#if defined(__uClinux__)
|
|
||||||
#define HAVE_LINUX_NETWORK
|
|
||||||
#define HAVE_GETOPT_LONG
|
|
||||||
#undef HAVE_SOCKADDR_SA_LEN
|
|
||||||
/* Never use fork() on uClinux. Note that this is subtly different from the
|
|
||||||
--keep-in-foreground option, since it also suppresses forking new
|
|
||||||
processes for TCP connections and disables the call-a-script on leasechange
|
|
||||||
system. It's intended for use on MMU-less kernels. */
|
|
||||||
#define NO_FORK
|
|
||||||
|
|
||||||
#elif defined(__UCLIBC__)
|
|
||||||
#define HAVE_LINUX_NETWORK
|
#define HAVE_LINUX_NETWORK
|
||||||
#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \
|
#if defined(__UCLIBC_HAS_GNU_GETOPT__) || \
|
||||||
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
|
((__UCLIBC_MAJOR__==0) && (__UCLIBC_MINOR__==9) && (__UCLIBC_SUBLEVEL__<21))
|
||||||
# define HAVE_GETOPT_LONG
|
# define HAVE_GETOPT_LONG
|
||||||
#endif
|
#endif
|
||||||
#undef HAVE_SOCKADDR_SA_LEN
|
#undef HAVE_SOCKADDR_SA_LEN
|
||||||
#if !defined(__ARCH_HAS_MMU__) && !defined(__UCLIBC_HAS_MMU__)
|
|
||||||
# define NO_FORK
|
|
||||||
#endif
|
|
||||||
#if defined(__UCLIBC_HAS_IPV6__)
|
#if defined(__UCLIBC_HAS_IPV6__)
|
||||||
# ifndef IPV6_V6ONLY
|
# ifndef IPV6_V6ONLY
|
||||||
# define IPV6_V6ONLY 26
|
# define IPV6_V6ONLY 26
|
||||||
@@ -282,11 +276,16 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#define HAVE_BSD_NETWORK
|
#define HAVE_BSD_NETWORK
|
||||||
#define HAVE_GETOPT_LONG
|
#define HAVE_GETOPT_LONG
|
||||||
#define HAVE_SOCKADDR_SA_LEN
|
#define HAVE_SOCKADDR_SA_LEN
|
||||||
|
#define NO_IPSET
|
||||||
/* Define before sys/socket.h is included so we get socklen_t */
|
/* Define before sys/socket.h is included so we get socklen_t */
|
||||||
#define _BSD_SOCKLEN_T_
|
#define _BSD_SOCKLEN_T_
|
||||||
/* 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
|
||||||
|
/* Required for Mojave. */
|
||||||
|
#ifndef SOL_TCP
|
||||||
|
# define SOL_TCP IPPROTO_TCP
|
||||||
|
#endif
|
||||||
#define NO_IPSET
|
#define NO_IPSET
|
||||||
|
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
@@ -302,29 +301,9 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Decide if we're going to support IPv6 */
|
|
||||||
/* We assume that systems which don't have IPv6
|
|
||||||
headers don't have ntop and pton either */
|
|
||||||
|
|
||||||
#if defined(INET6_ADDRSTRLEN) && defined(IPV6_V6ONLY)
|
|
||||||
# define HAVE_IPV6
|
|
||||||
# define ADDRSTRLEN INET6_ADDRSTRLEN
|
|
||||||
#else
|
|
||||||
# if !defined(INET_ADDRSTRLEN)
|
|
||||||
# define INET_ADDRSTRLEN 16 /* 4*3 + 3 dots + NULL */
|
|
||||||
# endif
|
|
||||||
# undef HAVE_IPV6
|
|
||||||
# define ADDRSTRLEN INET_ADDRSTRLEN
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* rules to implement compile-time option dependencies and
|
/* rules to implement compile-time option dependencies and
|
||||||
the NO_XXX flags */
|
the NO_XXX flags */
|
||||||
|
|
||||||
#ifdef NO_IPV6
|
|
||||||
#undef HAVE_IPV6
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef NO_TFTP
|
#ifdef NO_TFTP
|
||||||
#undef HAVE_TFTP
|
#undef HAVE_TFTP
|
||||||
#endif
|
#endif
|
||||||
@@ -334,7 +313,7 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#undef HAVE_DHCP6
|
#undef HAVE_DHCP6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NO_DHCP6) || !defined(HAVE_IPV6)
|
#if defined(NO_DHCP6)
|
||||||
#undef HAVE_DHCP6
|
#undef HAVE_DHCP6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -343,7 +322,7 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#define HAVE_DHCP
|
#define HAVE_DHCP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(NO_SCRIPT) || defined(NO_FORK)
|
#if defined(NO_SCRIPT)
|
||||||
#undef HAVE_SCRIPT
|
#undef HAVE_SCRIPT
|
||||||
#undef HAVE_LUASCRIPT
|
#undef HAVE_LUASCRIPT
|
||||||
#endif
|
#endif
|
||||||
@@ -365,6 +344,10 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#undef HAVE_LOOP
|
#undef HAVE_LOOP
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef NO_DUMPFILE
|
||||||
|
#undef HAVE_DUMPFILE
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
|
#if defined (HAVE_LINUX_NETWORK) && !defined(NO_INOTIFY)
|
||||||
#define HAVE_INOTIFY
|
#define HAVE_INOTIFY
|
||||||
#endif
|
#endif
|
||||||
@@ -375,9 +358,6 @@ HAVE_SOCKADDR_SA_LEN
|
|||||||
#ifdef DNSMASQ_COMPILE_OPTS
|
#ifdef DNSMASQ_COMPILE_OPTS
|
||||||
|
|
||||||
static char *compile_opts =
|
static char *compile_opts =
|
||||||
#ifndef HAVE_IPV6
|
|
||||||
"no-"
|
|
||||||
#endif
|
|
||||||
"IPv6 "
|
"IPv6 "
|
||||||
#ifndef HAVE_GETOPT_LONG
|
#ifndef HAVE_GETOPT_LONG
|
||||||
"no-"
|
"no-"
|
||||||
@@ -386,13 +366,14 @@ static char *compile_opts =
|
|||||||
#ifdef HAVE_BROKEN_RTC
|
#ifdef HAVE_BROKEN_RTC
|
||||||
"no-RTC "
|
"no-RTC "
|
||||||
#endif
|
#endif
|
||||||
#ifdef NO_FORK
|
|
||||||
"no-MMU "
|
|
||||||
#endif
|
|
||||||
#ifndef HAVE_DBUS
|
#ifndef HAVE_DBUS
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"DBus "
|
"DBus "
|
||||||
|
#ifndef HAVE_UBUS
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"UBus "
|
||||||
#ifndef LOCALEDIR
|
#ifndef LOCALEDIR
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
@@ -453,8 +434,11 @@ static char *compile_opts =
|
|||||||
#ifndef HAVE_INOTIFY
|
#ifndef HAVE_INOTIFY
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"inotify";
|
"inotify "
|
||||||
|
#ifndef HAVE_DUMPFILE
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"dumpfile";
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+4
-6
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,7 @@ static int gotit = 0; /* yuck */
|
|||||||
|
|
||||||
static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data);
|
static int callback(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data);
|
||||||
|
|
||||||
int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr, int istcp, unsigned int *markp)
|
int get_incoming_mark(union mysockaddr *peer_addr, union all_addr *local_addr, int istcp, unsigned int *markp)
|
||||||
{
|
{
|
||||||
struct nf_conntrack *ct;
|
struct nf_conntrack *ct;
|
||||||
struct nfct_handle *h;
|
struct nfct_handle *h;
|
||||||
@@ -36,21 +36,19 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
|
|||||||
nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP);
|
nfct_set_attr_u8(ct, ATTR_L4PROTO, istcp ? IPPROTO_TCP : IPPROTO_UDP);
|
||||||
nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port));
|
nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(daemon->port));
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (peer_addr->sa.sa_family == AF_INET6)
|
if (peer_addr->sa.sa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
|
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6);
|
||||||
nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr);
|
nfct_set_attr(ct, ATTR_IPV6_SRC, peer_addr->in6.sin6_addr.s6_addr);
|
||||||
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port);
|
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in6.sin6_port);
|
||||||
nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr.addr6.s6_addr);
|
nfct_set_attr(ct, ATTR_IPV6_DST, local_addr->addr6.s6_addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
|
nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET);
|
||||||
nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr);
|
nfct_set_attr_u32(ct, ATTR_IPV4_SRC, peer_addr->in.sin_addr.s_addr);
|
||||||
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port);
|
nfct_set_attr_u16(ct, ATTR_PORT_SRC, peer_addr->in.sin_port);
|
||||||
nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr.addr4.s_addr);
|
nfct_set_attr_u32(ct, ATTR_IPV4_DST, local_addr->addr4.s_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+475
@@ -0,0 +1,475 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
|
||||||
|
#include <nettle/rsa.h>
|
||||||
|
#include <nettle/ecdsa.h>
|
||||||
|
#include <nettle/ecc-curve.h>
|
||||||
|
#include <nettle/eddsa.h>
|
||||||
|
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR >= 6
|
||||||
|
# include <nettle/gostdsa.h>
|
||||||
|
#endif
|
||||||
|
#include <nettle/nettle-meta.h>
|
||||||
|
#include <nettle/bignum.h>
|
||||||
|
|
||||||
|
/* Implement a "hash-function" to the nettle API, which simply returns
|
||||||
|
the input data, concatenated into a single, statically maintained, buffer.
|
||||||
|
|
||||||
|
Used for the EdDSA sigs, which operate on the whole message, rather
|
||||||
|
than a digest. */
|
||||||
|
|
||||||
|
struct null_hash_digest
|
||||||
|
{
|
||||||
|
uint8_t *buff;
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct null_hash_ctx
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
static size_t null_hash_buff_sz = 0;
|
||||||
|
static uint8_t *null_hash_buff = NULL;
|
||||||
|
#define BUFF_INCR 128
|
||||||
|
|
||||||
|
static void null_hash_init(void *ctx)
|
||||||
|
{
|
||||||
|
((struct null_hash_ctx *)ctx)->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
|
||||||
|
{
|
||||||
|
struct null_hash_ctx *ctx = ctxv;
|
||||||
|
size_t new_len = ctx->len + length;
|
||||||
|
|
||||||
|
if (new_len > null_hash_buff_sz)
|
||||||
|
{
|
||||||
|
uint8_t *new;
|
||||||
|
|
||||||
|
if (!(new = whine_malloc(new_len + BUFF_INCR)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (null_hash_buff)
|
||||||
|
{
|
||||||
|
if (ctx->len != 0)
|
||||||
|
memcpy(new, null_hash_buff, ctx->len);
|
||||||
|
free(null_hash_buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
null_hash_buff_sz = new_len + BUFF_INCR;
|
||||||
|
null_hash_buff = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(null_hash_buff + ctx->len, src, length);
|
||||||
|
ctx->len += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
|
||||||
|
{
|
||||||
|
(void)length;
|
||||||
|
|
||||||
|
((struct null_hash_digest *)dst)->buff = null_hash_buff;
|
||||||
|
((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct nettle_hash null_hash = {
|
||||||
|
"null_hash",
|
||||||
|
sizeof(struct null_hash_ctx),
|
||||||
|
sizeof(struct null_hash_digest),
|
||||||
|
0,
|
||||||
|
(nettle_hash_init_func *) null_hash_init,
|
||||||
|
(nettle_hash_update_func *) null_hash_update,
|
||||||
|
(nettle_hash_digest_func *) null_hash_digest
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Find pointer to correct hash function in nettle library */
|
||||||
|
const struct nettle_hash *hash_find(char *name)
|
||||||
|
{
|
||||||
|
if (!name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* We provide a "null" hash which returns the input data as digest. */
|
||||||
|
if (strcmp(null_hash.name, name) == 0)
|
||||||
|
return &null_hash;
|
||||||
|
|
||||||
|
/* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
|
||||||
|
incompatibilities if sizeof(nettle_hashes) changes between library
|
||||||
|
versions. It also #defines nettle_hashes, so use that to tell
|
||||||
|
if we have the new facilities. */
|
||||||
|
|
||||||
|
#ifdef nettle_hashes
|
||||||
|
return nettle_lookup_hash(name);
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; nettle_hashes[i]; i++)
|
||||||
|
if (strcmp(nettle_hashes[i]->name, name) == 0)
|
||||||
|
return nettle_hashes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expand ctx and digest memory allocations if necessary and init hash function */
|
||||||
|
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
|
||||||
|
{
|
||||||
|
static void *ctx = NULL;
|
||||||
|
static unsigned char *digest = NULL;
|
||||||
|
static unsigned int ctx_sz = 0;
|
||||||
|
static unsigned int digest_sz = 0;
|
||||||
|
|
||||||
|
void *new;
|
||||||
|
|
||||||
|
if (ctx_sz < hash->context_size)
|
||||||
|
{
|
||||||
|
if (!(new = whine_malloc(hash->context_size)))
|
||||||
|
return 0;
|
||||||
|
if (ctx)
|
||||||
|
free(ctx);
|
||||||
|
ctx = new;
|
||||||
|
ctx_sz = hash->context_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digest_sz < hash->digest_size)
|
||||||
|
{
|
||||||
|
if (!(new = whine_malloc(hash->digest_size)))
|
||||||
|
return 0;
|
||||||
|
if (digest)
|
||||||
|
free(digest);
|
||||||
|
digest = new;
|
||||||
|
digest_sz = hash->digest_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ctxp = ctx;
|
||||||
|
*digestp = digest;
|
||||||
|
|
||||||
|
hash->init(ctx);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
size_t exp_len;
|
||||||
|
|
||||||
|
static struct rsa_public_key *key = NULL;
|
||||||
|
static mpz_t sig_mpz;
|
||||||
|
|
||||||
|
(void)digest_len;
|
||||||
|
|
||||||
|
if (key == NULL)
|
||||||
|
{
|
||||||
|
if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_rsa_public_key_init(key);
|
||||||
|
mpz_init(sig_mpz);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
key_len--;
|
||||||
|
if ((exp_len = *p++) == 0)
|
||||||
|
{
|
||||||
|
GETSHORT(exp_len, p);
|
||||||
|
key_len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp_len >= key_len)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
key->size = key_len - exp_len;
|
||||||
|
mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
|
||||||
|
mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
|
||||||
|
|
||||||
|
mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 5: case 7:
|
||||||
|
return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
|
||||||
|
case 8:
|
||||||
|
return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
|
||||||
|
case 10:
|
||||||
|
return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||||
|
unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
unsigned int t;
|
||||||
|
struct ecc_point *key;
|
||||||
|
|
||||||
|
static struct ecc_point *key_256 = NULL, *key_384 = NULL;
|
||||||
|
static mpz_t x, y;
|
||||||
|
static struct dsa_signature *sig_struct;
|
||||||
|
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR < 4
|
||||||
|
#define nettle_get_secp_256r1() (&nettle_secp_256r1)
|
||||||
|
#define nettle_get_secp_384r1() (&nettle_secp_384r1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!sig_struct)
|
||||||
|
{
|
||||||
|
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_dsa_signature_init(sig_struct);
|
||||||
|
mpz_init(x);
|
||||||
|
mpz_init(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 13:
|
||||||
|
if (!key_256)
|
||||||
|
{
|
||||||
|
if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_ecc_point_init(key_256, nettle_get_secp_256r1());
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key_256;
|
||||||
|
t = 32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
if (!key_384)
|
||||||
|
{
|
||||||
|
if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_ecc_point_init(key_384, nettle_get_secp_384r1());
|
||||||
|
}
|
||||||
|
|
||||||
|
key = key_384;
|
||||||
|
t = 48;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sig_len != 2*t || key_len != 2*t ||
|
||||||
|
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(x, t , 1, 1, 0, 0, p);
|
||||||
|
mpz_import(y, t , 1, 1, 0, 0, p + t);
|
||||||
|
|
||||||
|
if (!ecc_point_set(key, x, y))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
|
||||||
|
mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
|
||||||
|
|
||||||
|
return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR >= 6
|
||||||
|
static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||||
|
unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
static struct ecc_point *gost_key = NULL;
|
||||||
|
static mpz_t x, y;
|
||||||
|
static struct dsa_signature *sig_struct;
|
||||||
|
|
||||||
|
if (algo != 12 ||
|
||||||
|
sig_len != 64 || key_len != 64 ||
|
||||||
|
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!sig_struct)
|
||||||
|
{
|
||||||
|
if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
|
||||||
|
!(gost_key = whine_malloc(sizeof(struct ecc_point))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nettle_dsa_signature_init(sig_struct);
|
||||||
|
nettle_ecc_point_init(gost_key, nettle_get_gost_gc256b());
|
||||||
|
mpz_init(x);
|
||||||
|
mpz_init(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpz_import(x, 32 , 1, 1, 0, 0, p);
|
||||||
|
mpz_import(y, 32 , 1, 1, 0, 0, p + 32);
|
||||||
|
|
||||||
|
if (!ecc_point_set(gost_key, x, y))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig);
|
||||||
|
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig + 32);
|
||||||
|
|
||||||
|
return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len,
|
||||||
|
unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
unsigned char *p;
|
||||||
|
|
||||||
|
if (digest_len != sizeof(struct null_hash_digest) ||
|
||||||
|
!(p = blockdata_retrieve(key_data, key_len, NULL)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* The "digest" returned by the null_hash function is simply a struct null_hash_digest
|
||||||
|
which has a pointer to the actual data and a length, because the buffer
|
||||||
|
may need to be extended during "hashing". */
|
||||||
|
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 15:
|
||||||
|
if (key_len != ED25519_KEY_SIZE ||
|
||||||
|
sig_len != ED25519_SIGNATURE_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ed25519_sha512_verify(p,
|
||||||
|
((struct null_hash_digest *)digest)->len,
|
||||||
|
((struct null_hash_digest *)digest)->buff,
|
||||||
|
sig);
|
||||||
|
|
||||||
|
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR >= 6
|
||||||
|
case 16:
|
||||||
|
if (key_len != ED448_KEY_SIZE ||
|
||||||
|
sig_len != ED448_SIGNATURE_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ed448_shake256_verify(p,
|
||||||
|
((struct null_hash_digest *)digest)->len,
|
||||||
|
((struct null_hash_digest *)digest)->buff,
|
||||||
|
sig);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Ensure at runtime that we have support for this digest */
|
||||||
|
if (!hash_find(algo_digest_name(algo)))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 5: case 7: case 8: case 10:
|
||||||
|
return dnsmasq_rsa_verify;
|
||||||
|
|
||||||
|
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR >= 6
|
||||||
|
case 12:
|
||||||
|
return dnsmasq_gostdsa_verify;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
case 13: case 14:
|
||||||
|
return dnsmasq_ecdsa_verify;
|
||||||
|
|
||||||
|
case 15: case 16:
|
||||||
|
return dnsmasq_eddsa_verify;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo)
|
||||||
|
{
|
||||||
|
|
||||||
|
int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo);
|
||||||
|
|
||||||
|
func = verify_func(algo);
|
||||||
|
|
||||||
|
if (!func)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
|
||||||
|
define which algo numbers we support. If algo_digest_name() returns
|
||||||
|
non-NULL for an algorithm number, we assume that algorithm is
|
||||||
|
supported by verify(). */
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
|
||||||
|
char *ds_digest_name(int digest)
|
||||||
|
{
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case 1: return "sha1";
|
||||||
|
case 2: return "sha256";
|
||||||
|
case 3: return "gosthash94";
|
||||||
|
case 4: return "sha384";
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
|
||||||
|
char *algo_digest_name(int algo)
|
||||||
|
{
|
||||||
|
switch (algo)
|
||||||
|
{
|
||||||
|
case 1: return NULL; /* RSA/MD5 - Must Not Implement. RFC 6944 para 2.3. */
|
||||||
|
case 2: return NULL; /* Diffie-Hellman */
|
||||||
|
case 3: return NULL; ; /* DSA/SHA1 - Must Not Implement. RFC 8624 section 3.1 */
|
||||||
|
case 5: return "sha1"; /* RSA/SHA1 */
|
||||||
|
case 6: return NULL; /* DSA-NSEC3-SHA1 - Must Not Implement. RFC 8624 section 3.1 */
|
||||||
|
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
||||||
|
case 8: return "sha256"; /* RSA/SHA-256 */
|
||||||
|
case 10: return "sha512"; /* RSA/SHA-512 */
|
||||||
|
case 12: return "gosthash94"; /* ECC-GOST */
|
||||||
|
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
||||||
|
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
||||||
|
case 15: return "null_hash"; /* ED25519 */
|
||||||
|
case 16: return "null_hash"; /* ED448 */
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
|
||||||
|
char *nsec3_digest_name(int digest)
|
||||||
|
{
|
||||||
|
switch (digest)
|
||||||
|
{
|
||||||
|
case 1: return "sha1";
|
||||||
|
default: return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+45
-18
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -85,6 +85,9 @@ const char* introspection_xml_template =
|
|||||||
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
#endif
|
#endif
|
||||||
|
" <method name=\"GetMetrics\">\n"
|
||||||
|
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
" </interface>\n"
|
" </interface>\n"
|
||||||
"</node>\n";
|
"</node>\n";
|
||||||
|
|
||||||
@@ -182,9 +185,6 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_IPV6
|
|
||||||
my_syslog(LOG_WARNING, _("attempt to set an IPv6 server address via DBus - no IPv6 support"));
|
|
||||||
#else
|
|
||||||
if (i == sizeof(struct in6_addr))
|
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));
|
||||||
@@ -199,7 +199,6 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
source_addr.in6.sin6_port = htons(daemon->query_port);
|
source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||||
skip = 0;
|
skip = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* At the end */
|
/* At the end */
|
||||||
@@ -238,7 +237,7 @@ static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
|
|||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
if (serv->flags & SERV_LOOP)
|
if (serv->flags & SERV_LOOP)
|
||||||
{
|
{
|
||||||
prettyprint_addr(&serv->addr, daemon->addrbuff);
|
(void)prettyprint_addr(&serv->addr, daemon->addrbuff);
|
||||||
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
|
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -457,7 +456,7 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
|
|||||||
int clid_len, hostname_len, hw_len, hw_type;
|
int clid_len, hostname_len, hw_len, hw_type;
|
||||||
dbus_uint32_t expires, ia_id;
|
dbus_uint32_t expires, ia_id;
|
||||||
dbus_bool_t is_temporary;
|
dbus_bool_t is_temporary;
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
time_t now = dnsmasq_time();
|
time_t now = dnsmasq_time();
|
||||||
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
|
unsigned char dhcp_chaddr[DHCP_CHADDR_MAX];
|
||||||
|
|
||||||
@@ -527,20 +526,20 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
|
|||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &is_temporary);
|
dbus_message_iter_get_basic(&iter, &is_temporary);
|
||||||
|
|
||||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
if (inet_pton(AF_INET, ipaddr, &addr.addr4))
|
||||||
{
|
{
|
||||||
if (ia_id != 0 || is_temporary)
|
if (ia_id != 0 || is_temporary)
|
||||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
"ia_id and is_temporary must be zero for IPv4 lease");
|
"ia_id and is_temporary must be zero for IPv4 lease");
|
||||||
|
|
||||||
if (!(lease = lease_find_by_addr(addr.addr.addr4)))
|
if (!(lease = lease_find_by_addr(addr.addr4)))
|
||||||
lease = lease4_allocate(addr.addr.addr4);
|
lease = lease4_allocate(addr.addr4);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
else if (inet_pton(AF_INET6, ipaddr, &addr.addr6))
|
||||||
{
|
{
|
||||||
if (!(lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0)))
|
if (!(lease = lease6_find_by_addr(&addr.addr6, 128, 0)))
|
||||||
lease = lease6_allocate(&addr.addr.addr6,
|
lease = lease6_allocate(&addr.addr6,
|
||||||
is_temporary ? LEASE_TA : LEASE_NA);
|
is_temporary ? LEASE_TA : LEASE_NA);
|
||||||
lease_set_iaid(lease, ia_id);
|
lease_set_iaid(lease, ia_id);
|
||||||
}
|
}
|
||||||
@@ -571,7 +570,7 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
|
|||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
const char *ipaddr;
|
const char *ipaddr;
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
dbus_bool_t ret = 1;
|
dbus_bool_t ret = 1;
|
||||||
time_t now = dnsmasq_time();
|
time_t now = dnsmasq_time();
|
||||||
|
|
||||||
@@ -585,11 +584,11 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
|
|||||||
|
|
||||||
dbus_message_iter_get_basic(&iter, &ipaddr);
|
dbus_message_iter_get_basic(&iter, &ipaddr);
|
||||||
|
|
||||||
if (inet_pton(AF_INET, ipaddr, &addr.addr.addr4))
|
if (inet_pton(AF_INET, ipaddr, &addr.addr4))
|
||||||
lease = lease_find_by_addr(addr.addr.addr4);
|
lease = lease_find_by_addr(addr.addr4);
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (inet_pton(AF_INET6, ipaddr, &addr.addr.addr6))
|
else if (inet_pton(AF_INET6, ipaddr, &addr.addr6))
|
||||||
lease = lease6_find_by_addr(&addr.addr.addr6, 128, 0);
|
lease = lease6_find_by_addr(&addr.addr6, 128, 0);
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
@@ -613,6 +612,30 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static DBusMessage *dbus_get_metrics(DBusMessage* message)
|
||||||
|
{
|
||||||
|
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||||
|
DBusMessageIter array, dict, iter;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
|
||||||
|
|
||||||
|
for (i = 0; i < __METRIC_MAX; i++) {
|
||||||
|
const char *key = get_metric_name(i);
|
||||||
|
dbus_uint32_t value = daemon->metrics[i];
|
||||||
|
|
||||||
|
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
|
||||||
|
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
|
||||||
|
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
|
||||||
|
dbus_message_iter_close_container(&array, &dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbus_message_iter_close_container(&iter, &array);
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||||
DBusMessage *message,
|
DBusMessage *message,
|
||||||
void *user_data)
|
void *user_data)
|
||||||
@@ -680,6 +703,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
reply = dbus_del_lease(message);
|
reply = dbus_del_lease(message);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else if (strcmp(method, "GetMetrics") == 0)
|
||||||
|
{
|
||||||
|
reply = dbus_get_metrics(message);
|
||||||
|
}
|
||||||
else if (strcmp(method, "ClearCache") == 0)
|
else if (strcmp(method, "ClearCache") == 0)
|
||||||
clear_cache = 1;
|
clear_cache = 1;
|
||||||
else
|
else
|
||||||
|
|||||||
+102
-43
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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 @@ void dhcp_common_init(void)
|
|||||||
|
|
||||||
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
||||||
{
|
{
|
||||||
ssize_t sz;
|
ssize_t sz, new_sz;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@@ -65,9 +65,18 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
|
while ((new_sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
|
||||||
|
|
||||||
|
/* Some kernels seem to ignore MSG_PEEK, and dequeue the packet anyway.
|
||||||
|
If that happens we get EAGAIN here because the socket is non-blocking.
|
||||||
|
Use the result of the original testing recvmsg as long as the buffer
|
||||||
|
was big enough. There's a small race here that may lose the odd packet,
|
||||||
|
but it's UDP anyway. */
|
||||||
|
|
||||||
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
|
if (new_sz == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))
|
||||||
|
new_sz = sz;
|
||||||
|
|
||||||
|
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
|
||||||
@@ -271,35 +280,45 @@ static int is_config_in_context(struct dhcp_context *context, struct dhcp_config
|
|||||||
{
|
{
|
||||||
if (!context) /* called via find_config() from lease_update_from_configs() */
|
if (!context) /* called via find_config() from lease_update_from_configs() */
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!(config->flags & (CONFIG_ADDR | CONFIG_ADDR6)))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if ((context->flags & CONTEXT_V6) && (config->flags & CONFIG_WILDCARD))
|
if (context->flags & CONTEXT_V6)
|
||||||
return 1;
|
{
|
||||||
#endif
|
struct addrlist *addr_list;
|
||||||
|
|
||||||
for (; context; context = context->current)
|
if (!(config->flags & CONFIG_ADDR6))
|
||||||
#ifdef HAVE_DHCP6
|
return 1;
|
||||||
if (context->flags & CONTEXT_V6)
|
|
||||||
{
|
for (; context; context = context->current)
|
||||||
if ((config->flags & CONFIG_ADDR6) && is_same_net6(&config->addr6, &context->start6, context->prefix))
|
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
|
||||||
return 1;
|
{
|
||||||
}
|
if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
|
||||||
else
|
return 1;
|
||||||
|
|
||||||
|
if (is_same_net6(&addr_list->addr.addr6, &context->start6, context->prefix))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
|
{
|
||||||
|
if (!(config->flags & CONFIG_ADDR))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
for (; context; context = context->current)
|
||||||
|
if ((config->flags & CONFIG_ADDR) && is_same_net(config->addr, context->start, context->netmask))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
static struct dhcp_config *find_config_match(struct dhcp_config *configs,
|
||||||
struct dhcp_context *context,
|
struct dhcp_context *context,
|
||||||
unsigned char *clid, int clid_len,
|
unsigned char *clid, int clid_len,
|
||||||
unsigned char *hwaddr, int hw_len,
|
unsigned char *hwaddr, int hw_len,
|
||||||
int hw_type, char *hostname)
|
int hw_type, char *hostname,
|
||||||
|
struct dhcp_netid *tags, int tag_not_needed)
|
||||||
{
|
{
|
||||||
int count, new;
|
int count, new;
|
||||||
struct dhcp_config *config, *candidate;
|
struct dhcp_config *config, *candidate;
|
||||||
@@ -311,7 +330,9 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
{
|
{
|
||||||
if (config->clid_len == clid_len &&
|
if (config->clid_len == clid_len &&
|
||||||
memcmp(config->clid, clid, clid_len) == 0 &&
|
memcmp(config->clid, clid, clid_len) == 0 &&
|
||||||
is_config_in_context(context, config))
|
is_config_in_context(context, config) &&
|
||||||
|
match_netid(config->filter, tags, tag_not_needed))
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
|
/* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
|
||||||
@@ -319,7 +340,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
see lease_update_from_configs() */
|
see lease_update_from_configs() */
|
||||||
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
|
if ((!context || !(context->flags & CONTEXT_V6)) && *clid == 0 && config->clid_len == clid_len-1 &&
|
||||||
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
|
memcmp(config->clid, clid+1, clid_len-1) == 0 &&
|
||||||
is_config_in_context(context, config))
|
is_config_in_context(context, config) &&
|
||||||
|
match_netid(config->filter, tags, tag_not_needed))
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,14 +349,16 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
if (hwaddr)
|
if (hwaddr)
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
|
if (config_has_mac(config, hwaddr, hw_len, hw_type) &&
|
||||||
is_config_in_context(context, config))
|
is_config_in_context(context, config) &&
|
||||||
|
match_netid(config->filter, tags, tag_not_needed))
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
if (hostname && context)
|
if (hostname && context)
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if ((config->flags & CONFIG_NAME) &&
|
if ((config->flags & CONFIG_NAME) &&
|
||||||
hostname_isequal(config->hostname, hostname) &&
|
hostname_isequal(config->hostname, hostname) &&
|
||||||
is_config_in_context(context, config))
|
is_config_in_context(context, config) &&
|
||||||
|
match_netid(config->filter, tags, tag_not_needed))
|
||||||
return config;
|
return config;
|
||||||
|
|
||||||
|
|
||||||
@@ -343,7 +367,8 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
|
|
||||||
/* use match with fewest wildcard octets */
|
/* use match with fewest wildcard octets */
|
||||||
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
|
for (candidate = NULL, count = 0, config = configs; config; config = config->next)
|
||||||
if (is_config_in_context(context, config))
|
if (is_config_in_context(context, config) &&
|
||||||
|
match_netid(config->filter, tags, tag_not_needed))
|
||||||
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next)
|
||||||
if (conf_addr->wildcard_mask != 0 &&
|
if (conf_addr->wildcard_mask != 0 &&
|
||||||
conf_addr->hwaddr_len == hw_len &&
|
conf_addr->hwaddr_len == hw_len &&
|
||||||
@@ -357,6 +382,21 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
|||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Find tagged configs first. */
|
||||||
|
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||||
|
struct dhcp_context *context,
|
||||||
|
unsigned char *clid, int clid_len,
|
||||||
|
unsigned char *hwaddr, int hw_len,
|
||||||
|
int hw_type, char *hostname, struct dhcp_netid *tags)
|
||||||
|
{
|
||||||
|
struct dhcp_config *ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 0);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
ret = find_config_match(configs, context, clid, clid_len, hwaddr, hw_len, hw_type, hostname, tags, 1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void dhcp_update_configs(struct dhcp_config *configs)
|
void dhcp_update_configs(struct dhcp_config *configs)
|
||||||
{
|
{
|
||||||
/* Some people like to keep all static IP addresses in /etc/hosts.
|
/* Some people like to keep all static IP addresses in /etc/hosts.
|
||||||
@@ -371,8 +411,14 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
int prot = AF_INET;
|
int prot = AF_INET;
|
||||||
|
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
|
{
|
||||||
if (config->flags & CONFIG_ADDR_HOSTS)
|
if (config->flags & CONFIG_ADDR_HOSTS)
|
||||||
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR6 | CONFIG_ADDR_HOSTS);
|
config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS);
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (config->flags & CONFIG_ADDR6_HOSTS)
|
||||||
|
config->flags &= ~(CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
again:
|
again:
|
||||||
@@ -403,30 +449,41 @@ void dhcp_update_configs(struct dhcp_config *configs)
|
|||||||
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
|
crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
|
||||||
if (!crec)
|
if (!crec)
|
||||||
continue; /* should be never */
|
continue; /* should be never */
|
||||||
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
|
||||||
config->hostname, daemon->addrbuff);
|
config->hostname, daemon->addrbuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prot == AF_INET &&
|
if (prot == AF_INET &&
|
||||||
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr.addr.addr4)) || conf_tmp == config))
|
(!(conf_tmp = config_find_by_address(configs, crec->addr.addr4)) || conf_tmp == config))
|
||||||
{
|
{
|
||||||
config->addr = crec->addr.addr.addr.addr4;
|
config->addr = crec->addr.addr4;
|
||||||
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (prot == AF_INET6 &&
|
if (prot == AF_INET6 &&
|
||||||
(!(conf_tmp = config_find_by_address6(configs, &crec->addr.addr.addr.addr6, 128, 0)) || conf_tmp == config))
|
(!(conf_tmp = config_find_by_address6(configs, NULL, 0, &crec->addr.addr6)) || conf_tmp == config))
|
||||||
{
|
{
|
||||||
memcpy(&config->addr6, &crec->addr.addr.addr.addr6, IN6ADDRSZ);
|
/* host must have exactly one address if comming from /etc/hosts. */
|
||||||
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR_HOSTS;
|
if (!config->addr6 && (config->addr6 = whine_malloc(sizeof(struct addrlist))))
|
||||||
|
{
|
||||||
|
config->addr6->next = NULL;
|
||||||
|
config->addr6->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->addr6 && !config->addr6->next && !(config->addr6->flags & (ADDRLIST_WILDCARD|ADDRLIST_PREFIX)))
|
||||||
|
{
|
||||||
|
memcpy(&config->addr6->addr.addr6, &crec->addr.addr6, IN6ADDRSZ);
|
||||||
|
config->flags |= CONFIG_ADDR6 | CONFIG_ADDR6_HOSTS;
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(prot, &crec->addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"),
|
||||||
daemon->addrbuff, config->hostname);
|
daemon->addrbuff, config->hostname);
|
||||||
|
|
||||||
@@ -485,11 +542,11 @@ char *whichdevice(void)
|
|||||||
|
|
||||||
void bindtodevice(char *device, int fd)
|
void bindtodevice(char *device, int fd)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
size_t len = strlen(device)+1;
|
||||||
|
if (len > IFNAMSIZ)
|
||||||
strcpy(ifr.ifr_name, device);
|
len = IFNAMSIZ;
|
||||||
/* only allowed by root. */
|
/* only allowed by root. */
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) == -1 &&
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
|
||||||
errno != EPERM)
|
errno != EPERM)
|
||||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||||
}
|
}
|
||||||
@@ -559,6 +616,7 @@ static const struct opttab_t {
|
|||||||
{ "nntp-server", 71, OT_ADDR_LIST },
|
{ "nntp-server", 71, OT_ADDR_LIST },
|
||||||
{ "irc-server", 74, OT_ADDR_LIST },
|
{ "irc-server", 74, OT_ADDR_LIST },
|
||||||
{ "user-class", 77, 0 },
|
{ "user-class", 77, 0 },
|
||||||
|
{ "rapid-commit", 80, 0 },
|
||||||
{ "FQDN", 81, OT_INTERNAL },
|
{ "FQDN", 81, OT_INTERNAL },
|
||||||
{ "agent-id", 82, OT_INTERNAL },
|
{ "agent-id", 82, OT_INTERNAL },
|
||||||
{ "client-arch", 93, 2 | OT_DEC },
|
{ "client-arch", 93, 2 | OT_DEC },
|
||||||
@@ -569,6 +627,7 @@ static const struct opttab_t {
|
|||||||
{ "sip-server", 120, 0 },
|
{ "sip-server", 120, 0 },
|
||||||
{ "classless-static-route", 121, 0 },
|
{ "classless-static-route", 121, 0 },
|
||||||
{ "vendor-id-encap", 125, 0 },
|
{ "vendor-id-encap", 125, 0 },
|
||||||
|
{ "tftp-server-address", 150, OT_ADDR_LIST },
|
||||||
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
|
{ "server-ip-address", 255, OT_ADDR_LIST }, /* special, internal only, sets siaddr */
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
@@ -599,7 +658,7 @@ static const struct opttab_t opttab6[] = {
|
|||||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||||
{ "information-refresh-time", 32, OT_TIME },
|
{ "information-refresh-time", 32, OT_TIME },
|
||||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||||
{ "ntp-server", 56, 0 },
|
{ "ntp-server", 56, 0 /* OT_ADDR_LIST | OT_RFC1035_NAME */ },
|
||||||
{ "bootfile-url", 59, OT_NAME },
|
{ "bootfile-url", 59, OT_NAME },
|
||||||
{ "bootfile-param", 60, OT_CSTRING },
|
{ "bootfile-param", 60, OT_CSTRING },
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
@@ -692,7 +751,7 @@ char *option_string(int prot, unsigned int opt, unsigned char *val, int opt_len,
|
|||||||
|
|
||||||
if (ot[o].size & OT_ADDR_LIST)
|
if (ot[o].size & OT_ADDR_LIST)
|
||||||
{
|
{
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
int addr_len = INADDRSZ;
|
int addr_len = INADDRSZ;
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -54,6 +54,7 @@
|
|||||||
#define OPTION_SNAME 66
|
#define OPTION_SNAME 66
|
||||||
#define OPTION_FILENAME 67
|
#define OPTION_FILENAME 67
|
||||||
#define OPTION_USER_CLASS 77
|
#define OPTION_USER_CLASS 77
|
||||||
|
#define OPTION_RAPID_COMMIT 80
|
||||||
#define OPTION_CLIENT_FQDN 81
|
#define OPTION_CLIENT_FQDN 81
|
||||||
#define OPTION_AGENT_ID 82
|
#define OPTION_AGENT_ID 82
|
||||||
#define OPTION_ARCH 93
|
#define OPTION_ARCH 93
|
||||||
|
|||||||
+106
-47
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -232,7 +232,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* ARP fiddling uses original interface even if we pretend to use a different one. */
|
/* ARP fiddling uses original interface even if we pretend to use a different one. */
|
||||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If the interface on which the DHCP request was received is an
|
/* If the interface on which the DHCP request was received is an
|
||||||
@@ -255,7 +255,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
|
safe_strncpy(ifr.ifr_name, bridge->iface, sizeof(ifr.ifr_name));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -279,7 +279,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
is_relay_reply = 1;
|
is_relay_reply = 1;
|
||||||
iov.iov_len = sz;
|
iov.iov_len = sz;
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -310,7 +310,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
parm.relay_local.s_addr = 0;
|
parm.relay_local.s_addr = 0;
|
||||||
parm.ind = iface_index;
|
parm.ind = iface_index;
|
||||||
|
|
||||||
if (!iface_check(AF_INET, (struct all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
||||||
{
|
{
|
||||||
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
/* If we failed to match the primary address of the interface, see if we've got a --listen-address
|
||||||
for a secondary */
|
for a secondary */
|
||||||
@@ -401,7 +401,8 @@ void dhcp_packet(time_t now, int pxe_fd)
|
|||||||
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
|
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
|
||||||
pkt->ipi_ifindex = rcvd_iface_index;
|
pkt->ipi_ifindex = rcvd_iface_index;
|
||||||
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 = CMSG_SPACE(sizeof(struct in_pktinfo));
|
||||||
|
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;
|
||||||
|
|
||||||
@@ -507,33 +508,83 @@ static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
|||||||
|
|
||||||
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
|
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
|
||||||
|
|
||||||
static int complete_context(struct in_addr local, int if_index, char *label,
|
static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
|
||||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct dhcp_relay *relay;
|
|
||||||
struct iface_param *param = vparam;
|
|
||||||
|
|
||||||
(void)label;
|
|
||||||
|
|
||||||
for (context = daemon->dhcp; context; context = context->next)
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
{
|
if (!(context->flags & CONTEXT_NETMASK) &&
|
||||||
if (!(context->flags & CONTEXT_NETMASK) &&
|
(is_same_net(addr, context->start, netmask) ||
|
||||||
(is_same_net(local, context->start, netmask) ||
|
is_same_net(addr, context->end, netmask)))
|
||||||
is_same_net(local, context->end, netmask)))
|
|
||||||
{
|
{
|
||||||
if (context->netmask.s_addr != netmask.s_addr &&
|
if (context->netmask.s_addr != netmask.s_addr &&
|
||||||
!(is_same_net(local, context->start, netmask) &&
|
!(is_same_net(addr, context->start, netmask) &&
|
||||||
is_same_net(local, context->end, netmask)))
|
is_same_net(addr, context->end, netmask)))
|
||||||
{
|
{
|
||||||
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
|
strcpy(daemon->dhcp_buff, inet_ntoa(context->start));
|
||||||
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
|
strcpy(daemon->dhcp_buff2, inet_ntoa(context->end));
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
|
||||||
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
|
daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask));
|
||||||
}
|
}
|
||||||
context->netmask = netmask;
|
context->netmask = netmask;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int complete_context(struct in_addr local, int if_index, char *label,
|
||||||
|
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||||
|
{
|
||||||
|
struct dhcp_context *context;
|
||||||
|
struct dhcp_relay *relay;
|
||||||
|
struct iface_param *param = vparam;
|
||||||
|
struct shared_network *share;
|
||||||
|
|
||||||
|
(void)label;
|
||||||
|
|
||||||
|
for (share = daemon->shared_networks; share; share = share->next)
|
||||||
|
{
|
||||||
|
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
if (share->shared_addr.s_addr == 0)
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (share->if_index != 0)
|
||||||
|
{
|
||||||
|
if (share->if_index != if_index)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (share->match_addr.s_addr != local.s_addr)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
|
{
|
||||||
|
if (context->netmask.s_addr != 0 &&
|
||||||
|
is_same_net(share->shared_addr, context->start, context->netmask) &&
|
||||||
|
is_same_net(share->shared_addr, context->end, context->netmask))
|
||||||
|
{
|
||||||
|
/* link it onto the current chain if we've not seen it before */
|
||||||
|
if (context->current == context)
|
||||||
|
{
|
||||||
|
/* For a shared network, we have no way to guess what the default route should be. */
|
||||||
|
context->router.s_addr = 0;
|
||||||
|
context->local = local; /* Use configured address for Server Identifier */
|
||||||
|
context->current = param->current;
|
||||||
|
param->current = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(context->flags & CONTEXT_BRDCAST))
|
||||||
|
context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guess_range_netmask(local, netmask);
|
||||||
|
|
||||||
|
for (context = daemon->dhcp; context; context = context->next)
|
||||||
|
{
|
||||||
if (context->netmask.s_addr != 0 &&
|
if (context->netmask.s_addr != 0 &&
|
||||||
is_same_net(local, context->start, context->netmask) &&
|
is_same_net(local, context->start, context->netmask) &&
|
||||||
is_same_net(local, context->end, context->netmask))
|
is_same_net(local, context->end, context->netmask))
|
||||||
@@ -558,7 +609,7 @@ static int complete_context(struct in_addr local, int if_index, char *label,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||||
if (if_index == param->ind && relay->local.addr.addr4.s_addr == local.s_addr && relay->current == relay &&
|
if (if_index == param->ind && relay->local.addr4.s_addr == local.s_addr && relay->current == relay &&
|
||||||
(param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
|
(param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
|
||||||
{
|
{
|
||||||
relay->current = param->relay;
|
relay->current = param->relay;
|
||||||
@@ -678,7 +729,7 @@ struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int h
|
|||||||
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
|
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
|
||||||
{
|
{
|
||||||
/* overloaded, or configured not to check, loopback interface, return "not in use" */
|
/* overloaded, or configured not to check, loopback interface, return "not in use" */
|
||||||
dummy.hash = 0;
|
dummy.hash = hash;
|
||||||
return &dummy;
|
return &dummy;
|
||||||
}
|
}
|
||||||
else if (icmp_ping(addr))
|
else if (icmp_ping(addr))
|
||||||
@@ -765,24 +816,33 @@ int address_allocate(struct dhcp_context *context,
|
|||||||
(!IN_CLASSC(ntohl(addr.s_addr)) ||
|
(!IN_CLASSC(ntohl(addr.s_addr)) ||
|
||||||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
|
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
|
||||||
{
|
{
|
||||||
struct ping_result *r;
|
/* in consec-ip mode, skip addresses equal to
|
||||||
|
the number of addresses rejected by clients. This
|
||||||
if ((r = do_icmp_ping(now, addr, j, loopback)))
|
should avoid the same client being offered the same
|
||||||
{
|
address after it has rjected it. */
|
||||||
/* consec-ip mode: we offered this address for another client
|
if (option_bool(OPT_CONSEC_ADDR) && c->addr_epoch)
|
||||||
(different hash) recently, don't offer it to this one. */
|
c->addr_epoch--;
|
||||||
if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
|
|
||||||
{
|
|
||||||
*addrp = addr;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* address in use: perturb address selection so that we are
|
struct ping_result *r;
|
||||||
less likely to try this address again. */
|
|
||||||
if (!option_bool(OPT_CONSEC_ADDR))
|
if ((r = do_icmp_ping(now, addr, j, loopback)))
|
||||||
c->addr_epoch++;
|
{
|
||||||
|
/* consec-ip mode: we offered this address for another client
|
||||||
|
(different hash) recently, don't offer it to this one. */
|
||||||
|
if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
|
||||||
|
{
|
||||||
|
*addrp = addr;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* address in use: perturb address selection so that we are
|
||||||
|
less likely to try this address again. */
|
||||||
|
if (!option_bool(OPT_CONSEC_ADDR))
|
||||||
|
c->addr_epoch++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -971,7 +1031,7 @@ char *host_from_dns(struct in_addr addr)
|
|||||||
if (daemon->port == 0)
|
if (daemon->port == 0)
|
||||||
return NULL; /* DNS disabled. */
|
return NULL; /* DNS disabled. */
|
||||||
|
|
||||||
lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4);
|
lookup = cache_find_by_addr(NULL, (union all_addr *)&addr, 0, F_IPV4);
|
||||||
|
|
||||||
if (lookup && (lookup->flags & F_HOSTS))
|
if (lookup && (lookup->flags & F_HOSTS))
|
||||||
{
|
{
|
||||||
@@ -988,8 +1048,7 @@ char *host_from_dns(struct in_addr addr)
|
|||||||
if (!legal_hostname(hostname))
|
if (!legal_hostname(hostname))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
strncpy(daemon->dhcp_buff, hostname, 256);
|
safe_strncpy(daemon->dhcp_buff, hostname, 256);
|
||||||
daemon->dhcp_buff[255] = 0;
|
|
||||||
strip_hostname(daemon->dhcp_buff);
|
strip_hostname(daemon->dhcp_buff);
|
||||||
|
|
||||||
return daemon->dhcp_buff;
|
return daemon->dhcp_buff;
|
||||||
@@ -1001,25 +1060,25 @@ char *host_from_dns(struct in_addr addr)
|
|||||||
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
|
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
|
||||||
{
|
{
|
||||||
/* ->local is same value for all relays on ->current chain */
|
/* ->local is same value for all relays on ->current chain */
|
||||||
struct all_addr from;
|
union all_addr from;
|
||||||
|
|
||||||
if (mess->op != BOOTREQUEST)
|
if (mess->op != BOOTREQUEST)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* source address == relay address */
|
/* source address == relay address */
|
||||||
from.addr.addr4 = relay->local.addr.addr4;
|
from.addr4 = relay->local.addr4;
|
||||||
|
|
||||||
/* already gatewayed ? */
|
/* already gatewayed ? */
|
||||||
if (mess->giaddr.s_addr)
|
if (mess->giaddr.s_addr)
|
||||||
{
|
{
|
||||||
/* if so check if by us, to stomp on loops. */
|
/* if so check if by us, to stomp on loops. */
|
||||||
if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
|
if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* plug in our address */
|
/* plug in our address */
|
||||||
mess->giaddr.s_addr = relay->local.addr.addr4.s_addr;
|
mess->giaddr.s_addr = relay->local.addr4.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mess->hops++) > 20)
|
if ((mess->hops++) > 20)
|
||||||
@@ -1030,7 +1089,7 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess,
|
|||||||
union mysockaddr to;
|
union mysockaddr to;
|
||||||
|
|
||||||
to.sa.sa_family = AF_INET;
|
to.sa.sa_family = AF_INET;
|
||||||
to.in.sin_addr = relay->server.addr.addr4;
|
to.in.sin_addr = relay->server.addr4;
|
||||||
to.in.sin_port = htons(daemon->dhcp_server_port);
|
to.in.sin_port = htons(daemon->dhcp_server_port);
|
||||||
|
|
||||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||||
@@ -1038,7 +1097,7 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess,
|
|||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr.addr4));
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, inet_ntoa(relay->server.addr4));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save this for replies */
|
/* Save this for replies */
|
||||||
@@ -1058,7 +1117,7 @@ static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_i
|
|||||||
|
|
||||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||||
{
|
{
|
||||||
if (mess->giaddr.s_addr == relay->local.addr.addr4.s_addr)
|
if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
||||||
{
|
{
|
||||||
if (!relay->interface || wildcard_match(relay->interface, arrival_interface))
|
if (!relay->interface || wildcard_match(relay->interface, arrival_interface))
|
||||||
return relay->iface_index != 0 ? relay : NULL;
|
return relay->iface_index != 0 ? relay : NULL;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -59,12 +59,12 @@
|
|||||||
#define OPTION6_REMOTE_ID 37
|
#define OPTION6_REMOTE_ID 37
|
||||||
#define OPTION6_SUBSCRIBER_ID 38
|
#define OPTION6_SUBSCRIBER_ID 38
|
||||||
#define OPTION6_FQDN 39
|
#define OPTION6_FQDN 39
|
||||||
|
#define OPTION6_NTP_SERVER 56
|
||||||
#define OPTION6_CLIENT_MAC 79
|
#define OPTION6_CLIENT_MAC 79
|
||||||
|
|
||||||
/* replace this with the real number when allocated.
|
#define NTP_SUBOPTION_SRV_ADDR 1
|
||||||
defining this also enables the relevant code. */
|
#define NTP_SUBOPTION_MC_ADDR 2
|
||||||
/* #define OPTION6_PREFIX_CLASS 99 */
|
#define NTP_SUBOPTION_SRV_FQDN 3
|
||||||
|
|
||||||
|
|
||||||
#define DHCP6SUCCESS 0
|
#define DHCP6SUCCESS 0
|
||||||
#define DHCP6UNSPEC 1
|
#define DHCP6UNSPEC 1
|
||||||
|
|||||||
+190
-143
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -135,7 +135,14 @@ void dhcp6_packet(time_t now)
|
|||||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) == 0)
|
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
|
||||||
|
{
|
||||||
|
from.sin6_port = htons(port);
|
||||||
|
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||||
|
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||||
|
sizeof(from))));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
struct dhcp_bridge *bridge, *alias;
|
struct dhcp_bridge *bridge, *alias;
|
||||||
|
|
||||||
@@ -233,21 +240,23 @@ void dhcp6_packet(time_t now)
|
|||||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||||
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
|
&parm.ll_addr, &parm.ula_addr, sz, &from.sin6_addr, now);
|
||||||
|
|
||||||
|
/* The port in the source address of the original request should
|
||||||
|
be correct, but at least once client sends from the server port,
|
||||||
|
so we explicitly send to the client port to a client, and the
|
||||||
|
server port to a relay. */
|
||||||
|
if (port != 0)
|
||||||
|
{
|
||||||
|
from.sin6_port = htons(port);
|
||||||
|
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||||
|
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||||
|
sizeof(from))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file()
|
||||||
|
may trigger sending an RA packet, which overwrites our buffer. */
|
||||||
lease_update_file(now);
|
lease_update_file(now);
|
||||||
lease_update_dns(0);
|
lease_update_dns(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The port in the source address of the original request should
|
|
||||||
be correct, but at least once client sends from the server port,
|
|
||||||
so we explicitly send to the client port to a client, and the
|
|
||||||
server port to a relay. */
|
|
||||||
if (port != 0)
|
|
||||||
{
|
|
||||||
from.sin6_port = htons(port);
|
|
||||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
|
||||||
save_counter(0), 0, (struct sockaddr *)&from,
|
|
||||||
sizeof(from))));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
|
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
|
||||||
@@ -299,106 +308,136 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
|||||||
unsigned int valid, void *vparam)
|
unsigned int valid, void *vparam)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
struct shared_network *share;
|
||||||
struct dhcp_relay *relay;
|
struct dhcp_relay *relay;
|
||||||
struct iface_param *param = vparam;
|
struct iface_param *param = vparam;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
|
|
||||||
(void)scope; /* warning */
|
(void)scope; /* warning */
|
||||||
|
|
||||||
if (if_index == param->ind)
|
if (if_index != param->ind)
|
||||||
{
|
return 1;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(local))
|
|
||||||
param->ll_addr = *local;
|
if (IN6_IS_ADDR_LINKLOCAL(local))
|
||||||
else if (IN6_IS_ADDR_ULA(local))
|
param->ll_addr = *local;
|
||||||
param->ula_addr = *local;
|
else if (IN6_IS_ADDR_ULA(local))
|
||||||
|
param->ula_addr = *local;
|
||||||
if (!IN6_IS_ADDR_LOOPBACK(local) &&
|
|
||||||
!IN6_IS_ADDR_LINKLOCAL(local) &&
|
|
||||||
!IN6_IS_ADDR_MULTICAST(local))
|
|
||||||
{
|
|
||||||
/* if we have --listen-address config, see if the
|
|
||||||
arrival interface has a matching address. */
|
|
||||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
|
||||||
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
|
||||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
|
||||||
param->addr_match = 1;
|
|
||||||
|
|
||||||
/* Determine a globally address on the arrival interface, even
|
|
||||||
if we have no matching dhcp-context, because we're only
|
|
||||||
allocating on remote subnets via relays. This
|
|
||||||
is used as a default for the DNS server option. */
|
|
||||||
param->fallback = *local;
|
|
||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
|
||||||
{
|
|
||||||
if ((context->flags & CONTEXT_DHCP) &&
|
|
||||||
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
|
||||||
prefix <= context->prefix &&
|
|
||||||
is_same_net6(local, &context->start6, context->prefix) &&
|
|
||||||
is_same_net6(local, &context->end6, context->prefix))
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
/* link it onto the current chain if we've not seen it before */
|
|
||||||
if (context->current == context)
|
|
||||||
{
|
|
||||||
struct dhcp_context *tmp, **up;
|
|
||||||
|
|
||||||
/* use interface values only for constructed contexts */
|
|
||||||
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
|
||||||
preferred = valid = 0xffffffff;
|
|
||||||
else if (flags & IFACE_DEPRECATED)
|
|
||||||
preferred = 0;
|
|
||||||
|
|
||||||
if (context->flags & CONTEXT_DEPRECATE)
|
|
||||||
preferred = 0;
|
|
||||||
|
|
||||||
/* order chain, longest preferred time first */
|
|
||||||
for (up = ¶m->current, tmp = param->current; tmp; tmp = tmp->current)
|
|
||||||
if (tmp->preferred <= preferred)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
up = &tmp->current;
|
|
||||||
|
|
||||||
context->current = *up;
|
|
||||||
*up = context;
|
|
||||||
context->local6 = *local;
|
|
||||||
context->preferred = preferred;
|
|
||||||
context->valid = valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
|
||||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr.addr6) && relay->current == relay &&
|
|
||||||
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local)))
|
|
||||||
{
|
|
||||||
relay->current = param->relay;
|
|
||||||
param->relay = relay;
|
|
||||||
param->relay_local = *local;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (IN6_IS_ADDR_LOOPBACK(local) ||
|
||||||
|
IN6_IS_ADDR_LINKLOCAL(local) ||
|
||||||
return 1;
|
IN6_IS_ADDR_MULTICAST(local))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* if we have --listen-address config, see if the
|
||||||
|
arrival interface has a matching address. */
|
||||||
|
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
||||||
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
||||||
|
param->addr_match = 1;
|
||||||
|
|
||||||
|
/* Determine a globally address on the arrival interface, even
|
||||||
|
if we have no matching dhcp-context, because we're only
|
||||||
|
allocating on remote subnets via relays. This
|
||||||
|
is used as a default for the DNS server option. */
|
||||||
|
param->fallback = *local;
|
||||||
|
|
||||||
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
|
if ((context->flags & CONTEXT_DHCP) &&
|
||||||
|
!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
||||||
|
prefix <= context->prefix &&
|
||||||
|
context->current == context)
|
||||||
|
{
|
||||||
|
if (is_same_net6(local, &context->start6, context->prefix) &&
|
||||||
|
is_same_net6(local, &context->end6, context->prefix))
|
||||||
|
{
|
||||||
|
struct dhcp_context *tmp, **up;
|
||||||
|
|
||||||
|
/* use interface values only for constructed contexts */
|
||||||
|
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||||
|
preferred = valid = 0xffffffff;
|
||||||
|
else if (flags & IFACE_DEPRECATED)
|
||||||
|
preferred = 0;
|
||||||
|
|
||||||
|
if (context->flags & CONTEXT_DEPRECATE)
|
||||||
|
preferred = 0;
|
||||||
|
|
||||||
|
/* order chain, longest preferred time first */
|
||||||
|
for (up = ¶m->current, tmp = param->current; tmp; tmp = tmp->current)
|
||||||
|
if (tmp->preferred <= preferred)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
up = &tmp->current;
|
||||||
|
|
||||||
|
context->current = *up;
|
||||||
|
*up = context;
|
||||||
|
context->local6 = *local;
|
||||||
|
context->preferred = preferred;
|
||||||
|
context->valid = valid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (share = daemon->shared_networks; share; share = share->next)
|
||||||
|
{
|
||||||
|
/* IPv4 shared_address - ignore */
|
||||||
|
if (share->shared_addr.s_addr != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (share->if_index != 0)
|
||||||
|
{
|
||||||
|
if (share->if_index != if_index)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!IN6_ARE_ADDR_EQUAL(&share->match_addr6, local))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_same_net6(&share->shared_addr6, &context->start6, context->prefix) &&
|
||||||
|
is_same_net6(&share->shared_addr6, &context->end6, context->prefix))
|
||||||
|
{
|
||||||
|
context->current = param->current;
|
||||||
|
param->current = context;
|
||||||
|
context->local6 = *local;
|
||||||
|
context->preferred = context->flags & CONTEXT_DEPRECATE ? 0 :0xffffffff;
|
||||||
|
context->valid = 0xffffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||||
|
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay &&
|
||||||
|
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local)))
|
||||||
|
{
|
||||||
|
relay->current = param->relay;
|
||||||
|
param->relay = relay;
|
||||||
|
param->relay_local = *local;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, u64 addr)
|
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net, int prefix, struct in6_addr *addr)
|
||||||
{
|
{
|
||||||
struct dhcp_config *config;
|
struct dhcp_config *config;
|
||||||
|
|
||||||
for (config = configs; config; config = config->next)
|
for (config = configs; config; config = config->next)
|
||||||
if ((config->flags & CONFIG_ADDR6) &&
|
if (config->flags & CONFIG_ADDR6)
|
||||||
is_same_net6(&config->addr6, net, prefix) &&
|
{
|
||||||
(prefix == 128 || addr6part(&config->addr6) == addr))
|
struct addrlist *addr_list;
|
||||||
return config;
|
|
||||||
|
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
|
||||||
|
if ((!net || is_same_net6(&addr_list->addr.addr6, net, prefix) || ((addr_list->flags & ADDRLIST_WILDCARD) && prefix == 64)) &&
|
||||||
|
is_same_net6(&addr_list->addr.addr6, addr, (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128))
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
||||||
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
|
unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans)
|
||||||
{
|
{
|
||||||
/* Find a free address: exclude anything in use and anything allocated to
|
/* Find a free address: exclude anything in use and anything allocated to
|
||||||
a particular hwaddr/clientid/hostname in our configuration.
|
a particular hwaddr/clientid/hostname in our configuration.
|
||||||
@@ -431,8 +470,15 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
|
if (!temp_addr && option_bool(OPT_CONSEC_ADDR))
|
||||||
/* seed is largest extant lease addr in this context */
|
{
|
||||||
start = lease_find_max_addr6(c) + serial;
|
/* seed is largest extant lease addr in this context,
|
||||||
|
skip addresses equal to the number of addresses rejected
|
||||||
|
by clients. This should avoid the same client being offered the same
|
||||||
|
address after it has rjected it. */
|
||||||
|
start = lease_find_max_addr6(c) + 1 + serial + c->addr_epoch;
|
||||||
|
if (c->addr_epoch)
|
||||||
|
c->addr_epoch--;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
|
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
|
||||||
@@ -453,16 +499,15 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
|||||||
for (d = context; d; d = d->current)
|
for (d = context; d; d = d->current)
|
||||||
if (addr == addr6part(&d->local6))
|
if (addr == addr6part(&d->local6))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
*ans = c->start6;
|
||||||
|
setaddr6part (ans, addr);
|
||||||
|
|
||||||
if (!d &&
|
if (!d &&
|
||||||
!lease6_find_by_addr(&c->start6, c->prefix, addr) &&
|
!lease6_find_by_addr(&c->start6, c->prefix, addr) &&
|
||||||
!config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, addr))
|
!config_find_by_address6(daemon->dhcp_conf, &c->start6, c->prefix, ans))
|
||||||
{
|
return c;
|
||||||
*ans = c->start6;
|
|
||||||
setaddr6part (ans, addr);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr++;
|
addr++;
|
||||||
|
|
||||||
if (addr == addr6part(&c->end6) + 1)
|
if (addr == addr6part(&c->end6) + 1)
|
||||||
@@ -516,27 +561,6 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
|
|
||||||
{
|
|
||||||
if (!config || !(config->flags & CONFIG_ADDR6))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if ((config->flags & CONFIG_WILDCARD) && context->prefix == 64)
|
|
||||||
{
|
|
||||||
*addr = context->start6;
|
|
||||||
setaddr6part(addr, addr6part(&config->addr6));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_same_net6(&context->start6, &config->addr6, context->prefix))
|
|
||||||
{
|
|
||||||
*addr = config->addr6;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void make_duid(time_t now)
|
void make_duid(time_t now)
|
||||||
{
|
{
|
||||||
(void)now;
|
(void)now;
|
||||||
@@ -617,7 +641,8 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
|||||||
char ifrn_name[IFNAMSIZ];
|
char ifrn_name[IFNAMSIZ];
|
||||||
struct in6_addr start6, end6;
|
struct in6_addr start6, end6;
|
||||||
struct dhcp_context *template, *context;
|
struct dhcp_context *template, *context;
|
||||||
|
struct iname *tmp;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)flags;
|
(void)flags;
|
||||||
(void)valid;
|
(void)valid;
|
||||||
@@ -636,17 +661,30 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
|||||||
if (flags & IFACE_DEPRECATED)
|
if (flags & IFACE_DEPRECATED)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name))
|
/* Ignore interfaces where we're not doing RA/DHCP6 */
|
||||||
return 0;
|
if (!indextoname(daemon->icmp6fd, if_index, ifrn_name) ||
|
||||||
|
!iface_check(AF_LOCAL, NULL, ifrn_name, NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && wildcard_match(tmp->name, ifrn_name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
for (template = daemon->dhcp6; template; template = template->next)
|
for (template = daemon->dhcp6; template; template = template->next)
|
||||||
if (!(template->flags & CONTEXT_TEMPLATE))
|
if (!(template->flags & (CONTEXT_TEMPLATE | CONTEXT_CONSTRUCTED)))
|
||||||
{
|
{
|
||||||
/* non-template entries, just fill in interface and local addresses */
|
/* non-template entries, just fill in interface and local addresses */
|
||||||
if (prefix <= template->prefix &&
|
if (prefix <= template->prefix &&
|
||||||
is_same_net6(local, &template->start6, template->prefix) &&
|
is_same_net6(local, &template->start6, template->prefix) &&
|
||||||
is_same_net6(local, &template->end6, template->prefix))
|
is_same_net6(local, &template->end6, template->prefix))
|
||||||
{
|
{
|
||||||
|
/* First time found, do fast RA. */
|
||||||
|
if (template->if_index == 0)
|
||||||
|
{
|
||||||
|
ra_start_unsolicited(param->now, template);
|
||||||
|
param->newone = 1;
|
||||||
|
}
|
||||||
|
|
||||||
template->if_index = if_index;
|
template->if_index = if_index;
|
||||||
template->local6 = *local;
|
template->local6 = *local;
|
||||||
}
|
}
|
||||||
@@ -661,24 +699,33 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
|||||||
setaddr6part(&end6, addr6part(&template->end6));
|
setaddr6part(&end6, addr6part(&template->end6));
|
||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if ((context->flags & CONTEXT_CONSTRUCTED) &&
|
if (!(context->flags & CONTEXT_TEMPLATE) &&
|
||||||
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
|
IN6_ARE_ADDR_EQUAL(&start6, &context->start6) &&
|
||||||
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
|
IN6_ARE_ADDR_EQUAL(&end6, &context->end6))
|
||||||
{
|
{
|
||||||
int flags = context->flags;
|
/* If there's an absolute address context covering this address
|
||||||
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
|
then don't construct one as well. */
|
||||||
if (flags & CONTEXT_OLD)
|
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (context->if_index == if_index)
|
||||||
{
|
{
|
||||||
/* address went, now it's back */
|
int cflags = context->flags;
|
||||||
log_context(AF_INET6, context);
|
context->flags &= ~(CONTEXT_GC | CONTEXT_OLD);
|
||||||
/* fast RAs for a while */
|
if (cflags & CONTEXT_OLD)
|
||||||
ra_start_unsolicited(param->now, context);
|
{
|
||||||
param->newone = 1;
|
/* address went, now it's back, and on the same interface */
|
||||||
/* Add address to name again */
|
log_context(AF_INET6, context);
|
||||||
if (context->flags & CONTEXT_RA_NAME)
|
/* fast RAs for a while */
|
||||||
param->newname = 1;
|
ra_start_unsolicited(param->now, context);
|
||||||
|
param->newone = 1;
|
||||||
|
/* Add address to name again */
|
||||||
|
if (context->flags & CONTEXT_RA_NAME)
|
||||||
|
param->newname = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
|
if (!context && (context = whine_malloc(sizeof (struct dhcp_context))))
|
||||||
|
|||||||
+3
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,6 +16,7 @@
|
|||||||
|
|
||||||
#define NAMESERVER_PORT 53
|
#define NAMESERVER_PORT 53
|
||||||
#define TFTP_PORT 69
|
#define TFTP_PORT 69
|
||||||
|
#define MIN_PORT 1024 /* first non-reserved port */
|
||||||
#define MAX_PORT 65535u
|
#define MAX_PORT 65535u
|
||||||
|
|
||||||
#define IN6ADDRSZ 16
|
#define IN6ADDRSZ 16
|
||||||
@@ -75,6 +76,7 @@
|
|||||||
#define T_AXFR 252
|
#define T_AXFR 252
|
||||||
#define T_MAILB 253
|
#define T_MAILB 253
|
||||||
#define T_ANY 255
|
#define T_ANY 255
|
||||||
|
#define T_CAA 257
|
||||||
|
|
||||||
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
||||||
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
||||||
|
|||||||
+375
-142
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -48,11 +48,17 @@ int main (int argc, char **argv)
|
|||||||
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
long i, max_fd = sysconf(_SC_OPEN_MAX);
|
||||||
char *baduser = NULL;
|
char *baduser = NULL;
|
||||||
int log_err;
|
int log_err;
|
||||||
|
int chown_warn = 0;
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
cap_user_header_t hdr = NULL;
|
cap_user_header_t hdr = NULL;
|
||||||
cap_user_data_t data = NULL;
|
cap_user_data_t data = NULL;
|
||||||
|
int need_cap_net_admin = 0;
|
||||||
|
int need_cap_net_raw = 0;
|
||||||
|
int need_cap_net_bind_service = 0;
|
||||||
char *bound_device = NULL;
|
char *bound_device = NULL;
|
||||||
int did_bind = 0;
|
int did_bind = 0;
|
||||||
|
struct server *serv;
|
||||||
|
char *netlink_warn;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
|
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
@@ -77,17 +83,22 @@ int main (int argc, char **argv)
|
|||||||
sigaction(SIGTERM, &sigact, NULL);
|
sigaction(SIGTERM, &sigact, NULL);
|
||||||
sigaction(SIGALRM, &sigact, NULL);
|
sigaction(SIGALRM, &sigact, NULL);
|
||||||
sigaction(SIGCHLD, &sigact, NULL);
|
sigaction(SIGCHLD, &sigact, NULL);
|
||||||
|
sigaction(SIGINT, &sigact, NULL);
|
||||||
|
|
||||||
/* ignore SIGPIPE */
|
/* ignore SIGPIPE */
|
||||||
sigact.sa_handler = SIG_IGN;
|
sigact.sa_handler = SIG_IGN;
|
||||||
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() */
|
rand_init(); /* Must precede read_opts() */
|
||||||
|
|
||||||
read_opts(argc, argv, compile_opts);
|
read_opts(argc, argv, compile_opts);
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
daemon->kernel_version = kernel_version();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (daemon->edns_pktsz < PACKETSZ)
|
if (daemon->edns_pktsz < PACKETSZ)
|
||||||
daemon->edns_pktsz = PACKETSZ;
|
daemon->edns_pktsz = PACKETSZ;
|
||||||
|
|
||||||
@@ -118,6 +129,9 @@ int main (int argc, char **argv)
|
|||||||
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
daemon->namebuff = safe_malloc(MAXDNAME * 2);
|
||||||
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
daemon->keyname = safe_malloc(MAXDNAME * 2);
|
||||||
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
daemon->workspacename = safe_malloc(MAXDNAME * 2);
|
||||||
|
/* one char flag per possible RR in answer section (may get extended). */
|
||||||
|
daemon->rr_status_sz = 64;
|
||||||
|
daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -129,20 +143,18 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Close any file descriptors we inherited apart from std{in|out|err}
|
/* Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
|
||||||
|
|
||||||
Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
|
|
||||||
otherwise file descriptors we create can end up being 0, 1, or 2
|
otherwise file descriptors we create can end up being 0, 1, or 2
|
||||||
and then get accidentally closed later when we make 0, 1, and 2
|
and then get accidentally closed later when we make 0, 1, and 2
|
||||||
open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
|
open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
|
||||||
but it's not guaranteed. By opening /dev/null three times, we
|
but it's not guaranteed. By opening /dev/null three times, we
|
||||||
ensure that we're not using those fds for real stuff. */
|
ensure that we're not using those fds for real stuff. */
|
||||||
for (i = 0; i < max_fd; i++)
|
for (i = 0; i < 3; i++)
|
||||||
if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
|
open("/dev/null", O_RDWR);
|
||||||
close(i);
|
|
||||||
else
|
/* Close any file descriptors we inherited apart from std{in|out|err} */
|
||||||
open("/dev/null", O_RDWR);
|
close_fds(max_fd, -1, -1, -1);
|
||||||
|
|
||||||
#ifndef HAVE_LINUX_NETWORK
|
#ifndef HAVE_LINUX_NETWORK
|
||||||
# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
|
# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
|
||||||
if (!option_bool(OPT_NOWILD))
|
if (!option_bool(OPT_NOWILD))
|
||||||
@@ -211,7 +223,7 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HAVE_AUTH
|
#ifndef HAVE_AUTH
|
||||||
if (daemon->authserver)
|
if (daemon->auth_zones)
|
||||||
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
|
||||||
|
|
||||||
@@ -220,21 +232,30 @@ int main (int argc, char **argv)
|
|||||||
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
|
#ifndef HAVE_UBUS
|
||||||
daemon->min_port = 1024u;
|
if (option_bool(OPT_UBUS))
|
||||||
|
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (daemon->max_port < daemon->min_port)
|
if (daemon->max_port < daemon->min_port)
|
||||||
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
/* Create a serial at startup if not configured. */
|
if (daemon->auth_zones)
|
||||||
if (daemon->authinterface && daemon->soa_sn == 0)
|
{
|
||||||
|
if (!daemon->authserver)
|
||||||
|
die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
|
||||||
|
|
||||||
|
/* Create a serial at startup if not configured. */
|
||||||
#ifdef HAVE_BROKEN_RTC
|
#ifdef HAVE_BROKEN_RTC
|
||||||
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
|
if (daemon->soa_sn == 0)
|
||||||
|
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
|
||||||
#else
|
#else
|
||||||
daemon->soa_sn = now;
|
if (daemon->soa_sn == 0)
|
||||||
|
daemon->soa_sn = now;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->dhcp6)
|
if (daemon->dhcp6)
|
||||||
@@ -271,11 +292,24 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (daemon->dhcp || daemon->relay4)
|
if (daemon->dhcp || daemon->relay4)
|
||||||
dhcp_init();
|
{
|
||||||
|
dhcp_init();
|
||||||
|
# ifdef HAVE_LINUX_NETWORK
|
||||||
|
if (!option_bool(OPT_NO_PING))
|
||||||
|
need_cap_net_raw = 1;
|
||||||
|
need_cap_net_admin = 1;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
# ifdef HAVE_DHCP6
|
# ifdef HAVE_DHCP6
|
||||||
if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
|
if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
|
||||||
ra_init(now);
|
{
|
||||||
|
ra_init(now);
|
||||||
|
# ifdef HAVE_LINUX_NETWORK
|
||||||
|
need_cap_net_raw = 1;
|
||||||
|
need_cap_net_admin = 1;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
if (daemon->doing_dhcp6 || daemon->relay6)
|
if (daemon->doing_dhcp6 || daemon->relay6)
|
||||||
dhcp6_init();
|
dhcp6_init();
|
||||||
@@ -285,11 +319,16 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
if (daemon->ipsets)
|
if (daemon->ipsets)
|
||||||
ipset_init();
|
{
|
||||||
|
ipset_init();
|
||||||
|
# ifdef HAVE_LINUX_NETWORK
|
||||||
|
need_cap_net_admin = 1;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
netlink_init();
|
netlink_warn = netlink_init();
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
route_init();
|
route_init();
|
||||||
#endif
|
#endif
|
||||||
@@ -352,18 +391,26 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
cache_init();
|
cache_init();
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
blockdata_init();
|
blockdata_init();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
|
||||||
|
&& (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
|
||||||
inotify_dnsmasq_init();
|
inotify_dnsmasq_init();
|
||||||
else
|
else
|
||||||
daemon->inotifyfd = -1;
|
daemon->inotifyfd = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (daemon->dump_file)
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
dump_init();
|
||||||
|
else
|
||||||
|
daemon->dumpfd = -1;
|
||||||
|
#else
|
||||||
|
die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (option_bool(OPT_DBUS))
|
if (option_bool(OPT_DBUS))
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
{
|
{
|
||||||
@@ -377,6 +424,16 @@ int main (int argc, char **argv)
|
|||||||
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 (option_bool(OPT_UBUS))
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
{
|
||||||
|
daemon->ubus = NULL;
|
||||||
|
ubus_init();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
pre_allocate_sfds();
|
pre_allocate_sfds();
|
||||||
|
|
||||||
@@ -386,10 +443,12 @@ int main (int argc, char **argv)
|
|||||||
daemon->scriptuser &&
|
daemon->scriptuser &&
|
||||||
(daemon->lease_change_command || daemon->luascript))
|
(daemon->lease_change_command || daemon->luascript))
|
||||||
{
|
{
|
||||||
if ((ent_pw = getpwnam(daemon->scriptuser)))
|
struct passwd *scr_pw;
|
||||||
|
|
||||||
|
if ((scr_pw = getpwnam(daemon->scriptuser)))
|
||||||
{
|
{
|
||||||
script_uid = ent_pw->pw_uid;
|
script_uid = scr_pw->pw_uid;
|
||||||
script_gid = ent_pw->pw_gid;
|
script_gid = scr_pw->pw_gid;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
baduser = daemon->scriptuser;
|
baduser = daemon->scriptuser;
|
||||||
@@ -416,28 +475,81 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
|
/* We keep CAP_NETADMIN (for ARP-injection) and
|
||||||
|
CAP_NET_RAW (for icmp) if we're doing dhcp,
|
||||||
|
if we have yet to bind ports because of DAD,
|
||||||
|
or we're doing it dynamically, we need CAP_NET_BIND_SERVICE. */
|
||||||
|
if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
|
||||||
|
(option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
|
||||||
|
need_cap_net_bind_service = 1;
|
||||||
|
|
||||||
|
/* usptream servers which bind to an interface call SO_BINDTODEVICE
|
||||||
|
for each TCP connection, so need CAP_NET_RAW */
|
||||||
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
if (serv->interface[0] != 0)
|
||||||
|
need_cap_net_raw = 1;
|
||||||
|
|
||||||
|
/* If we're doing Dbus or UBus, the above can be set dynamically,
|
||||||
|
(as can ports) so always (potentially) needed. */
|
||||||
|
#ifdef HAVE_DBUS
|
||||||
|
if (option_bool(OPT_DBUS))
|
||||||
|
{
|
||||||
|
need_cap_net_bind_service = 1;
|
||||||
|
need_cap_net_raw = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
if (option_bool(OPT_UBUS))
|
||||||
|
{
|
||||||
|
need_cap_net_bind_service = 1;
|
||||||
|
need_cap_net_raw = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* determine capability API version here, while we can still
|
/* determine capability API version here, while we can still
|
||||||
call safe_malloc */
|
call safe_malloc */
|
||||||
if (ent_pw && ent_pw->pw_uid != 0)
|
int capsize = 1; /* for header version 1 */
|
||||||
|
char *fail = NULL;
|
||||||
|
|
||||||
|
hdr = safe_malloc(sizeof(*hdr));
|
||||||
|
|
||||||
|
/* find version supported by kernel */
|
||||||
|
memset(hdr, 0, sizeof(*hdr));
|
||||||
|
capget(hdr, NULL);
|
||||||
|
|
||||||
|
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
|
||||||
{
|
{
|
||||||
int capsize = 1; /* for header version 1 */
|
/* if unknown version, use largest supported version (3) */
|
||||||
hdr = safe_malloc(sizeof(*hdr));
|
if (hdr->version != LINUX_CAPABILITY_VERSION_2)
|
||||||
|
hdr->version = LINUX_CAPABILITY_VERSION_3;
|
||||||
/* find version supported by kernel */
|
capsize = 2;
|
||||||
memset(hdr, 0, sizeof(*hdr));
|
|
||||||
capget(hdr, NULL);
|
|
||||||
|
|
||||||
if (hdr->version != LINUX_CAPABILITY_VERSION_1)
|
|
||||||
{
|
|
||||||
/* if unknown version, use largest supported version (3) */
|
|
||||||
if (hdr->version != LINUX_CAPABILITY_VERSION_2)
|
|
||||||
hdr->version = LINUX_CAPABILITY_VERSION_3;
|
|
||||||
capsize = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = safe_malloc(sizeof(*data) * capsize);
|
|
||||||
memset(data, 0, sizeof(*data) * capsize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data = safe_malloc(sizeof(*data) * capsize);
|
||||||
|
capget(hdr, data); /* Get current values, for verification */
|
||||||
|
|
||||||
|
if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
|
||||||
|
fail = "NET_ADMIN";
|
||||||
|
else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
|
||||||
|
fail = "NET_RAW";
|
||||||
|
else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
|
||||||
|
fail = "NET_BIND_SERVICE";
|
||||||
|
|
||||||
|
if (fail)
|
||||||
|
die(_("process is missing required capability %s"), fail, EC_MISC);
|
||||||
|
|
||||||
|
/* Now set bitmaps to set caps after daemonising */
|
||||||
|
memset(data, 0, sizeof(*data) * capsize);
|
||||||
|
|
||||||
|
if (need_cap_net_admin)
|
||||||
|
data->effective |= (1 << CAP_NET_ADMIN);
|
||||||
|
if (need_cap_net_raw)
|
||||||
|
data->effective |= (1 << CAP_NET_RAW);
|
||||||
|
if (need_cap_net_bind_service)
|
||||||
|
data->effective |= (1 << CAP_NET_BIND_SERVICE);
|
||||||
|
|
||||||
|
data->permitted = data->effective;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Use a pipe to carry signals and other events back to the event loop
|
/* Use a pipe to carry signals and other events back to the event loop
|
||||||
@@ -459,7 +571,6 @@ int main (int argc, char **argv)
|
|||||||
if (chdir("/") != 0)
|
if (chdir("/") != 0)
|
||||||
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
#ifndef NO_FORK
|
|
||||||
if (!option_bool(OPT_NO_FORK))
|
if (!option_bool(OPT_NO_FORK))
|
||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
@@ -478,7 +589,7 @@ int main (int argc, char **argv)
|
|||||||
char *msg;
|
char *msg;
|
||||||
|
|
||||||
/* close our copy of write-end */
|
/* close our copy of write-end */
|
||||||
while (retry_send(close(err_pipe[1])));
|
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))
|
||||||
@@ -487,7 +598,7 @@ int main (int argc, char **argv)
|
|||||||
_exit(EC_GOOD);
|
_exit(EC_GOOD);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (retry_send(close(err_pipe[0])));
|
close(err_pipe[0]);
|
||||||
|
|
||||||
/* NO calls to die() from here on. */
|
/* NO calls to die() from here on. */
|
||||||
|
|
||||||
@@ -499,7 +610,6 @@ int main (int argc, char **argv)
|
|||||||
if (pid != 0)
|
if (pid != 0)
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/* write pidfile _after_ forking ! */
|
/* write pidfile _after_ forking ! */
|
||||||
if (daemon->runfile)
|
if (daemon->runfile)
|
||||||
@@ -537,12 +647,20 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* We're still running as root here. Change the ownership of the PID file
|
||||||
|
to the user we will be running as. Note that this is not to allow
|
||||||
|
us to delete the file, since that depends on the permissions
|
||||||
|
of the directory containing the file. That directory will
|
||||||
|
need to by owned by the dnsmasq user, and the ownership of the
|
||||||
|
file has to match, to keep systemd >273 happy. */
|
||||||
|
if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
|
||||||
|
chown_warn = errno;
|
||||||
|
|
||||||
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
|
||||||
err = 1;
|
err = 1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (retry_send(close(fd)));
|
if (close(fd) == -1)
|
||||||
if (errno != 0)
|
|
||||||
err = 1;
|
err = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,18 +713,9 @@ int main (int argc, char **argv)
|
|||||||
if (ent_pw && ent_pw->pw_uid != 0)
|
if (ent_pw && ent_pw->pw_uid != 0)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
/* On linux, we keep CAP_NETADMIN (for ARP-injection) and
|
/* Need to be able to drop root. */
|
||||||
CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
|
data->effective |= (1 << CAP_SETUID);
|
||||||
ports because of DAD, or we're doing it dynamically,
|
data->permitted |= (1 << CAP_SETUID);
|
||||||
we need CAP_NET_BIND_SERVICE too. */
|
|
||||||
if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
|
|
||||||
data->effective = data->permitted = data->inheritable =
|
|
||||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
|
|
||||||
(1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
|
|
||||||
else
|
|
||||||
data->effective = data->permitted = data->inheritable =
|
|
||||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
|
|
||||||
|
|
||||||
/* Tell kernel to not clear capabilities when dropping root */
|
/* Tell kernel to not clear capabilities when dropping root */
|
||||||
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
|
if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
|
||||||
bad_capabilities = errno;
|
bad_capabilities = errno;
|
||||||
@@ -647,15 +756,10 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
|
data->effective &= ~(1 << CAP_SETUID);
|
||||||
data->effective = data->permitted =
|
data->permitted &= ~(1 << CAP_SETUID);
|
||||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
|
|
||||||
else
|
|
||||||
data->effective = data->permitted =
|
|
||||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
|
|
||||||
data->inheritable = 0;
|
|
||||||
|
|
||||||
/* lose the setuid and setgid capabilities */
|
/* lose the setuid capability */
|
||||||
if (capset(hdr, data) == -1)
|
if (capset(hdr, data) == -1)
|
||||||
{
|
{
|
||||||
send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
|
send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
|
||||||
@@ -717,7 +821,11 @@ int main (int argc, char **argv)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (daemon->cachesize != 0)
|
if (daemon->cachesize != 0)
|
||||||
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
|
{
|
||||||
|
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
|
||||||
|
if (daemon->cachesize > 10000)
|
||||||
|
my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
|
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
|
||||||
|
|
||||||
@@ -726,6 +834,9 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
||||||
|
|
||||||
|
if (chown_warn != 0)
|
||||||
|
my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
if (option_bool(OPT_DBUS))
|
if (option_bool(OPT_DBUS))
|
||||||
@@ -737,11 +848,22 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
if (option_bool(OPT_UBUS))
|
||||||
|
{
|
||||||
|
if (daemon->ubus)
|
||||||
|
my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
|
||||||
|
else
|
||||||
|
my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
struct ds_config *ds;
|
||||||
|
|
||||||
/* Delay creating the timestamp file until here, after we've changed user, so that
|
/* 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.
|
it has the correct owner to allow updating the mtime later.
|
||||||
This means we have to report fatal errors via the pipe. */
|
This means we have to report fatal errors via the pipe. */
|
||||||
@@ -751,14 +873,21 @@ int main (int argc, char **argv)
|
|||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
|
if (option_bool(OPT_DNSSEC_IGN_NS))
|
||||||
|
my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
|
||||||
|
else
|
||||||
|
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
|
||||||
|
|
||||||
daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
|
daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
|
||||||
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
|
if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
|
||||||
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
|
||||||
|
|
||||||
if (rc == 1)
|
if (rc == 1)
|
||||||
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
|
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
|
||||||
|
|
||||||
|
for (ds = daemon->ds; ds; ds = ds->next)
|
||||||
|
my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
|
||||||
|
ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -818,6 +947,9 @@ int main (int argc, char **argv)
|
|||||||
# ifdef HAVE_LINUX_NETWORK
|
# ifdef HAVE_LINUX_NETWORK
|
||||||
if (did_bind)
|
if (did_bind)
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
|
||||||
|
|
||||||
|
if (netlink_warn)
|
||||||
|
my_syslog(LOG_WARNING, netlink_warn);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* after dhcp_construct_contexts */
|
/* after dhcp_construct_contexts */
|
||||||
@@ -830,10 +962,11 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
struct tftp_prefix *p;
|
struct tftp_prefix *p;
|
||||||
|
|
||||||
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
|
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%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") : "",
|
||||||
|
option_bool(OPT_SINGLE_PORT) ? _("single port mode") : "");
|
||||||
|
|
||||||
if (tftp_prefix_missing)
|
if (tftp_prefix_missing)
|
||||||
my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
|
my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
|
||||||
@@ -851,7 +984,7 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
if (max_fd < 0)
|
if (max_fd < 0)
|
||||||
max_fd = 5;
|
max_fd = 5;
|
||||||
else if (max_fd < 100)
|
else if (max_fd < 100 && !option_bool(OPT_SINGLE_PORT))
|
||||||
max_fd = max_fd/2;
|
max_fd = max_fd/2;
|
||||||
else
|
else
|
||||||
max_fd = max_fd - 20;
|
max_fd = max_fd - 20;
|
||||||
@@ -874,12 +1007,16 @@ 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)
|
||||||
while (retry_send(close(err_pipe[1])));
|
close(err_pipe[1]);
|
||||||
|
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
check_servers();
|
check_servers();
|
||||||
|
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
|
|
||||||
|
daemon->pipe_to_parent = -1;
|
||||||
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
|
daemon->tcp_pipes[i] = -1;
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
/* Using inotify, have to select a resolv file at startup */
|
/* Using inotify, have to select a resolv file at startup */
|
||||||
@@ -909,8 +1046,13 @@ int main (int argc, char **argv)
|
|||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
set_dbus_listeners();
|
set_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
if (option_bool(OPT_UBUS))
|
||||||
|
set_ubus_listeners();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
if (daemon->dhcp || daemon->relay4)
|
if (daemon->dhcp || daemon->relay4)
|
||||||
{
|
{
|
||||||
@@ -972,7 +1114,7 @@ int main (int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* must do this just before select(), when we know no
|
/* must do this just before do_poll(), when we know no
|
||||||
more calls to my_syslog() can occur */
|
more calls to my_syslog() can occur */
|
||||||
set_log_writer();
|
set_log_writer();
|
||||||
|
|
||||||
@@ -1040,7 +1182,20 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
check_dbus_listeners();
|
check_dbus_listeners();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
if (option_bool(OPT_UBUS))
|
||||||
|
{
|
||||||
|
/* if we didn't create a UBus connection, retry now. */
|
||||||
|
if (!daemon->ubus)
|
||||||
|
{
|
||||||
|
ubus_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
check_ubus_listeners();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
check_dns_listeners(now);
|
check_dns_listeners(now);
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
@@ -1079,7 +1234,7 @@ static void sig_handler(int sig)
|
|||||||
{
|
{
|
||||||
/* ignore anything other than TERM during startup
|
/* ignore anything other than TERM during startup
|
||||||
and in helper proc. (helper ignore TERM too) */
|
and in helper proc. (helper ignore TERM too) */
|
||||||
if (sig == SIGTERM)
|
if (sig == SIGTERM || sig == SIGINT)
|
||||||
exit(EC_MISC);
|
exit(EC_MISC);
|
||||||
}
|
}
|
||||||
else if (pid != getpid())
|
else if (pid != getpid())
|
||||||
@@ -1105,6 +1260,15 @@ static void sig_handler(int sig)
|
|||||||
event = EVENT_DUMP;
|
event = EVENT_DUMP;
|
||||||
else if (sig == SIGUSR2)
|
else if (sig == SIGUSR2)
|
||||||
event = EVENT_REOPEN;
|
event = EVENT_REOPEN;
|
||||||
|
else if (sig == SIGINT)
|
||||||
|
{
|
||||||
|
/* Handle SIGINT normally in debug mode, so
|
||||||
|
ctrl-c continues to operate. */
|
||||||
|
if (option_bool(OPT_DEBUG))
|
||||||
|
exit(EC_MISC);
|
||||||
|
else
|
||||||
|
event = EVENT_TIME;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -1187,31 +1351,40 @@ static void fatal_event(struct event_desc *ev, char *msg)
|
|||||||
|
|
||||||
case EVENT_FORK_ERR:
|
case EVENT_FORK_ERR:
|
||||||
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
die(_("cannot fork into background: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_PIPE_ERR:
|
case EVENT_PIPE_ERR:
|
||||||
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
die(_("failed to create helper: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_CAP_ERR:
|
case EVENT_CAP_ERR:
|
||||||
die(_("setting capabilities failed: %s"), NULL, EC_MISC);
|
die(_("setting capabilities failed: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_USER_ERR:
|
case EVENT_USER_ERR:
|
||||||
die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
|
die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_GROUP_ERR:
|
case EVENT_GROUP_ERR:
|
||||||
die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
|
die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_PIDFILE:
|
case EVENT_PIDFILE:
|
||||||
die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
|
die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_LOG_ERR:
|
case EVENT_LOG_ERR:
|
||||||
die(_("cannot open log %s: %s"), msg, EC_FILE);
|
die(_("cannot open log %s: %s"), msg, EC_FILE);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_LUA_ERR:
|
case EVENT_LUA_ERR:
|
||||||
die(_("failed to load Lua script: %s"), msg, EC_MISC);
|
die(_("failed to load Lua script: %s"), msg, EC_MISC);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
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);
|
||||||
|
|
||||||
|
/* fall through */
|
||||||
case EVENT_TIME_ERR:
|
case EVENT_TIME_ERR:
|
||||||
die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
|
die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
|
||||||
}
|
}
|
||||||
@@ -1232,14 +1405,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
{
|
{
|
||||||
case EVENT_RELOAD:
|
case EVENT_RELOAD:
|
||||||
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
|
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
|
|
||||||
{
|
|
||||||
my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
|
|
||||||
daemon->dnssec_no_time_check = 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case EVENT_INIT:
|
case EVENT_INIT:
|
||||||
@@ -1348,6 +1514,17 @@ static void async_event(int pipe, time_t now)
|
|||||||
poll_resolv(0, 1, now);
|
poll_resolv(0, 1, now);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case EVENT_TIME:
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
|
||||||
|
daemon->dnssec_no_time_check = 0;
|
||||||
|
clear_cache_and_reload(now);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
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++)
|
||||||
@@ -1364,7 +1541,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));
|
||||||
while (retry_send(close(daemon->helperfd)));
|
close(daemon->helperfd);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1382,6 +1559,11 @@ static void async_event(int pipe, time_t now)
|
|||||||
|
|
||||||
if (daemon->runfile)
|
if (daemon->runfile)
|
||||||
unlink(daemon->runfile);
|
unlink(daemon->runfile);
|
||||||
|
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
if (daemon->dumpfd != -1)
|
||||||
|
close(daemon->dumpfd);
|
||||||
|
#endif
|
||||||
|
|
||||||
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
|
my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
|
||||||
flush_log();
|
flush_log();
|
||||||
@@ -1472,9 +1654,6 @@ 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);
|
||||||
@@ -1498,16 +1677,17 @@ static int set_dns_listeners(time_t now)
|
|||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
int tftp = 0;
|
int tftp = 0;
|
||||||
struct tftp_transfer *transfer;
|
struct tftp_transfer *transfer;
|
||||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
if (!option_bool(OPT_SINGLE_PORT))
|
||||||
{
|
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||||
tftp++;
|
{
|
||||||
poll_listen(transfer->sockfd, POLLIN);
|
tftp++;
|
||||||
}
|
poll_listen(transfer->sockfd, POLLIN);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* will we be able to get memory? */
|
/* will we be able to get memory? */
|
||||||
if (daemon->port != 0)
|
if (daemon->port != 0)
|
||||||
get_new_frec(now, &wait, 0);
|
get_new_frec(now, &wait, NULL);
|
||||||
|
|
||||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||||
poll_listen(serverfdp->fd, POLLIN);
|
poll_listen(serverfdp->fd, POLLIN);
|
||||||
@@ -1527,19 +1707,25 @@ static int set_dns_listeners(time_t now)
|
|||||||
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 && daemon->tcp_pipes[i] == -1)
|
||||||
{
|
{
|
||||||
poll_listen(listener->tcpfd, POLLIN);
|
poll_listen(listener->tcpfd, POLLIN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
/* tftp == 0 in single-port mode. */
|
||||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||||
poll_listen(listener->tftpfd, POLLIN);
|
poll_listen(listener->tftpfd, POLLIN);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!option_bool(OPT_DEBUG))
|
||||||
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
|
if (daemon->tcp_pipes[i] != -1)
|
||||||
|
poll_listen(daemon->tcp_pipes[i], POLLIN);
|
||||||
|
|
||||||
return wait;
|
return wait;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1548,7 +1734,8 @@ static void check_dns_listeners(time_t now)
|
|||||||
struct serverfd *serverfdp;
|
struct serverfd *serverfdp;
|
||||||
struct listener *listener;
|
struct listener *listener;
|
||||||
int i;
|
int i;
|
||||||
|
int pipefd[2];
|
||||||
|
|
||||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||||
if (poll_check(serverfdp->fd, POLLIN))
|
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);
|
||||||
@@ -1558,7 +1745,24 @@ static void check_dns_listeners(time_t now)
|
|||||||
if (daemon->randomsocks[i].refcount != 0 &&
|
if (daemon->randomsocks[i].refcount != 0 &&
|
||||||
poll_check(daemon->randomsocks[i].fd, POLLIN))
|
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);
|
||||||
|
|
||||||
|
/* Races. The child process can die before we read all of the data from the
|
||||||
|
pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
|
||||||
|
process, and tcp_pipes to -1 and close the FD when we read the last
|
||||||
|
of the data - indicated by cache_recv_insert returning zero.
|
||||||
|
The order of these events is indeterminate, and both are needed
|
||||||
|
to free the process slot. Once the child process has gone, poll()
|
||||||
|
returns POLLHUP, not POLLIN, so have to check for both here. */
|
||||||
|
if (!option_bool(OPT_DEBUG))
|
||||||
|
for (i = 0; i < MAX_PROCS; i++)
|
||||||
|
if (daemon->tcp_pipes[i] != -1 &&
|
||||||
|
poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
|
||||||
|
!cache_recv_insert(now, daemon->tcp_pipes[i]))
|
||||||
|
{
|
||||||
|
close(daemon->tcp_pipes[i]);
|
||||||
|
daemon->tcp_pipes[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||||
{
|
{
|
||||||
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||||
@@ -1584,7 +1788,7 @@ static void check_dns_listeners(time_t now)
|
|||||||
|
|
||||||
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
|
if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
|
||||||
{
|
{
|
||||||
while (retry_send(close(confd)));
|
close(confd);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1612,15 +1816,16 @@ static void check_dns_listeners(time_t now)
|
|||||||
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
|
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
|
||||||
indextoname(listener->tcpfd, if_index, intr_name))
|
indextoname(listener->tcpfd, if_index, intr_name))
|
||||||
{
|
{
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
addr.addr.addr4 = tcp_addr.in.sin_addr;
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (tcp_addr.sa.sa_family == AF_INET6)
|
if (tcp_addr.sa.sa_family == AF_INET6)
|
||||||
addr.addr.addr6 = tcp_addr.in6.sin6_addr;
|
addr.addr6 = tcp_addr.in6.sin6_addr;
|
||||||
#endif
|
else
|
||||||
|
addr.addr4 = tcp_addr.in.sin_addr;
|
||||||
|
|
||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (iface->index == if_index)
|
if (iface->index == if_index &&
|
||||||
|
iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
|
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
|
||||||
@@ -1649,27 +1854,48 @@ static void check_dns_listeners(time_t now)
|
|||||||
if (!client_ok)
|
if (!client_ok)
|
||||||
{
|
{
|
||||||
shutdown(confd, SHUT_RDWR);
|
shutdown(confd, SHUT_RDWR);
|
||||||
while (retry_send(close(confd)));
|
close(confd);
|
||||||
}
|
}
|
||||||
#ifndef NO_FORK
|
else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
|
||||||
else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
|
|
||||||
{
|
{
|
||||||
if (p != -1)
|
close(pipefd[1]); /* parent needs read pipe end. */
|
||||||
|
if (p == -1)
|
||||||
|
close(pipefd[0]);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
/* The child process inherits the netlink socket,
|
||||||
|
which it never uses, but when the parent (us)
|
||||||
|
uses it in the future, the answer may go to the
|
||||||
|
child, resulting in the parent blocking
|
||||||
|
forever awaiting the result. To avoid this
|
||||||
|
the child closes the netlink socket, but there's
|
||||||
|
a nasty race, since the parent may use netlink
|
||||||
|
before the child has done the close.
|
||||||
|
|
||||||
|
To avoid this, the parent blocks here until a
|
||||||
|
single byte comes back up the pipe, which
|
||||||
|
is sent by the child after it has closed the
|
||||||
|
netlink socket. */
|
||||||
|
|
||||||
|
unsigned char a;
|
||||||
|
read_write(pipefd[0], &a, 1, 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
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 && daemon->tcp_pipes[i] == -1)
|
||||||
{
|
{
|
||||||
daemon->tcp_pids[i] = p;
|
daemon->tcp_pids[i] = p;
|
||||||
|
daemon->tcp_pipes[i] = pipefd[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (retry_send(close(confd)));
|
close(confd);
|
||||||
|
|
||||||
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
|
/* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
|
||||||
daemon->log_id += TCP_MAX_QUERIES;
|
daemon->log_id += TCP_MAX_QUERIES;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned char *buff;
|
unsigned char *buff;
|
||||||
@@ -1677,7 +1903,7 @@ static void check_dns_listeners(time_t now)
|
|||||||
int flags;
|
int flags;
|
||||||
struct in_addr netmask;
|
struct in_addr netmask;
|
||||||
int auth_dns;
|
int auth_dns;
|
||||||
|
|
||||||
if (iface)
|
if (iface)
|
||||||
{
|
{
|
||||||
netmask = iface->netmask;
|
netmask = iface->netmask;
|
||||||
@@ -1689,12 +1915,21 @@ static void check_dns_listeners(time_t now)
|
|||||||
auth_dns = 0;
|
auth_dns = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_FORK
|
|
||||||
/* Arrange for SIGALRM after CHILD_LIFETIME seconds to
|
/* Arrange for SIGALRM after CHILD_LIFETIME seconds to
|
||||||
terminate the process. */
|
terminate the process. */
|
||||||
if (!option_bool(OPT_DEBUG))
|
if (!option_bool(OPT_DEBUG))
|
||||||
alarm(CHILD_LIFETIME);
|
{
|
||||||
#endif
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
/* See comment above re: netlink socket. */
|
||||||
|
unsigned char a = 0;
|
||||||
|
|
||||||
|
close(daemon->netlinkfd);
|
||||||
|
read_write(pipefd[1], &a, 1, 0);
|
||||||
|
#endif
|
||||||
|
alarm(CHILD_LIFETIME);
|
||||||
|
close(pipefd[0]); /* close read end in child. */
|
||||||
|
daemon->pipe_to_parent = pipefd[1];
|
||||||
|
}
|
||||||
|
|
||||||
/* start with no upstream connections. */
|
/* start with no upstream connections. */
|
||||||
for (s = daemon->servers; s; s = s->next)
|
for (s = daemon->servers; s; s = s->next)
|
||||||
@@ -1709,7 +1944,7 @@ static void check_dns_listeners(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);
|
||||||
while (retry_send(close(confd)));
|
close(confd);
|
||||||
|
|
||||||
if (buff)
|
if (buff)
|
||||||
free(buff);
|
free(buff);
|
||||||
@@ -1718,15 +1953,15 @@ static void check_dns_listeners(time_t now)
|
|||||||
if (s->tcpfd != -1)
|
if (s->tcpfd != -1)
|
||||||
{
|
{
|
||||||
shutdown(s->tcpfd, SHUT_RDWR);
|
shutdown(s->tcpfd, SHUT_RDWR);
|
||||||
while (retry_send(close(s->tcpfd)));
|
close(s->tcpfd);
|
||||||
}
|
}
|
||||||
#ifndef NO_FORK
|
|
||||||
if (!option_bool(OPT_DEBUG))
|
if (!option_bool(OPT_DEBUG))
|
||||||
{
|
{
|
||||||
|
close(daemon->pipe_to_parent);
|
||||||
flush_log();
|
flush_log();
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1796,7 +2031,7 @@ int icmp_ping(struct in_addr addr)
|
|||||||
gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
|
gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
||||||
while (retry_send(close(fd)));
|
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));
|
||||||
@@ -1883,6 +2118,4 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* HAVE_DHCP */
|
||||||
|
|
||||||
|
|
||||||
+224
-131
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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-2017 Simon Kelley"
|
#define COPYRIGHT "Copyright (c) 2000-2020 Simon Kelley"
|
||||||
|
|
||||||
/* We do defines that influence behavior of stdio.h, so complain
|
/* We do defines that influence behavior of stdio.h, so complain
|
||||||
if included too early. */
|
if included too early. */
|
||||||
@@ -42,6 +42,12 @@
|
|||||||
# define __EXTENSIONS__
|
# define __EXTENSIONS__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__)
|
||||||
|
#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
|
||||||
|
#else
|
||||||
|
#define ATTRIBUTE_NORETURN
|
||||||
|
#endif
|
||||||
|
|
||||||
/* get these before config.h for IPv6 stuff... */
|
/* get these before config.h for IPv6 stuff... */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
@@ -57,6 +63,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "ip6addr.h"
|
#include "ip6addr.h"
|
||||||
|
#include "metrics.h"
|
||||||
|
|
||||||
typedef unsigned char u8;
|
typedef unsigned char u8;
|
||||||
typedef unsigned short u16;
|
typedef unsigned short u16;
|
||||||
@@ -88,7 +95,11 @@ 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/poll.h>
|
#if defined(HAVE_POLL_H)
|
||||||
|
# include <poll.h>
|
||||||
|
#else
|
||||||
|
# include <sys/poll.h>
|
||||||
|
#endif
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
@@ -119,7 +130,9 @@ typedef unsigned long long u64;
|
|||||||
#include <net/if_arp.h>
|
#include <net/if_arp.h>
|
||||||
#include <netinet/in_systm.h>
|
#include <netinet/in_systm.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
|
#include <netinet/ip6.h>
|
||||||
#include <netinet/ip_icmp.h>
|
#include <netinet/ip_icmp.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
@@ -128,6 +141,8 @@ typedef unsigned long long u64;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <linux/sockios.h>
|
||||||
#include <linux/capability.h>
|
#include <linux/capability.h>
|
||||||
/* There doesn't seem to be a universally-available
|
/* There doesn't seem to be a universally-available
|
||||||
userspace header for these. */
|
userspace header for these. */
|
||||||
@@ -142,9 +157,15 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
|
|||||||
#include <priv.h>
|
#include <priv.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
# include <nettle/nettle-meta.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* daemon is function in the C library.... */
|
/* daemon is function in the C library.... */
|
||||||
#define daemon dnsmasq_daemon
|
#define daemon dnsmasq_daemon
|
||||||
|
|
||||||
|
#define ADDRSTRLEN INET6_ADDRSTRLEN
|
||||||
|
|
||||||
/* Async event queue */
|
/* Async event queue */
|
||||||
struct event_desc {
|
struct event_desc {
|
||||||
int event, data, msg_sz;
|
int event, data, msg_sz;
|
||||||
@@ -175,6 +196,7 @@ struct event_desc {
|
|||||||
#define EVENT_NEWROUTE 23
|
#define EVENT_NEWROUTE 23
|
||||||
#define EVENT_TIME_ERR 24
|
#define EVENT_TIME_ERR 24
|
||||||
#define EVENT_SCRIPT_LOG 25
|
#define EVENT_SCRIPT_LOG 25
|
||||||
|
#define EVENT_TIME 26
|
||||||
|
|
||||||
/* Exit codes. */
|
/* Exit codes. */
|
||||||
#define EC_GOOD 0
|
#define EC_GOOD 0
|
||||||
@@ -185,9 +207,6 @@ struct event_desc {
|
|||||||
#define EC_MISC 5
|
#define EC_MISC 5
|
||||||
#define EC_INIT_OFFSET 10
|
#define EC_INIT_OFFSET 10
|
||||||
|
|
||||||
/* Trust the compiler dead-code eliminator.... */
|
|
||||||
#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
|
|
||||||
|
|
||||||
#define OPT_BOGUSPRIV 0
|
#define OPT_BOGUSPRIV 0
|
||||||
#define OPT_FILTER 1
|
#define OPT_FILTER 1
|
||||||
#define OPT_LOG 2
|
#define OPT_LOG 2
|
||||||
@@ -236,7 +255,7 @@ struct event_desc {
|
|||||||
#define OPT_DNSSEC_VALID 45
|
#define OPT_DNSSEC_VALID 45
|
||||||
#define OPT_DNSSEC_TIME 46
|
#define OPT_DNSSEC_TIME 46
|
||||||
#define OPT_DNSSEC_DEBUG 47
|
#define OPT_DNSSEC_DEBUG 47
|
||||||
#define OPT_DNSSEC_NO_SIGN 48
|
#define OPT_DNSSEC_IGN_NS 48
|
||||||
#define OPT_LOCAL_SERVICE 49
|
#define OPT_LOCAL_SERVICE 49
|
||||||
#define OPT_LOOP_DETECT 50
|
#define OPT_LOOP_DETECT 50
|
||||||
#define OPT_EXTRALOG 51
|
#define OPT_EXTRALOG 51
|
||||||
@@ -245,7 +264,18 @@ struct event_desc {
|
|||||||
#define OPT_MAC_B64 54
|
#define OPT_MAC_B64 54
|
||||||
#define OPT_MAC_HEX 55
|
#define OPT_MAC_HEX 55
|
||||||
#define OPT_TFTP_APREF_MAC 56
|
#define OPT_TFTP_APREF_MAC 56
|
||||||
#define OPT_LAST 57
|
#define OPT_RAPID_COMMIT 57
|
||||||
|
#define OPT_UBUS 58
|
||||||
|
#define OPT_IGNORE_CLID 59
|
||||||
|
#define OPT_SINGLE_PORT 60
|
||||||
|
#define OPT_LEASE_RENEW 61
|
||||||
|
#define OPT_LAST 62
|
||||||
|
|
||||||
|
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||||
|
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||||
|
#define option_var(x) (daemon->options[(x) / OPTION_BITS])
|
||||||
|
#define option_val(x) ((1u) << ((x) % OPTION_BITS))
|
||||||
|
#define option_bool(x) (option_var(x) & option_val(x))
|
||||||
|
|
||||||
/* 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. */
|
||||||
@@ -253,23 +283,44 @@ struct event_desc {
|
|||||||
#define MS_DHCP LOG_DAEMON
|
#define MS_DHCP LOG_DAEMON
|
||||||
#define MS_SCRIPT LOG_MAIL
|
#define MS_SCRIPT LOG_MAIL
|
||||||
|
|
||||||
struct all_addr {
|
/* Note that this is used widely as a container for IPv4/IPv6 addresses,
|
||||||
union {
|
so for that reason, was well as to avoid wasting memory in almost every
|
||||||
struct in_addr addr4;
|
cache entry, the other variants should not be larger than
|
||||||
#ifdef HAVE_IPV6
|
sizeof(struct in6_addr) - 16 bytes.
|
||||||
struct in6_addr addr6;
|
*/
|
||||||
#endif
|
union all_addr {
|
||||||
/* for log_query */
|
struct in_addr addr4;
|
||||||
struct {
|
struct in6_addr addr6;
|
||||||
unsigned short keytag, algo, digest;
|
struct {
|
||||||
} log;
|
union {
|
||||||
/* for cache_insert of DNSKEY, DS */
|
struct crec *cache;
|
||||||
struct {
|
char *name;
|
||||||
unsigned short class, type;
|
} target;
|
||||||
} dnssec;
|
unsigned int uid;
|
||||||
} addr;
|
int is_name_ptr; /* disciminates target union */
|
||||||
|
} cname;
|
||||||
|
struct {
|
||||||
|
struct blockdata *keydata;
|
||||||
|
unsigned short keylen, flags, keytag;
|
||||||
|
unsigned char algo;
|
||||||
|
} key;
|
||||||
|
struct {
|
||||||
|
struct blockdata *keydata;
|
||||||
|
unsigned short keylen, keytag;
|
||||||
|
unsigned char algo;
|
||||||
|
unsigned char digest;
|
||||||
|
} ds;
|
||||||
|
struct {
|
||||||
|
struct blockdata *target;
|
||||||
|
unsigned short targetlen, srvport, priority, weight;
|
||||||
|
} srv;
|
||||||
|
/* for log_query */
|
||||||
|
struct {
|
||||||
|
unsigned short keytag, algo, digest, rcode;
|
||||||
|
} log;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct bogus_addr {
|
struct bogus_addr {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
struct bogus_addr *next;
|
struct bogus_addr *next;
|
||||||
@@ -329,13 +380,17 @@ struct ds_config {
|
|||||||
struct ds_config *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
|
#define ADDRLIST_REVONLY 4
|
||||||
|
#define ADDRLIST_PREFIX 8
|
||||||
|
#define ADDRLIST_WILDCARD 16
|
||||||
|
#define ADDRLIST_DECLINED 32
|
||||||
|
|
||||||
struct addrlist {
|
struct addrlist {
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
int flags, prefixlen;
|
int flags, prefixlen;
|
||||||
|
time_t decline_time;
|
||||||
struct addrlist *next;
|
struct addrlist *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -354,17 +409,17 @@ struct auth_zone {
|
|||||||
struct auth_zone *next;
|
struct auth_zone *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HR_6 1
|
||||||
|
#define HR_4 2
|
||||||
|
|
||||||
struct host_record {
|
struct host_record {
|
||||||
int ttl;
|
int ttl, flags;
|
||||||
struct name_list {
|
struct name_list {
|
||||||
char *name;
|
char *name;
|
||||||
struct name_list *next;
|
struct name_list *next;
|
||||||
} *names;
|
} *names;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
#endif
|
|
||||||
struct host_record *next;
|
struct host_record *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -388,32 +443,11 @@ struct blockdata {
|
|||||||
|
|
||||||
struct crec {
|
struct crec {
|
||||||
struct crec *next, *prev, *hash_next;
|
struct crec *next, *prev, *hash_next;
|
||||||
/* union is 16 bytes when doing IPv6, 8 bytes on 32 bit machines without IPv6 */
|
union all_addr addr;
|
||||||
union {
|
|
||||||
struct all_addr addr;
|
|
||||||
struct {
|
|
||||||
union {
|
|
||||||
struct crec *cache;
|
|
||||||
struct interface_name *int_name;
|
|
||||||
} target;
|
|
||||||
unsigned int uid; /* 0 if union is interface-name */
|
|
||||||
} cname;
|
|
||||||
struct {
|
|
||||||
struct blockdata *keydata;
|
|
||||||
unsigned short keylen, flags, keytag;
|
|
||||||
unsigned char algo;
|
|
||||||
} key;
|
|
||||||
struct {
|
|
||||||
struct blockdata *keydata;
|
|
||||||
unsigned short keylen, keytag;
|
|
||||||
unsigned char algo;
|
|
||||||
unsigned char digest;
|
|
||||||
} ds;
|
|
||||||
} addr;
|
|
||||||
time_t ttd; /* time to die */
|
time_t ttd; /* time to die */
|
||||||
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
|
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
|
||||||
unsigned int uid;
|
unsigned int uid;
|
||||||
unsigned short flags;
|
unsigned int flags;
|
||||||
union {
|
union {
|
||||||
char sname[SMALLDNAME];
|
char sname[SMALLDNAME];
|
||||||
union bigname *bname;
|
union bigname *bname;
|
||||||
@@ -421,6 +455,9 @@ struct crec {
|
|||||||
} name;
|
} name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define SIZEOF_BARE_CREC (sizeof(struct crec) - SMALLDNAME)
|
||||||
|
#define SIZEOF_POINTER_CREC (sizeof(struct crec) + sizeof(char *) - SMALLDNAME)
|
||||||
|
|
||||||
#define F_IMMORTAL (1u<<0)
|
#define F_IMMORTAL (1u<<0)
|
||||||
#define F_NAMEP (1u<<1)
|
#define F_NAMEP (1u<<1)
|
||||||
#define F_REVERSE (1u<<2)
|
#define F_REVERSE (1u<<2)
|
||||||
@@ -437,9 +474,6 @@ struct crec {
|
|||||||
#define F_CONFIG (1u<<13)
|
#define F_CONFIG (1u<<13)
|
||||||
#define F_DS (1u<<14)
|
#define F_DS (1u<<14)
|
||||||
#define F_DNSSECOK (1u<<15)
|
#define F_DNSSECOK (1u<<15)
|
||||||
|
|
||||||
/* below here are only valid as args to log_query: cache
|
|
||||||
entries are limited to 16 bits */
|
|
||||||
#define F_UPSTREAM (1u<<16)
|
#define F_UPSTREAM (1u<<16)
|
||||||
#define F_RRNAME (1u<<17)
|
#define F_RRNAME (1u<<17)
|
||||||
#define F_SERVER (1u<<18)
|
#define F_SERVER (1u<<18)
|
||||||
@@ -452,9 +486,12 @@ struct crec {
|
|||||||
#define F_NO_RR (1u<<25)
|
#define F_NO_RR (1u<<25)
|
||||||
#define F_IPSET (1u<<26)
|
#define F_IPSET (1u<<26)
|
||||||
#define F_NOEXTRA (1u<<27)
|
#define F_NOEXTRA (1u<<27)
|
||||||
|
#define F_SERVFAIL (1u<<28) /* currently unused. */
|
||||||
|
#define F_RCODE (1u<<29)
|
||||||
|
#define F_SRV (1u<<30)
|
||||||
|
|
||||||
|
#define UID_NONE 0
|
||||||
/* Values of uid in crecs with F_CONFIG bit set. */
|
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||||
#define SRC_INTERFACE 0
|
|
||||||
#define SRC_CONFIG 1
|
#define SRC_CONFIG 1
|
||||||
#define SRC_HOSTS 2
|
#define SRC_HOSTS 2
|
||||||
#define SRC_AH 3
|
#define SRC_AH 3
|
||||||
@@ -466,9 +503,7 @@ struct crec {
|
|||||||
union mysockaddr {
|
union mysockaddr {
|
||||||
struct sockaddr sa;
|
struct sockaddr sa;
|
||||||
struct sockaddr_in in;
|
struct sockaddr_in in;
|
||||||
#if defined(HAVE_IPV6)
|
|
||||||
struct sockaddr_in6 in6;
|
struct sockaddr_in6 in6;
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* bits in flag param to IPv6 callbacks from iface_enumerate() */
|
/* bits in flag param to IPv6 callbacks from iface_enumerate() */
|
||||||
@@ -499,7 +534,7 @@ struct serverfd {
|
|||||||
int fd;
|
int fd;
|
||||||
union mysockaddr source_addr;
|
union mysockaddr source_addr;
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
unsigned int ifindex, used;
|
unsigned int ifindex, used, preallocated;
|
||||||
struct serverfd *next;
|
struct serverfd *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -514,6 +549,7 @@ struct server {
|
|||||||
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, edns_pktsz;
|
int flags, tcpfd, edns_pktsz;
|
||||||
|
time_t pktsz_reduced;
|
||||||
unsigned int queries, failed_queries;
|
unsigned int queries, failed_queries;
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
u32 uid;
|
u32 uid;
|
||||||
@@ -536,7 +572,8 @@ struct irec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct listener {
|
struct listener {
|
||||||
int fd, tcpfd, tftpfd, family;
|
int fd, tcpfd, tftpfd, used;
|
||||||
|
union mysockaddr addr;
|
||||||
struct irec *iface; /* only sometimes valid for non-wildcard */
|
struct irec *iface; /* only sometimes valid for non-wildcard */
|
||||||
struct listener *next;
|
struct listener *next;
|
||||||
};
|
};
|
||||||
@@ -585,6 +622,16 @@ struct hostsfile {
|
|||||||
unsigned int index; /* matches to cache entries for logging */
|
unsigned int index; /* matches to cache entries for logging */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* packet-dump flags */
|
||||||
|
#define DUMP_QUERY 0x0001
|
||||||
|
#define DUMP_REPLY 0x0002
|
||||||
|
#define DUMP_UP_QUERY 0x0004
|
||||||
|
#define DUMP_UP_REPLY 0x0008
|
||||||
|
#define DUMP_SEC_QUERY 0x0010
|
||||||
|
#define DUMP_SEC_REPLY 0x0020
|
||||||
|
#define DUMP_BOGUS 0x0040
|
||||||
|
#define DUMP_SEC_BOGUS 0x0080
|
||||||
|
|
||||||
|
|
||||||
/* DNSSEC status values. */
|
/* DNSSEC status values. */
|
||||||
#define STAT_SECURE 1
|
#define STAT_SECURE 1
|
||||||
@@ -616,12 +663,10 @@ struct hostsfile {
|
|||||||
|
|
||||||
struct frec {
|
struct frec {
|
||||||
union mysockaddr source;
|
union mysockaddr source;
|
||||||
struct all_addr dest;
|
union all_addr dest;
|
||||||
struct server *sentto; /* NULL means free */
|
struct server *sentto; /* NULL means free */
|
||||||
struct randfd *rfd4;
|
struct randfd *rfd4;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct randfd *rfd6;
|
struct randfd *rfd6;
|
||||||
#endif
|
|
||||||
unsigned int iface;
|
unsigned int iface;
|
||||||
unsigned short orig_id, new_id;
|
unsigned short orig_id, new_id;
|
||||||
int log_id, fd, forwardall, flags;
|
int log_id, fd, forwardall, flags;
|
||||||
@@ -663,6 +708,7 @@ struct frec {
|
|||||||
#define LEASE_NA 32 /* IPv6 no-temporary lease */
|
#define LEASE_NA 32 /* IPv6 no-temporary lease */
|
||||||
#define LEASE_TA 64 /* IPv6 temporary lease */
|
#define LEASE_TA 64 /* IPv6 temporary lease */
|
||||||
#define LEASE_HAVE_HWADDR 128 /* Have set hwaddress */
|
#define LEASE_HAVE_HWADDR 128 /* Have set hwaddress */
|
||||||
|
#define LEASE_EXP_CHANGED 256 /* Lease expiry time changed */
|
||||||
|
|
||||||
struct dhcp_lease {
|
struct dhcp_lease {
|
||||||
int clid_len; /* length of client identifier */
|
int clid_len; /* length of client identifier */
|
||||||
@@ -684,7 +730,7 @@ struct dhcp_lease {
|
|||||||
int new_prefixlen; /* and its prefix length */
|
int new_prefixlen; /* and its prefix length */
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
int iaid;
|
unsigned int iaid;
|
||||||
struct slaac_address {
|
struct slaac_address {
|
||||||
struct in6_addr addr;
|
struct in6_addr addr;
|
||||||
time_t ping_time;
|
time_t ping_time;
|
||||||
@@ -731,8 +777,9 @@ struct dhcp_config {
|
|||||||
unsigned char *clid; /* clientid */
|
unsigned char *clid; /* clientid */
|
||||||
char *hostname, *domain;
|
char *hostname, *domain;
|
||||||
struct dhcp_netid_list *netid;
|
struct dhcp_netid_list *netid;
|
||||||
|
struct dhcp_netid *filter;
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
struct in6_addr addr6;
|
struct addrlist *addr6;
|
||||||
#endif
|
#endif
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
time_t decline_time;
|
time_t decline_time;
|
||||||
@@ -754,7 +801,7 @@ struct dhcp_config {
|
|||||||
#define CONFIG_DECLINED 1024 /* address declined by client */
|
#define CONFIG_DECLINED 1024 /* address declined by client */
|
||||||
#define CONFIG_BANK 2048 /* from dhcp hosts file */
|
#define CONFIG_BANK 2048 /* from dhcp hosts file */
|
||||||
#define CONFIG_ADDR6 4096
|
#define CONFIG_ADDR6 4096
|
||||||
#define CONFIG_WILDCARD 8192
|
#define CONFIG_ADDR6_HOSTS 16384 /* address added by from /etc/hosts */
|
||||||
|
|
||||||
struct dhcp_opt {
|
struct dhcp_opt {
|
||||||
int opt, len, flags;
|
int opt, len, flags;
|
||||||
@@ -790,6 +837,13 @@ struct dhcp_boot {
|
|||||||
struct dhcp_boot *next;
|
struct dhcp_boot *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcp_match_name {
|
||||||
|
char *name;
|
||||||
|
int wildcard;
|
||||||
|
struct dhcp_netid *netid;
|
||||||
|
struct dhcp_match_name *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct pxe_service {
|
struct pxe_service {
|
||||||
unsigned short CSA, type;
|
unsigned short CSA, type;
|
||||||
char *menu, *basename, *sname;
|
char *menu, *basename, *sname;
|
||||||
@@ -829,21 +883,11 @@ struct dhcp_bridge {
|
|||||||
struct cond_domain {
|
struct cond_domain {
|
||||||
char *domain, *prefix;
|
char *domain, *prefix;
|
||||||
struct in_addr start, end;
|
struct in_addr start, end;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct in6_addr start6, end6;
|
struct in6_addr start6, end6;
|
||||||
#endif
|
int is6, indexed;
|
||||||
int is6;
|
|
||||||
struct cond_domain *next;
|
struct cond_domain *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
struct prefix_class {
|
|
||||||
int class;
|
|
||||||
struct dhcp_netid tag;
|
|
||||||
struct prefix_class *next;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ra_interface {
|
struct ra_interface {
|
||||||
char *name;
|
char *name;
|
||||||
char *mtu_name;
|
char *mtu_name;
|
||||||
@@ -869,6 +913,16 @@ struct dhcp_context {
|
|||||||
struct dhcp_context *next, *current;
|
struct dhcp_context *next, *current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct shared_network {
|
||||||
|
int if_index;
|
||||||
|
struct in_addr match_addr, shared_addr;
|
||||||
|
#ifdef HAVE_DHCP6
|
||||||
|
/* shared_addr == 0 for IP6 entries. */
|
||||||
|
struct in6_addr match_addr6, shared_addr6;
|
||||||
|
#endif
|
||||||
|
struct shared_network *next;
|
||||||
|
};
|
||||||
|
|
||||||
#define CONTEXT_STATIC (1u<<0)
|
#define CONTEXT_STATIC (1u<<0)
|
||||||
#define CONTEXT_NETMASK (1u<<1)
|
#define CONTEXT_NETMASK (1u<<1)
|
||||||
#define CONTEXT_BRDCAST (1u<<2)
|
#define CONTEXT_BRDCAST (1u<<2)
|
||||||
@@ -888,6 +942,7 @@ struct dhcp_context {
|
|||||||
#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)
|
#define CONTEXT_RA_OFF_LINK (1u<<18)
|
||||||
|
#define CONTEXT_SETLEASE (1u<<19)
|
||||||
|
|
||||||
struct ping_result {
|
struct ping_result {
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
@@ -911,6 +966,8 @@ struct tftp_transfer {
|
|||||||
unsigned int block, blocksize, expansion;
|
unsigned int block, blocksize, expansion;
|
||||||
off_t offset;
|
off_t offset;
|
||||||
union mysockaddr peer;
|
union mysockaddr peer;
|
||||||
|
union all_addr source;
|
||||||
|
int if_index;
|
||||||
char opt_blocksize, opt_transize, netascii, carrylf;
|
char opt_blocksize, opt_transize, netascii, carrylf;
|
||||||
struct tftp_file *file;
|
struct tftp_file *file;
|
||||||
struct tftp_transfer *next;
|
struct tftp_transfer *next;
|
||||||
@@ -929,7 +986,7 @@ struct tftp_prefix {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct dhcp_relay {
|
struct dhcp_relay {
|
||||||
struct all_addr local, server;
|
union all_addr local, server;
|
||||||
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
|
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
|
||||||
int iface_index; /* working - interface in which requests arrived, for return */
|
int iface_index; /* working - interface in which requests arrived, for return */
|
||||||
struct dhcp_relay *current, *next;
|
struct dhcp_relay *current, *next;
|
||||||
@@ -940,7 +997,7 @@ extern struct daemon {
|
|||||||
config file arguments. All set (including defaults)
|
config file arguments. All set (including defaults)
|
||||||
in option.c */
|
in option.c */
|
||||||
|
|
||||||
unsigned int options, options2;
|
unsigned int options[OPTION_SIZE];
|
||||||
struct resolvc default_resolv, *resolv_files;
|
struct resolvc default_resolv, *resolv_files;
|
||||||
time_t last_resolv;
|
time_t last_resolv;
|
||||||
char *servers_file;
|
char *servers_file;
|
||||||
@@ -982,6 +1039,7 @@ extern struct daemon {
|
|||||||
struct ra_interface *ra_interfaces;
|
struct ra_interface *ra_interfaces;
|
||||||
struct dhcp_config *dhcp_conf;
|
struct dhcp_config *dhcp_conf;
|
||||||
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
||||||
|
struct dhcp_match_name *dhcp_name_match;
|
||||||
struct dhcp_vendor *dhcp_vendors;
|
struct dhcp_vendor *dhcp_vendors;
|
||||||
struct dhcp_mac *dhcp_macs;
|
struct dhcp_mac *dhcp_macs;
|
||||||
struct dhcp_boot *boot_config;
|
struct dhcp_boot *boot_config;
|
||||||
@@ -1007,14 +1065,13 @@ extern struct daemon {
|
|||||||
unsigned int duid_enterprise, duid_config_len;
|
unsigned int duid_enterprise, duid_config_len;
|
||||||
unsigned char *duid_config;
|
unsigned char *duid_config;
|
||||||
char *dbus_name;
|
char *dbus_name;
|
||||||
|
char *ubus_name;
|
||||||
|
char *dump_file;
|
||||||
|
int dump_mask;
|
||||||
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
u32 metrics[__METRIC_MAX];
|
||||||
struct prefix_class *prefix_classes;
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
struct ds_config *ds;
|
struct ds_config *ds;
|
||||||
int dnssec_no_time_check;
|
|
||||||
int back_to_the_future;
|
|
||||||
char *timestamp_file;
|
char *timestamp_file;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1025,8 +1082,11 @@ extern struct daemon {
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
char *keyname; /* MAXDNAME size buffer */
|
char *keyname; /* MAXDNAME size buffer */
|
||||||
char *workspacename; /* ditto */
|
char *workspacename; /* ditto */
|
||||||
|
unsigned long *rr_status; /* ceiling in TTL from DNSSEC or zero for insecure */
|
||||||
|
int rr_status_sz;
|
||||||
|
int dnssec_no_time_check;
|
||||||
|
int back_to_the_future;
|
||||||
#endif
|
#endif
|
||||||
unsigned int local_answer, queries_forwarded, auth_answer;
|
|
||||||
struct frec *frec_list;
|
struct frec *frec_list;
|
||||||
struct serverfd *sfds;
|
struct serverfd *sfds;
|
||||||
struct irec *interfaces;
|
struct irec *interfaces;
|
||||||
@@ -1038,6 +1098,8 @@ extern struct daemon {
|
|||||||
size_t packet_len; /* " " */
|
size_t packet_len; /* " " */
|
||||||
struct randfd *rfd_save; /* " " */
|
struct randfd *rfd_save; /* " " */
|
||||||
pid_t tcp_pids[MAX_PROCS];
|
pid_t tcp_pids[MAX_PROCS];
|
||||||
|
int tcp_pipes[MAX_PROCS];
|
||||||
|
int pipe_to_parent;
|
||||||
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 */
|
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
|
||||||
@@ -1050,7 +1112,7 @@ extern struct daemon {
|
|||||||
int inotifyfd;
|
int inotifyfd;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
int netlinkfd;
|
int netlinkfd, kernel_version;
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
|
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
|
||||||
#endif
|
#endif
|
||||||
@@ -1059,6 +1121,7 @@ extern struct daemon {
|
|||||||
struct ping_result *ping_results;
|
struct ping_result *ping_results;
|
||||||
FILE *lease_stream;
|
FILE *lease_stream;
|
||||||
struct dhcp_bridge *bridges;
|
struct dhcp_bridge *bridges;
|
||||||
|
struct shared_network *shared_networks;
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
int duid_len;
|
int duid_len;
|
||||||
unsigned char *duid;
|
unsigned char *duid;
|
||||||
@@ -1071,6 +1134,11 @@ extern struct daemon {
|
|||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
struct watch *watches;
|
struct watch *watches;
|
||||||
#endif
|
#endif
|
||||||
|
/* UBus stuff */
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
/* void * here to avoid depending on ubus headers outside ubus.c */
|
||||||
|
void *ubus;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* TFTP stuff */
|
/* TFTP stuff */
|
||||||
struct tftp_transfer *tftp_trans, *tftp_done_trans;
|
struct tftp_transfer *tftp_trans, *tftp_done_trans;
|
||||||
@@ -1079,24 +1147,31 @@ extern struct daemon {
|
|||||||
char *addrbuff;
|
char *addrbuff;
|
||||||
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
|
char *addrbuff2; /* only allocated when OPT_EXTRALOG */
|
||||||
|
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
/* file for packet dumps. */
|
||||||
|
int dumpfd;
|
||||||
|
#endif
|
||||||
} *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 next_uid(struct crec *crecp);
|
||||||
|
void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg);
|
||||||
char *record_source(unsigned int index);
|
char *record_source(unsigned int index);
|
||||||
char *querystr(char *desc, unsigned short type);
|
char *querystr(char *desc, unsigned short type);
|
||||||
|
int cache_find_non_terminal(char *name, time_t now);
|
||||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||||
struct all_addr *addr, time_t now,
|
union all_addr *addr, time_t now,
|
||||||
unsigned int 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 int 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,
|
int cache_recv_insert(time_t now, int fd);
|
||||||
time_t now, unsigned long ttl, unsigned short flags);
|
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
||||||
|
time_t now, unsigned long ttl, unsigned int flags);
|
||||||
void cache_reload(void);
|
void cache_reload(void);
|
||||||
void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_address, time_t ttd);
|
void cache_add_dhcp_entry(char *host_name, int prot, union all_addr *host_address, time_t ttd);
|
||||||
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);
|
||||||
@@ -1110,21 +1185,19 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size,
|
|||||||
struct crec **rhash, int hashsz);
|
struct crec **rhash, int hashsz);
|
||||||
|
|
||||||
/* blockdata.c */
|
/* blockdata.c */
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
void blockdata_init(void);
|
void blockdata_init(void);
|
||||||
void blockdata_report(void);
|
void blockdata_report(void);
|
||||||
struct blockdata *blockdata_alloc(char *data, size_t len);
|
struct blockdata *blockdata_alloc(char *data, size_t len);
|
||||||
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);
|
void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);
|
||||||
|
struct blockdata *blockdata_read(int fd, size_t len);
|
||||||
|
void blockdata_write(struct blockdata *block, size_t len, int fd);
|
||||||
void blockdata_free(struct blockdata *blocks);
|
void blockdata_free(struct blockdata *blocks);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* domain.c */
|
/* domain.c */
|
||||||
char *get_domain(struct in_addr addr);
|
char *get_domain(struct in_addr addr);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
char *get_domain6(struct in6_addr *addr);
|
char *get_domain6(struct in6_addr *addr);
|
||||||
#endif
|
int is_name_synthetic(int flags, char *name, union all_addr *addr);
|
||||||
int is_name_synthetic(int flags, char *name, struct all_addr *addr);
|
int is_rev_synth(int flag, union all_addr *addr, char *name);
|
||||||
int is_rev_synth(int flag, struct all_addr *addr, char *name);
|
|
||||||
|
|
||||||
/* rfc1035.c */
|
/* rfc1035.c */
|
||||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
||||||
@@ -1135,7 +1208,7 @@ unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *h
|
|||||||
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,
|
||||||
struct all_addr *addrp, unsigned int flags,
|
union all_addr *addrp, unsigned int flags,
|
||||||
unsigned long ttl);
|
unsigned long ttl);
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||||
time_t now, char **ipsets, int is_sign, int check_rebind,
|
time_t now, char **ipsets, int is_sign, int check_rebind,
|
||||||
@@ -1153,10 +1226,7 @@ size_t resize_packet(struct dns_header *header, size_t plen,
|
|||||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||||
int nameoffset, unsigned char **pp, unsigned long ttl,
|
int nameoffset, unsigned char **pp, unsigned long ttl,
|
||||||
int *offset, unsigned short type, unsigned short class, char *format, ...);
|
int *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||||
unsigned char *skip_questions(struct dns_header *header, size_t plen);
|
int in_arpa_name_2_addr(char *namein, union all_addr *addrp);
|
||||||
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
|
|
||||||
char *name, int isExtract, int extrabytes);
|
|
||||||
int in_arpa_name_2_addr(char *namein, struct all_addr *addrp);
|
|
||||||
int private_net(struct in_addr addr, int ban_localhost);
|
int private_net(struct in_addr addr, int ban_localhost);
|
||||||
|
|
||||||
/* auth.c */
|
/* auth.c */
|
||||||
@@ -1168,16 +1238,25 @@ 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, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, int edns_pktsz);
|
||||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
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 check_unsigned, int *neganswer, int *nons);
|
int check_unsigned, int *neganswer, int *nons, int *nsec_ttl);
|
||||||
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||||
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
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);
|
int setup_timestamp(void);
|
||||||
|
|
||||||
|
/* crypto.c */
|
||||||
|
const struct nettle_hash *hash_find(char *name);
|
||||||
|
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
|
||||||
|
int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
|
||||||
|
unsigned char *digest, size_t digest_len, int algo);
|
||||||
|
char *ds_digest_name(int digest);
|
||||||
|
char *algo_digest_name(int algo);
|
||||||
|
char *nsec3_digest_name(int digest);
|
||||||
|
|
||||||
/* util.c */
|
/* util.c */
|
||||||
void rand_init(void);
|
void rand_init(void);
|
||||||
unsigned short rand16(void);
|
unsigned short rand16(void);
|
||||||
@@ -1187,19 +1266,19 @@ int legal_hostname(char *name);
|
|||||||
char *canonicalise(char *in, int *nomem);
|
char *canonicalise(char *in, int *nomem);
|
||||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||||
void *safe_malloc(size_t size);
|
void *safe_malloc(size_t size);
|
||||||
|
void safe_strncpy(char *dest, const char *src, size_t size);
|
||||||
void safe_pipe(int *fd, int read_noblock);
|
void safe_pipe(int *fd, int read_noblock);
|
||||||
void *whine_malloc(size_t size);
|
void *whine_malloc(size_t size);
|
||||||
int sa_len(union mysockaddr *addr);
|
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);
|
||||||
|
int hostname_issubdomain(char *a, char *b);
|
||||||
time_t dnsmasq_time(void);
|
time_t dnsmasq_time(void);
|
||||||
int netmask_length(struct in_addr mask);
|
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
|
|
||||||
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
|
|
||||||
int retry_send(ssize_t rc);
|
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);
|
||||||
@@ -1210,12 +1289,15 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
|
|||||||
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);
|
||||||
int read_write(int fd, unsigned char *packet, int size, int rw);
|
int read_write(int fd, unsigned char *packet, int size, int rw);
|
||||||
|
void close_fds(long max_fd, int spare1, int spare2, int spare3);
|
||||||
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);
|
int wildcard_matchn(const char* wildcard, const char* match, int num);
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
int kernel_version(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* log.c */
|
/* log.c */
|
||||||
void die(char *message, char *arg1, int exit_code);
|
void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN;
|
||||||
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);
|
||||||
|
|
||||||
@@ -1244,9 +1326,9 @@ void receive_query(struct listener *listen, time_t now);
|
|||||||
unsigned char *tcp_request(int confd, time_t now,
|
unsigned char *tcp_request(int confd, time_t now,
|
||||||
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
|
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
|
||||||
void server_gone(struct server *server);
|
void server_gone(struct server *server);
|
||||||
struct frec *get_new_frec(time_t now, int *wait, int force);
|
struct frec *get_new_frec(time_t now, int *wait, struct frec *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, union all_addr *source,
|
||||||
unsigned int iface);
|
unsigned int iface);
|
||||||
void resend_query(void);
|
void resend_query(void);
|
||||||
struct randfd *allocate_rfd(int family);
|
struct randfd *allocate_rfd(int family);
|
||||||
@@ -1254,7 +1336,7 @@ 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);
|
||||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp);
|
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, 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);
|
||||||
@@ -1273,14 +1355,12 @@ void warn_bound_listeners(void);
|
|||||||
void warn_wild_labels(void);
|
void warn_wild_labels(void);
|
||||||
void warn_int_names(void);
|
void warn_int_names(void);
|
||||||
int is_dad_listeners(void);
|
int is_dad_listeners(void);
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth);
|
int iface_check(int family, union all_addr *addr, char *name, int *auth);
|
||||||
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
int loopback_exception(int fd, int family, union all_addr *addr, char *name);
|
||||||
int label_exception(int index, int family, struct all_addr *addr);
|
int label_exception(int index, int family, union all_addr *addr);
|
||||||
int fix_fd(int fd);
|
int fix_fd(int fd);
|
||||||
int tcp_interface(int fd, int af);
|
int tcp_interface(int fd, int af);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
int set_ipv6pktinfo(int fd);
|
int set_ipv6pktinfo(int fd);
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void join_multicast(int dienow);
|
void join_multicast(int dienow);
|
||||||
#endif
|
#endif
|
||||||
@@ -1318,14 +1398,15 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr);
|
|||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type);
|
||||||
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
||||||
int lease_type, int iaid, struct in6_addr *addr);
|
int lease_type, unsigned int iaid, struct in6_addr *addr);
|
||||||
void lease6_reset(void);
|
void lease6_reset(void);
|
||||||
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid);
|
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type,
|
||||||
|
unsigned char *clid, int clid_len, unsigned int iaid);
|
||||||
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
struct dhcp_lease *lease6_find_by_addr(struct in6_addr *net, int prefix, u64 addr);
|
||||||
u64 lease_find_max_addr6(struct dhcp_context *context);
|
u64 lease_find_max_addr6(struct dhcp_context *context);
|
||||||
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
|
void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *interface);
|
||||||
void lease_update_slaac(time_t now);
|
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, unsigned 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, const unsigned char *hwaddr,
|
void lease_set_hwaddr(struct dhcp_lease *lease, const unsigned char *hwaddr,
|
||||||
@@ -1371,7 +1452,7 @@ void clear_cache_and_reload(time_t now);
|
|||||||
|
|
||||||
/* netlink.c */
|
/* netlink.c */
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
void netlink_init(void);
|
char *netlink_init(void);
|
||||||
void netlink_multicast(void);
|
void netlink_multicast(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1397,10 +1478,18 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ubus.c */
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
void ubus_init(void);
|
||||||
|
void set_ubus_listeners(void);
|
||||||
|
void check_ubus_listeners(void);
|
||||||
|
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ipset.c */
|
/* ipset.c */
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
void ipset_init(void);
|
void ipset_init(void);
|
||||||
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove);
|
int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* helper.c */
|
/* helper.c */
|
||||||
@@ -1413,7 +1502,7 @@ void queue_script(int action, struct dhcp_lease *lease,
|
|||||||
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
||||||
#endif
|
#endif
|
||||||
void queue_arp(int action, unsigned char *mac, int maclen,
|
void queue_arp(int action, unsigned char *mac, int maclen,
|
||||||
int family, struct all_addr *addr);
|
int family, union all_addr *addr);
|
||||||
int helper_buf_empty(void);
|
int helper_buf_empty(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1426,7 +1515,7 @@ int do_tftp_script_run(void);
|
|||||||
|
|
||||||
/* conntrack.c */
|
/* conntrack.c */
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
|
int get_incoming_mark(union mysockaddr *peer_addr, union all_addr *local_addr,
|
||||||
int istcp, unsigned int *markp);
|
int istcp, unsigned int *markp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1435,8 +1524,7 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
|
|||||||
void dhcp6_init(void);
|
void dhcp6_init(void);
|
||||||
void dhcp6_packet(time_t now);
|
void dhcp6_packet(time_t now);
|
||||||
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned char *clid, int clid_len, int temp_addr,
|
||||||
int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
|
unsigned int iaid, int serial, struct dhcp_netid *netids, int plain_range, struct in6_addr *ans);
|
||||||
int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
|
|
||||||
struct dhcp_context *address6_available(struct dhcp_context *context,
|
struct dhcp_context *address6_available(struct dhcp_context *context,
|
||||||
struct in6_addr *taddr,
|
struct in6_addr *taddr,
|
||||||
struct dhcp_netid *netids,
|
struct dhcp_netid *netids,
|
||||||
@@ -1446,7 +1534,7 @@ struct dhcp_context *address6_valid(struct dhcp_context *context,
|
|||||||
struct dhcp_netid *netids,
|
struct dhcp_netid *netids,
|
||||||
int plain_range);
|
int plain_range);
|
||||||
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct in6_addr *net,
|
||||||
int prefix, u64 addr);
|
int prefix, struct in6_addr *addr);
|
||||||
void make_duid(time_t now);
|
void make_duid(time_t now);
|
||||||
void dhcp_construct_contexts(time_t now);
|
void dhcp_construct_contexts(time_t now);
|
||||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||||
@@ -1479,13 +1567,12 @@ void dhcp_update_configs(struct dhcp_config *configs);
|
|||||||
void display_opts(void);
|
void display_opts(void);
|
||||||
int lookup_dhcp_opt(int prot, char *name);
|
int lookup_dhcp_opt(int prot, char *name);
|
||||||
int lookup_dhcp_len(int prot, int val);
|
int lookup_dhcp_len(int prot, int val);
|
||||||
char *option_string(int prot, unsigned int opt, unsigned char *val,
|
|
||||||
int opt_len, char *buf, int buf_len);
|
|
||||||
struct dhcp_config *find_config(struct dhcp_config *configs,
|
struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||||
struct dhcp_context *context,
|
struct dhcp_context *context,
|
||||||
unsigned char *clid, int clid_len,
|
unsigned char *clid, int clid_len,
|
||||||
unsigned char *hwaddr, int hw_len,
|
unsigned char *hwaddr, int hw_len,
|
||||||
int hw_type, char *hostname);
|
int hw_type, char *hostname,
|
||||||
|
struct dhcp_netid *filter);
|
||||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
char *whichdevice(void);
|
char *whichdevice(void);
|
||||||
@@ -1564,3 +1651,9 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
|
|||||||
/* arp.c */
|
/* arp.c */
|
||||||
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
|
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
|
||||||
int do_arp_script_run(void);
|
int do_arp_script_run(void);
|
||||||
|
|
||||||
|
/* dump.c */
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
void dump_init(void);
|
||||||
|
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst);
|
||||||
|
#endif
|
||||||
+523
-679
File diff suppressed because it is too large.
Load diff
+142
-95
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -18,21 +18,14 @@
|
|||||||
|
|
||||||
|
|
||||||
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
|
static struct cond_domain *search_domain(struct in_addr addr, struct cond_domain *c);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c);
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
int is_name_synthetic(int flags, char *name, union all_addr *addr)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
struct cond_domain *c = NULL;
|
struct cond_domain *c = NULL;
|
||||||
int prot = AF_INET;
|
int prot = (flags & F_IPV6) ? AF_INET6 : AF_INET;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (flags & F_IPV6)
|
|
||||||
prot = AF_INET6;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (c = daemon->synth_domains; c; c = c->next)
|
for (c = daemon->synth_domains; c; c = c->next)
|
||||||
{
|
{
|
||||||
@@ -55,83 +48,123 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
|||||||
|
|
||||||
if (pref && *pref != 0)
|
if (pref && *pref != 0)
|
||||||
continue; /* prefix match fail */
|
continue; /* prefix match fail */
|
||||||
|
|
||||||
/* NB, must not alter name if we return zero */
|
if (c->indexed)
|
||||||
for (p = tail; *p; p++)
|
|
||||||
{
|
{
|
||||||
char c = *p;
|
for (p = tail; *p; p++)
|
||||||
|
{
|
||||||
|
char c = *p;
|
||||||
|
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((c >='0' && c <= '9') || c == '-')
|
if (*p != '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
*p = 0;
|
||||||
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
break;
|
if (hostname_isequal(c->domain, p+1))
|
||||||
}
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
if (*p != '.')
|
{
|
||||||
continue;
|
unsigned int index = atoi(tail);
|
||||||
|
|
||||||
*p = 0;
|
if (!c->is6 &&
|
||||||
|
index <= ntohl(c->end.s_addr) - ntohl(c->start.s_addr))
|
||||||
#ifdef HAVE_IPV6
|
{
|
||||||
if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
|
addr->addr4.s_addr = htonl(ntohl(c->start.s_addr) + index);
|
||||||
{
|
found = 1;
|
||||||
/* special hack for v4-mapped. */
|
}
|
||||||
memcpy(tail, "::ffff:", 7);
|
}
|
||||||
for (p = tail + 7; *p; p++)
|
else
|
||||||
if (*p == '-')
|
{
|
||||||
*p = '.';
|
u64 index = atoll(tail);
|
||||||
|
|
||||||
|
if (c->is6 &&
|
||||||
|
index <= addr6part(&c->end6) - addr6part(&c->start6))
|
||||||
|
{
|
||||||
|
u64 start = addr6part(&c->start6);
|
||||||
|
addr->addr6 = c->start6;
|
||||||
|
setaddr6part(&addr->addr6, start + index);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
/* swap . or : for - */
|
/* NB, must not alter name if we return zero */
|
||||||
for (p = tail; *p; p++)
|
for (p = tail; *p; p++)
|
||||||
if (*p == '-')
|
|
||||||
{
|
|
||||||
if (prot == AF_INET)
|
|
||||||
*p = '.';
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
|
||||||
*p = ':';
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
|
||||||
{
|
|
||||||
if (prot == AF_INET)
|
|
||||||
{
|
{
|
||||||
if (!c->is6 &&
|
char c = *p;
|
||||||
ntohl(addr->addr.addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
|
||||||
ntohl(addr->addr.addr4.s_addr) <= ntohl(c->end.s_addr))
|
if ((c >='0' && c <= '9') || c == '-')
|
||||||
found = 1;
|
continue;
|
||||||
|
|
||||||
|
if (prot == AF_INET6 && ((c >='A' && c <= 'F') || (c >='a' && c <= 'f')))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p != '.')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*p = 0;
|
||||||
|
|
||||||
|
if (prot == AF_INET6 && strstr(tail, "--ffff-") == tail)
|
||||||
|
{
|
||||||
|
/* special hack for v4-mapped. */
|
||||||
|
memcpy(tail, "::ffff:", 7);
|
||||||
|
for (p = tail + 7; *p; p++)
|
||||||
|
if (*p == '-')
|
||||||
|
*p = '.';
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u64 addrpart = addr6part(&addr->addr.addr6);
|
/* swap . or : for - */
|
||||||
|
for (p = tail; *p; p++)
|
||||||
if (c->is6 &&
|
if (*p == '-')
|
||||||
is_same_net6(&addr->addr.addr6, &c->start6, 64) &&
|
{
|
||||||
addrpart >= addr6part(&c->start6) &&
|
if (prot == AF_INET)
|
||||||
addrpart <= addr6part(&c->end6))
|
*p = '.';
|
||||||
found = 1;
|
else
|
||||||
|
*p = ':';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
||||||
|
{
|
||||||
|
if (prot == AF_INET)
|
||||||
|
{
|
||||||
|
if (!c->is6 &&
|
||||||
|
ntohl(addr->addr4.s_addr) >= ntohl(c->start.s_addr) &&
|
||||||
|
ntohl(addr->addr4.s_addr) <= ntohl(c->end.s_addr))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u64 addrpart = addr6part(&addr->addr6);
|
||||||
|
|
||||||
|
if (c->is6 &&
|
||||||
|
is_same_net6(&addr->addr6, &c->start6, 64) &&
|
||||||
|
addrpart >= addr6part(&c->start6) &&
|
||||||
|
addrpart <= addr6part(&c->end6))
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* restore name */
|
/* restore name */
|
||||||
for (p = tail; *p; p++)
|
for (p = tail; *p; p++)
|
||||||
if (*p == '.' || *p == ':')
|
if (*p == '.' || *p == ':')
|
||||||
*p = '-';
|
*p = '-';
|
||||||
|
|
||||||
*p = '.';
|
*p = '.';
|
||||||
|
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -140,59 +173,74 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int is_rev_synth(int flag, struct all_addr *addr, char *name)
|
int is_rev_synth(int flag, union all_addr *addr, char *name)
|
||||||
{
|
{
|
||||||
struct cond_domain *c;
|
struct cond_domain *c;
|
||||||
|
|
||||||
if (flag & F_IPV4 && (c = search_domain(addr->addr.addr4, daemon->synth_domains)))
|
if (flag & F_IPV4 && (c = search_domain(addr->addr4, daemon->synth_domains)))
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*name = 0;
|
*name = 0;
|
||||||
if (c->prefix)
|
if (c->indexed)
|
||||||
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
{
|
||||||
|
unsigned int index = ntohl(addr->addr4.s_addr) - ntohl(c->start.s_addr);
|
||||||
|
snprintf(name, MAXDNAME, "%s%u", c->prefix ? c->prefix : "", index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET, &addr->addr4, name + strlen(name), ADDRSTRLEN);
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == '.')
|
||||||
|
*p = '-';
|
||||||
|
}
|
||||||
|
|
||||||
inet_ntop(AF_INET, &addr->addr.addr4, name + strlen(name), ADDRSTRLEN);
|
|
||||||
for (p = name; *p; p++)
|
|
||||||
if (*p == '.')
|
|
||||||
*p = '-';
|
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
if ((flag & F_IPV6) && (c = search_domain6(&addr->addr6, daemon->synth_domains)))
|
||||||
if (flag & F_IPV6 && (c = search_domain6(&addr->addr.addr6, daemon->synth_domains)))
|
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
*name = 0;
|
*name = 0;
|
||||||
if (c->prefix)
|
if (c->indexed)
|
||||||
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
|
||||||
|
|
||||||
inet_ntop(AF_INET6, &addr->addr.addr6, name + strlen(name), ADDRSTRLEN);
|
|
||||||
|
|
||||||
/* IPv6 presentation address can start with ":", but valid domain names
|
|
||||||
cannot start with "-" so prepend a zero in that case. */
|
|
||||||
if (!c->prefix && *name == ':')
|
|
||||||
{
|
{
|
||||||
*name = '0';
|
u64 index = addr6part(&addr->addr6) - addr6part(&c->start6);
|
||||||
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
|
snprintf(name, MAXDNAME, "%s%llu", c->prefix ? c->prefix : "", index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (c->prefix)
|
||||||
|
strncpy(name, c->prefix, MAXDNAME - ADDRSTRLEN);
|
||||||
|
|
||||||
|
inet_ntop(AF_INET6, &addr->addr6, name + strlen(name), ADDRSTRLEN);
|
||||||
|
|
||||||
|
/* IPv6 presentation address can start with ":", but valid domain names
|
||||||
|
cannot start with "-" so prepend a zero in that case. */
|
||||||
|
if (!c->prefix && *name == ':')
|
||||||
|
{
|
||||||
|
*name = '0';
|
||||||
|
inet_ntop(AF_INET6, &addr->addr6, name+1, ADDRSTRLEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* V4-mapped have periods.... */
|
||||||
|
for (p = name; *p; p++)
|
||||||
|
if (*p == ':' || *p == '.')
|
||||||
|
*p = '-';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* V4-mapped have periods.... */
|
|
||||||
for (p = name; *p; p++)
|
|
||||||
if (*p == ':' || *p == '.')
|
|
||||||
*p = '-';
|
|
||||||
|
|
||||||
strncat(name, ".", MAXDNAME);
|
strncat(name, ".", MAXDNAME);
|
||||||
strncat(name, c->domain, MAXDNAME);
|
strncat(name, c->domain, MAXDNAME);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -219,7 +267,7 @@ char *get_domain(struct in_addr addr)
|
|||||||
return daemon->domain_suffix;
|
return daemon->domain_suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
|
static struct cond_domain *search_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||||
{
|
{
|
||||||
u64 addrpart = addr6part(addr);
|
u64 addrpart = addr6part(addr);
|
||||||
@@ -243,4 +291,3 @@ char *get_domain6(struct in6_addr *addr)
|
|||||||
|
|
||||||
return daemon->domain_suffix;
|
return daemon->domain_suffix;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
+211
@@ -0,0 +1,211 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DUMPFILE
|
||||||
|
|
||||||
|
static u32 packet_count;
|
||||||
|
|
||||||
|
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
|
||||||
|
struct pcap_hdr_s {
|
||||||
|
u32 magic_number; /* magic number */
|
||||||
|
u16 version_major; /* major version number */
|
||||||
|
u16 version_minor; /* minor version number */
|
||||||
|
u32 thiszone; /* GMT to local correction */
|
||||||
|
u32 sigfigs; /* accuracy of timestamps */
|
||||||
|
u32 snaplen; /* max length of captured packets, in octets */
|
||||||
|
u32 network; /* data link type */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pcaprec_hdr_s {
|
||||||
|
u32 ts_sec; /* timestamp seconds */
|
||||||
|
u32 ts_usec; /* timestamp microseconds */
|
||||||
|
u32 incl_len; /* number of octets of packet saved in file */
|
||||||
|
u32 orig_len; /* actual length of packet */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void dump_init(void)
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
struct pcap_hdr_s header;
|
||||||
|
struct pcaprec_hdr_s pcap_header;
|
||||||
|
|
||||||
|
packet_count = 0;
|
||||||
|
|
||||||
|
if (stat(daemon->dump_file, &buf) == -1)
|
||||||
|
{
|
||||||
|
/* doesn't exist, create and add header */
|
||||||
|
header.magic_number = 0xa1b2c3d4;
|
||||||
|
header.version_major = 2;
|
||||||
|
header.version_minor = 4;
|
||||||
|
header.thiszone = 0;
|
||||||
|
header.sigfigs = 0;
|
||||||
|
header.snaplen = daemon->edns_pktsz + 200; /* slop for IP/UDP headers */
|
||||||
|
header.network = 101; /* DLT_RAW http://www.tcpdump.org/linktypes.html */
|
||||||
|
|
||||||
|
if (errno != ENOENT ||
|
||||||
|
(daemon->dumpfd = creat(daemon->dump_file, S_IRUSR | S_IWUSR)) == -1 ||
|
||||||
|
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 0))
|
||||||
|
die(_("cannot create %s: %s"), daemon->dump_file, EC_FILE);
|
||||||
|
}
|
||||||
|
else if ((daemon->dumpfd = open(daemon->dump_file, O_APPEND | O_RDWR)) == -1 ||
|
||||||
|
!read_write(daemon->dumpfd, (void *)&header, sizeof(header), 1))
|
||||||
|
die(_("cannot access %s: %s"), daemon->dump_file, EC_FILE);
|
||||||
|
else if (header.magic_number != 0xa1b2c3d4)
|
||||||
|
die(_("bad header in %s"), daemon->dump_file, EC_FILE);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* count existing records */
|
||||||
|
while (read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 1))
|
||||||
|
{
|
||||||
|
lseek(daemon->dumpfd, pcap_header.incl_len, SEEK_CUR);
|
||||||
|
packet_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
|
||||||
|
{
|
||||||
|
struct ip ip;
|
||||||
|
struct ip6_hdr ip6;
|
||||||
|
int family;
|
||||||
|
struct udphdr {
|
||||||
|
u16 uh_sport; /* source port */
|
||||||
|
u16 uh_dport; /* destination port */
|
||||||
|
u16 uh_ulen; /* udp length */
|
||||||
|
u16 uh_sum; /* udp checksum */
|
||||||
|
} udp;
|
||||||
|
struct pcaprec_hdr_s pcap_header;
|
||||||
|
struct timeval time;
|
||||||
|
u32 i, sum;
|
||||||
|
void *iphdr;
|
||||||
|
size_t ipsz;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* So wireshark can Id the packet. */
|
||||||
|
udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
|
||||||
|
|
||||||
|
if (src)
|
||||||
|
family = src->sa.sa_family;
|
||||||
|
else
|
||||||
|
family = dst->sa.sa_family;
|
||||||
|
|
||||||
|
if (family == AF_INET6)
|
||||||
|
{
|
||||||
|
iphdr = &ip6;
|
||||||
|
ipsz = sizeof(ip6);
|
||||||
|
memset(&ip6, 0, sizeof(ip6));
|
||||||
|
|
||||||
|
ip6.ip6_vfc = 6 << 4;
|
||||||
|
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
|
||||||
|
ip6.ip6_nxt = IPPROTO_UDP;
|
||||||
|
ip6.ip6_hops = 64;
|
||||||
|
|
||||||
|
if (src)
|
||||||
|
{
|
||||||
|
memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
|
||||||
|
udp.uh_sport = src->in6.sin6_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst)
|
||||||
|
{
|
||||||
|
memcpy(&ip6.ip6_dst, &dst->in6.sin6_addr, IN6ADDRSZ);
|
||||||
|
udp.uh_dport = dst->in6.sin6_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* start UDP checksum */
|
||||||
|
for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2)
|
||||||
|
{
|
||||||
|
sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ;
|
||||||
|
sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iphdr = &ip;
|
||||||
|
ipsz = sizeof(ip);
|
||||||
|
memset(&ip, 0, sizeof(ip));
|
||||||
|
|
||||||
|
ip.ip_v = IPVERSION;
|
||||||
|
ip.ip_hl = sizeof(struct ip) / 4;
|
||||||
|
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
|
||||||
|
ip.ip_ttl = IPDEFTTL;
|
||||||
|
ip.ip_p = IPPROTO_UDP;
|
||||||
|
|
||||||
|
if (src)
|
||||||
|
{
|
||||||
|
ip.ip_src = src->in.sin_addr;
|
||||||
|
udp.uh_sport = src->in.sin_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dst)
|
||||||
|
{
|
||||||
|
ip.ip_dst = dst->in.sin_addr;
|
||||||
|
udp.uh_dport = dst->in.sin_port;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip.ip_sum = 0;
|
||||||
|
for (sum = 0, i = 0; i < sizeof(struct ip) / 2; i++)
|
||||||
|
sum += ((u16 *)&ip)[i];
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||||
|
|
||||||
|
/* start UDP checksum */
|
||||||
|
sum = ip.ip_src.s_addr & 0xffff;
|
||||||
|
sum += (ip.ip_src.s_addr >> 16) & 0xffff;
|
||||||
|
sum += ip.ip_dst.s_addr & 0xffff;
|
||||||
|
sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len & 1)
|
||||||
|
((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
|
||||||
|
|
||||||
|
udp.uh_sum = 0;
|
||||||
|
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
|
||||||
|
sum += htons(IPPROTO_UDP);
|
||||||
|
sum += htons(sizeof(struct udphdr) + len);
|
||||||
|
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||||
|
sum += ((u16 *)&udp)[i];
|
||||||
|
for (i = 0; i < (len + 1) / 2; i++)
|
||||||
|
sum += ((u16 *)packet)[i];
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xffff) + (sum >> 16);
|
||||||
|
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||||
|
|
||||||
|
rc = gettimeofday(&time, NULL);
|
||||||
|
pcap_header.ts_sec = time.tv_sec;
|
||||||
|
pcap_header.ts_usec = time.tv_usec;
|
||||||
|
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
|
||||||
|
|
||||||
|
if (rc == -1 ||
|
||||||
|
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
|
||||||
|
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
|
||||||
|
!read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) ||
|
||||||
|
!read_write(daemon->dumpfd, (void *)packet, len, 0))
|
||||||
|
my_syslog(LOG_ERR, _("failed to write packet dump"));
|
||||||
|
else
|
||||||
|
my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+2
-14
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -301,20 +301,14 @@ static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *lim
|
|||||||
|
|
||||||
struct subnet_opt {
|
struct subnet_opt {
|
||||||
u16 family;
|
u16 family;
|
||||||
u8 source_netmask, scope_netmask;
|
u8 source_netmask, scope_netmask;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
u8 addr[IN6ADDRSZ];
|
u8 addr[IN6ADDRSZ];
|
||||||
#else
|
|
||||||
u8 addr[INADDRSZ];
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void *get_addrp(union mysockaddr *addr, const short family)
|
static void *get_addrp(union mysockaddr *addr, const short family)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (family == AF_INET6)
|
if (family == AF_INET6)
|
||||||
return &addr->in6.sin6_addr;
|
return &addr->in6.sin6_addr;
|
||||||
#endif
|
|
||||||
|
|
||||||
return &addr->in.sin_addr;
|
return &addr->in.sin_addr;
|
||||||
}
|
}
|
||||||
@@ -330,7 +324,6 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
|||||||
opt->source_netmask = 0;
|
opt->source_netmask = 0;
|
||||||
opt->scope_netmask = 0;
|
opt->scope_netmask = 0;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
|
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
|
||||||
{
|
{
|
||||||
opt->source_netmask = daemon->add_subnet6->mask;
|
opt->source_netmask = daemon->add_subnet6->mask;
|
||||||
@@ -342,7 +335,6 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
|||||||
else
|
else
|
||||||
addrp = &source->in6.sin6_addr;
|
addrp = &source->in6.sin6_addr;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
|
if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
|
||||||
{
|
{
|
||||||
@@ -356,11 +348,7 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
|||||||
addrp = &source->in.sin_addr;
|
addrp = &source->in.sin_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
|
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
|
||||||
#else
|
|
||||||
opt->family = htons(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
|
|||||||
+411
-249
File diff suppressed because it is too large.
Load diff
+19
-23
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -64,11 +64,10 @@ struct script_data
|
|||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
off_t file_len;
|
off_t file_len;
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
int iaid, vendorclass_count;
|
int vendorclass_count;
|
||||||
|
unsigned int iaid;
|
||||||
#endif
|
#endif
|
||||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||||
char interface[IF_NAMESIZE];
|
char interface[IF_NAMESIZE];
|
||||||
@@ -82,7 +81,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int i, pipefd[2];
|
int i, pipefd[2];
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
|
unsigned char *alloc_buff = NULL;
|
||||||
|
|
||||||
/* create the pipe through which the main program sends us commands,
|
/* create the pipe through which the main program sends us commands,
|
||||||
then fork our process. */
|
then fork our process. */
|
||||||
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
|
if (pipe(pipefd) == -1 || !fix_fd(pipefd[1]) || (pid = fork()) == -1)
|
||||||
@@ -97,13 +97,14 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
return pipefd[1];
|
return pipefd[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ignore SIGTERM, so that we can clean up when the main process gets hit
|
/* ignore SIGTERM and SIGINT, so that we can clean up when the main process gets hit
|
||||||
and SIGALRM so that we can use sleep() */
|
and SIGALRM so that we can use sleep() */
|
||||||
sigact.sa_handler = SIG_IGN;
|
sigact.sa_handler = SIG_IGN;
|
||||||
sigact.sa_flags = 0;
|
sigact.sa_flags = 0;
|
||||||
sigemptyset(&sigact.sa_mask);
|
sigemptyset(&sigact.sa_mask);
|
||||||
sigaction(SIGTERM, &sigact, NULL);
|
sigaction(SIGTERM, &sigact, NULL);
|
||||||
sigaction(SIGALRM, &sigact, NULL);
|
sigaction(SIGALRM, &sigact, NULL);
|
||||||
|
sigaction(SIGINT, &sigact, NULL);
|
||||||
|
|
||||||
if (!option_bool(OPT_DEBUG) && uid != 0)
|
if (!option_bool(OPT_DEBUG) && uid != 0)
|
||||||
{
|
{
|
||||||
@@ -130,12 +131,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
Don't close err_fd, in case the lua-init fails.
|
Don't close err_fd, in case the lua-init fails.
|
||||||
Note that we have to do this before lua init
|
Note that we have to do this before lua init
|
||||||
so we don't close any lua fds. */
|
so we don't close any lua fds. */
|
||||||
for (max_fd--; max_fd >= 0; max_fd--)
|
close_fds(max_fd, pipefd[0], event_fd, err_fd);
|
||||||
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO &&
|
|
||||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
|
|
||||||
max_fd != event_fd && max_fd != err_fd)
|
|
||||||
close(max_fd);
|
|
||||||
|
|
||||||
#ifdef HAVE_LUASCRIPT
|
#ifdef HAVE_LUASCRIPT
|
||||||
if (daemon->luascript)
|
if (daemon->luascript)
|
||||||
{
|
{
|
||||||
@@ -187,11 +184,16 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
struct script_data data;
|
struct script_data data;
|
||||||
char *p, *action_str, *hostname = NULL, *domain = NULL;
|
char *p, *action_str, *hostname = NULL, *domain = NULL;
|
||||||
unsigned char *buf = (unsigned char *)daemon->namebuff;
|
unsigned char *buf = (unsigned char *)daemon->namebuff;
|
||||||
unsigned char *end, *extradata, *alloc_buff = NULL;
|
unsigned char *end, *extradata;
|
||||||
int is6, err = 0;
|
int is6, err = 0;
|
||||||
int pipeout[2];
|
int pipeout[2];
|
||||||
|
|
||||||
free(alloc_buff);
|
/* Free rarely-allocated memory from previous iteration. */
|
||||||
|
if (alloc_buff)
|
||||||
|
{
|
||||||
|
free(alloc_buff);
|
||||||
|
alloc_buff = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* we read zero bytes when pipe closed: this is our signal to exit */
|
/* we read zero bytes when pipe closed: this is our signal to exit */
|
||||||
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
|
if (!read_write(pipefd[0], (unsigned char *)&data, sizeof(data), 1))
|
||||||
@@ -301,10 +303,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
|
|
||||||
if (!is6)
|
if (!is6)
|
||||||
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
/* file length */
|
/* file length */
|
||||||
@@ -825,10 +825,8 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
|||||||
|
|
||||||
if ((buf->flags = peer->sa.sa_family) == AF_INET)
|
if ((buf->flags = peer->sa.sa_family) == AF_INET)
|
||||||
buf->addr = peer->in.sin_addr;
|
buf->addr = peer->in.sin_addr;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
buf->addr6 = peer->in6.sin6_addr;
|
buf->addr6 = peer->in6.sin6_addr;
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy((unsigned char *)(buf+1), filename, filename_len);
|
memcpy((unsigned char *)(buf+1), filename, filename_len);
|
||||||
|
|
||||||
@@ -836,7 +834,7 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr)
|
void queue_arp(int action, unsigned char *mac, int maclen, int family, union all_addr *addr)
|
||||||
{
|
{
|
||||||
/* no script */
|
/* no script */
|
||||||
if (daemon->helperfd == -1)
|
if (daemon->helperfd == -1)
|
||||||
@@ -849,11 +847,9 @@ void queue_arp(int action, unsigned char *mac, int maclen, int family, struct al
|
|||||||
buf->hwaddr_len = maclen;
|
buf->hwaddr_len = maclen;
|
||||||
buf->hwaddr_type = ARPHRD_ETHER;
|
buf->hwaddr_type = ARPHRD_ETHER;
|
||||||
if ((buf->flags = family) == AF_INET)
|
if ((buf->flags = family) == AF_INET)
|
||||||
buf->addr = addr->addr.addr4;
|
buf->addr = addr->addr4;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
buf->addr6 = addr->addr.addr6;
|
buf->addr6 = addr->addr6;
|
||||||
#endif
|
|
||||||
|
|
||||||
memcpy(buf->hwaddr, mac, maclen);
|
memcpy(buf->hwaddr, mac, maclen);
|
||||||
|
|
||||||
|
|||||||
+12
-10
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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 @@
|
|||||||
#include <sys/inotify.h>
|
#include <sys/inotify.h>
|
||||||
#include <sys/param.h> /* For MAXSYMLINKS */
|
#include <sys/param.h> /* For MAXSYMLINKS */
|
||||||
|
|
||||||
/* the strategy is to set a inotify on the directories containing
|
/* the strategy is to set an inotify on the directories containing
|
||||||
resolv files, for any files in the directory which are close-write
|
resolv files, for any files in the directory which are close-write
|
||||||
or moved into the directory.
|
or moved into the directory.
|
||||||
|
|
||||||
@@ -227,19 +227,21 @@ int inotify_check(time_t now)
|
|||||||
|
|
||||||
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
|
for (p = inotify_buffer; rc - (p - inotify_buffer) >= (int)sizeof(struct inotify_event); p += sizeof(struct inotify_event) + in->len)
|
||||||
{
|
{
|
||||||
|
size_t namelen;
|
||||||
|
|
||||||
in = (struct inotify_event*)p;
|
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 */
|
/* ignore emacs backups and dotfiles */
|
||||||
if (in->len == 0 ||
|
if (in->len == 0 || (namelen = strlen(in->name)) == 0 ||
|
||||||
in->name[in->len - 1] == '~' ||
|
in->name[namelen - 1] == '~' ||
|
||||||
(in->name[0] == '#' && in->name[in->len - 1] == '#') ||
|
(in->name[0] == '#' && in->name[namelen - 1] == '#') ||
|
||||||
in->name[0] == '.')
|
in->name[0] == '.')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
for (res = daemon->resolv_files; res; res = res->next)
|
||||||
|
if (res->wd == in->wd && strcmp(res->file, in->name) == 0)
|
||||||
|
hit = 1;
|
||||||
|
|
||||||
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
for (ah = daemon->dynamic_dirs; ah; ah = ah->next)
|
||||||
if (ah->wd == in->wd)
|
if (ah->wd == in->wd)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
|
|||||||
+7
-29
@@ -22,9 +22,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/utsname.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
|
|
||||||
/* We want to be able to compile against old header files
|
/* We want to be able to compile against old header files
|
||||||
@@ -87,20 +85,7 @@ static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, con
|
|||||||
|
|
||||||
void ipset_init(void)
|
void ipset_init(void)
|
||||||
{
|
{
|
||||||
struct utsname utsname;
|
old_kernel = (daemon->kernel_version < KERNEL_VERSION(2,6,32));
|
||||||
int version;
|
|
||||||
char *split;
|
|
||||||
|
|
||||||
if (uname(&utsname) < 0)
|
|
||||||
die(_("failed to find kernel version: %s"), NULL, EC_MISC);
|
|
||||||
|
|
||||||
split = strtok(utsname.release, ".");
|
|
||||||
version = (split ? atoi(split) : 0);
|
|
||||||
split = strtok(NULL, ".");
|
|
||||||
version = version * 256 + (split ? atoi(split) : 0);
|
|
||||||
split = strtok(NULL, ".");
|
|
||||||
version = version * 256 + (split ? atoi(split) : 0);
|
|
||||||
old_kernel = (version < KERNEL_VERSION(2,6,32));
|
|
||||||
|
|
||||||
if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
|
if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
|
||||||
return;
|
return;
|
||||||
@@ -114,19 +99,14 @@ void ipset_init(void)
|
|||||||
die (_("failed to create IPset control socket: %s"), NULL, EC_MISC);
|
die (_("failed to create IPset control socket: %s"), NULL, EC_MISC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int af, int remove)
|
static int new_add_to_ipset(const char *setname, const union all_addr *ipaddr, int af, int remove)
|
||||||
{
|
{
|
||||||
struct nlmsghdr *nlh;
|
struct nlmsghdr *nlh;
|
||||||
struct my_nfgenmsg *nfg;
|
struct my_nfgenmsg *nfg;
|
||||||
struct my_nlattr *nested[2];
|
struct my_nlattr *nested[2];
|
||||||
uint8_t proto;
|
uint8_t proto;
|
||||||
int addrsz = INADDRSZ;
|
int addrsz = (af == AF_INET6) ? IN6ADDRSZ : INADDRSZ;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (af == AF_INET6)
|
|
||||||
addrsz = IN6ADDRSZ;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (strlen(setname) >= IPSET_MAXNAMELEN)
|
if (strlen(setname) >= IPSET_MAXNAMELEN)
|
||||||
{
|
{
|
||||||
errno = ENAMETOOLONG;
|
errno = ENAMETOOLONG;
|
||||||
@@ -157,7 +137,7 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
|
nested[1]->nla_type = NLA_F_NESTED | IPSET_ATTR_IP;
|
||||||
add_attr(nlh,
|
add_attr(nlh,
|
||||||
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
|
(af == AF_INET ? IPSET_ATTR_IPADDR_IPV4 : IPSET_ATTR_IPADDR_IPV6) | NLA_F_NET_BYTEORDER,
|
||||||
addrsz, &ipaddr->addr);
|
addrsz, 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];
|
||||||
|
|
||||||
@@ -168,7 +148,7 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr, int remove)
|
static int old_add_to_ipset(const char *setname, const union all_addr *ipaddr, int remove)
|
||||||
{
|
{
|
||||||
socklen_t size;
|
socklen_t size;
|
||||||
struct ip_set_req_adt_get {
|
struct ip_set_req_adt_get {
|
||||||
@@ -200,7 +180,7 @@ static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
return -1;
|
return -1;
|
||||||
req_adt.op = remove ? 0x102 : 0x101;
|
req_adt.op = remove ? 0x102 : 0x101;
|
||||||
req_adt.index = req_adt_get.set.index;
|
req_adt.index = req_adt_get.set.index;
|
||||||
req_adt.ip = ntohl(ipaddr->addr.addr4.s_addr);
|
req_adt.ip = ntohl(ipaddr->addr4.s_addr);
|
||||||
if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
|
if (setsockopt(ipset_sock, SOL_IP, 83, &req_adt, sizeof(req_adt)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@@ -209,11 +189,10 @@ static int old_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags, int remove)
|
int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove)
|
||||||
{
|
{
|
||||||
int ret = 0, af = AF_INET;
|
int ret = 0, af = AF_INET;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (flags & F_IPV6)
|
if (flags & F_IPV6)
|
||||||
{
|
{
|
||||||
af = AF_INET6;
|
af = AF_INET6;
|
||||||
@@ -224,7 +203,6 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
|
|||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret != -1)
|
if (ret != -1)
|
||||||
ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
|
ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
|
||||||
|
|||||||
+49
-30
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,7 @@ static int dns_dirty, file_dirty, leases_left;
|
|||||||
static int read_leases(time_t now, FILE *leasestream)
|
static int read_leases(time_t now, FILE *leasestream)
|
||||||
{
|
{
|
||||||
unsigned long ei;
|
unsigned long ei;
|
||||||
struct all_addr addr;
|
union all_addr addr;
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
int clid_len, hw_len, hw_type;
|
int clid_len, hw_len, hw_type;
|
||||||
int items;
|
int items;
|
||||||
@@ -60,11 +60,16 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
|
|
||||||
if (fscanf(leasestream, " %64s %255s %764s",
|
if (fscanf(leasestream, " %64s %255s %764s",
|
||||||
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
|
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4))
|
|
||||||
{
|
{
|
||||||
if ((lease = lease4_allocate(addr.addr.addr4)))
|
my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database: %s %s %s %s ..."),
|
||||||
|
daemon->dhcp_buff3, daemon->dhcp_buff2,
|
||||||
|
daemon->namebuff, daemon->dhcp_buff);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr4))
|
||||||
|
{
|
||||||
|
if ((lease = lease4_allocate(addr.addr4)))
|
||||||
domain = get_domain(lease->addr);
|
domain = get_domain(lease->addr);
|
||||||
|
|
||||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||||
@@ -73,7 +78,7 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
hw_type = ARPHRD_ETHER;
|
hw_type = ARPHRD_ETHER;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
|
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr6))
|
||||||
{
|
{
|
||||||
char *s = daemon->dhcp_buff2;
|
char *s = daemon->dhcp_buff2;
|
||||||
int lease_type = LEASE_NA;
|
int lease_type = LEASE_NA;
|
||||||
@@ -84,15 +89,20 @@ static int read_leases(time_t now, FILE *leasestream)
|
|||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
|
if ((lease = lease6_allocate(&addr.addr6, lease_type)))
|
||||||
{
|
{
|
||||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||||
domain = get_domain6((struct in6_addr *)lease->hwaddr);
|
domain = get_domain6(&lease->addr6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
else
|
||||||
return 0;
|
{
|
||||||
|
my_syslog(MS_DHCP | LOG_WARNING, _("ignoring invalid line in lease database, bad address: %s"),
|
||||||
|
daemon->namebuff);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!lease)
|
if (!lease)
|
||||||
die (_("too many stored leases"), NULL, EC_MISC);
|
die (_("too many stored leases"), NULL, EC_MISC);
|
||||||
@@ -172,10 +182,8 @@ void lease_init(time_t now)
|
|||||||
if (leasestream)
|
if (leasestream)
|
||||||
{
|
{
|
||||||
if (!read_leases(now, leasestream))
|
if (!read_leases(now, leasestream))
|
||||||
my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
|
my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database cleanly"));
|
||||||
daemon->dhcp_buff3, daemon->dhcp_buff2,
|
|
||||||
daemon->namebuff, daemon->dhcp_buff);
|
|
||||||
|
|
||||||
if (ferror(leasestream))
|
if (ferror(leasestream))
|
||||||
die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
|
die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
|
||||||
}
|
}
|
||||||
@@ -222,7 +230,7 @@ void lease_update_from_configs(void)
|
|||||||
if (lease->flags & (LEASE_TA | LEASE_NA))
|
if (lease->flags & (LEASE_TA | LEASE_NA))
|
||||||
continue;
|
continue;
|
||||||
else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
|
else if ((config = find_config(daemon->dhcp_conf, NULL, lease->clid, lease->clid_len,
|
||||||
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL)) &&
|
lease->hwaddr, lease->hwaddr_len, lease->hwaddr_type, NULL, NULL)) &&
|
||||||
(config->flags & CONFIG_NAME) &&
|
(config->flags & CONFIG_NAME) &&
|
||||||
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
|
(!(config->flags & CONFIG_ADDR) || config->addr.s_addr == lease->addr.s_addr))
|
||||||
lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
|
lease_set_hostname(lease, config->hostname, 1, get_domain(lease->addr), NULL);
|
||||||
@@ -514,28 +522,28 @@ void lease_update_dns(int force)
|
|||||||
if (slaac->backoff == 0)
|
if (slaac->backoff == 0)
|
||||||
{
|
{
|
||||||
if (lease->fqdn)
|
if (lease->fqdn)
|
||||||
cache_add_dhcp_entry(lease->fqdn, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
|
cache_add_dhcp_entry(lease->fqdn, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
|
||||||
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
||||||
cache_add_dhcp_entry(lease->hostname, AF_INET6, (struct all_addr *)&slaac->addr, lease->expires);
|
cache_add_dhcp_entry(lease->hostname, AF_INET6, (union all_addr *)&slaac->addr, lease->expires);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lease->fqdn)
|
if (lease->fqdn)
|
||||||
cache_add_dhcp_entry(lease->fqdn, prot,
|
cache_add_dhcp_entry(lease->fqdn, prot,
|
||||||
prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->addr6,
|
prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6,
|
||||||
lease->expires);
|
lease->expires);
|
||||||
|
|
||||||
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
||||||
cache_add_dhcp_entry(lease->hostname, prot,
|
cache_add_dhcp_entry(lease->hostname, prot,
|
||||||
prot == AF_INET ? (struct all_addr *)&lease->addr : (struct all_addr *)&lease->addr6,
|
prot == AF_INET ? (union all_addr *)&lease->addr : (union all_addr *)&lease->addr6,
|
||||||
lease->expires);
|
lease->expires);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
if (lease->fqdn)
|
if (lease->fqdn)
|
||||||
cache_add_dhcp_entry(lease->fqdn, prot, (struct all_addr *)&lease->addr, lease->expires);
|
cache_add_dhcp_entry(lease->fqdn, prot, (union all_addr *)&lease->addr, lease->expires);
|
||||||
|
|
||||||
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
if (!option_bool(OPT_DHCP_FQDN) && lease->hostname)
|
||||||
cache_add_dhcp_entry(lease->hostname, prot, (struct all_addr *)&lease->addr, lease->expires);
|
cache_add_dhcp_entry(lease->hostname, prot, (union all_addr *)&lease->addr, lease->expires);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,12 +558,14 @@ void lease_prune(struct dhcp_lease *target, time_t now)
|
|||||||
for (lease = leases, up = &leases; lease; lease = tmp)
|
for (lease = leases, up = &leases; lease; lease = tmp)
|
||||||
{
|
{
|
||||||
tmp = lease->next;
|
tmp = lease->next;
|
||||||
if ((lease->expires != 0 && difftime(now, lease->expires) > 0) || lease == target)
|
if ((lease->expires != 0 && difftime(now, lease->expires) >= 0) || lease == target)
|
||||||
{
|
{
|
||||||
file_dirty = 1;
|
file_dirty = 1;
|
||||||
if (lease->hostname)
|
if (lease->hostname)
|
||||||
dns_dirty = 1;
|
dns_dirty = 1;
|
||||||
|
|
||||||
|
daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
|
||||||
|
|
||||||
*up = lease->next; /* unlink */
|
*up = lease->next; /* unlink */
|
||||||
|
|
||||||
/* Put on old_leases list 'till we
|
/* Put on old_leases list 'till we
|
||||||
@@ -625,7 +635,8 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
|
|||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
/* find address for {CLID, IAID, address} */
|
/* find address for {CLID, IAID, address} */
|
||||||
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
struct dhcp_lease *lease6_find(unsigned char *clid, int clid_len,
|
||||||
int lease_type, int iaid, struct in6_addr *addr)
|
int lease_type, unsigned int iaid,
|
||||||
|
struct in6_addr *addr)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
@@ -657,7 +668,9 @@ void lease6_reset(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* enumerate all leases belonging to {CLID, IAID} */
|
/* enumerate all leases belonging to {CLID, IAID} */
|
||||||
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type, unsigned char *clid, int clid_len, int iaid)
|
struct dhcp_lease *lease6_find_by_client(struct dhcp_lease *first, int lease_type,
|
||||||
|
unsigned char *clid, int clid_len,
|
||||||
|
unsigned int iaid)
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
|
||||||
@@ -773,7 +786,10 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr)
|
|||||||
{
|
{
|
||||||
struct dhcp_lease *lease = lease_allocate();
|
struct dhcp_lease *lease = lease_allocate();
|
||||||
if (lease)
|
if (lease)
|
||||||
lease->addr = addr;
|
{
|
||||||
|
lease->addr = addr;
|
||||||
|
daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
|
||||||
|
}
|
||||||
|
|
||||||
return lease;
|
return lease;
|
||||||
}
|
}
|
||||||
@@ -788,6 +804,8 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
|
|||||||
lease->addr6 = *addrp;
|
lease->addr6 = *addrp;
|
||||||
lease->flags |= lease_type;
|
lease->flags |= lease_type;
|
||||||
lease->iaid = 0;
|
lease->iaid = 0;
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return lease;
|
return lease;
|
||||||
@@ -818,7 +836,7 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
|
|||||||
dns_dirty = 1;
|
dns_dirty = 1;
|
||||||
lease->expires = exp;
|
lease->expires = exp;
|
||||||
#ifndef HAVE_BROKEN_RTC
|
#ifndef HAVE_BROKEN_RTC
|
||||||
lease->flags |= LEASE_AUX_CHANGED;
|
lease->flags |= LEASE_AUX_CHANGED | LEASE_EXP_CHANGED;
|
||||||
file_dirty = 1;
|
file_dirty = 1;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -834,7 +852,7 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
void lease_set_iaid(struct dhcp_lease *lease, int iaid)
|
void lease_set_iaid(struct dhcp_lease *lease, unsigned int iaid)
|
||||||
{
|
{
|
||||||
if (lease->iaid != iaid)
|
if (lease->iaid != iaid)
|
||||||
{
|
{
|
||||||
@@ -1118,7 +1136,8 @@ int do_script_run(time_t now)
|
|||||||
|
|
||||||
for (lease = leases; lease; lease = lease->next)
|
for (lease = leases; lease; lease = lease->next)
|
||||||
if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) ||
|
if ((lease->flags & (LEASE_NEW | LEASE_CHANGED)) ||
|
||||||
((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)))
|
((lease->flags & LEASE_AUX_CHANGED) && option_bool(OPT_LEASE_RO)) ||
|
||||||
|
((lease->flags & LEASE_EXP_CHANGED) && option_bool(OPT_LEASE_RENEW)))
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SCRIPT
|
#ifdef HAVE_SCRIPT
|
||||||
queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
|
queue_script((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
|
||||||
@@ -1128,7 +1147,7 @@ int do_script_run(time_t now)
|
|||||||
emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
|
emit_dbus_signal((lease->flags & LEASE_NEW) ? ACTION_ADD : ACTION_OLD, lease,
|
||||||
lease->fqdn ? lease->fqdn : lease->hostname);
|
lease->fqdn ? lease->fqdn : lease->hostname);
|
||||||
#endif
|
#endif
|
||||||
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED);
|
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED | LEASE_AUX_CHANGED | LEASE_EXP_CHANGED);
|
||||||
|
|
||||||
/* this is used for the "add" call, then junked, since they're not in the database */
|
/* this is used for the "add" call, then junked, since they're not in the database */
|
||||||
free(lease->extradata);
|
free(lease->extradata);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -232,7 +232,7 @@ static void log_write(void)
|
|||||||
logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1;
|
logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1;
|
||||||
#endif
|
#endif
|
||||||
logaddr.sun_family = AF_UNIX;
|
logaddr.sun_family = AF_UNIX;
|
||||||
strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
safe_strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
||||||
|
|
||||||
/* Got connection back? try again. */
|
/* Got connection back? try again. */
|
||||||
if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
|
if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
const char * metric_names[] = {
|
||||||
|
"dns_cache_inserted",
|
||||||
|
"dns_cache_live_freed",
|
||||||
|
"dns_queries_forwarded",
|
||||||
|
"dns_auth_answered",
|
||||||
|
"dns_local_answered",
|
||||||
|
"bootp",
|
||||||
|
"pxe",
|
||||||
|
"dhcp_ack",
|
||||||
|
"dhcp_decline",
|
||||||
|
"dhcp_discover",
|
||||||
|
"dhcp_inform",
|
||||||
|
"dhcp_nak",
|
||||||
|
"dhcp_offer",
|
||||||
|
"dhcp_release",
|
||||||
|
"dhcp_request",
|
||||||
|
"noanswer",
|
||||||
|
"leases_allocated_4",
|
||||||
|
"leases_pruned_4",
|
||||||
|
"leases_allocated_6",
|
||||||
|
"leases_pruned_6",
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* get_metric_name(int i) {
|
||||||
|
return metric_names[i];
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If you modify this list, please keep the labels in metrics.c in sync. */
|
||||||
|
enum {
|
||||||
|
METRIC_DNS_CACHE_INSERTED,
|
||||||
|
METRIC_DNS_CACHE_LIVE_FREED,
|
||||||
|
METRIC_DNS_QUERIES_FORWARDED,
|
||||||
|
METRIC_DNS_AUTH_ANSWERED,
|
||||||
|
METRIC_DNS_LOCAL_ANSWERED,
|
||||||
|
METRIC_BOOTP,
|
||||||
|
METRIC_PXE,
|
||||||
|
METRIC_DHCPACK,
|
||||||
|
METRIC_DHCPDECLINE,
|
||||||
|
METRIC_DHCPDISCOVER,
|
||||||
|
METRIC_DHCPINFORM,
|
||||||
|
METRIC_DHCPNAK,
|
||||||
|
METRIC_DHCPOFFER,
|
||||||
|
METRIC_DHCPRELEASE,
|
||||||
|
METRIC_DHCPREQUEST,
|
||||||
|
METRIC_NOANSWER,
|
||||||
|
METRIC_LEASES_ALLOCATED_4,
|
||||||
|
METRIC_LEASES_PRUNED_4,
|
||||||
|
METRIC_LEASES_ALLOCATED_6,
|
||||||
|
METRIC_LEASES_PRUNED_6,
|
||||||
|
|
||||||
|
__METRIC_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
const char* get_metric_name(int);
|
||||||
+27
-11
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -22,6 +22,15 @@
|
|||||||
#include <linux/netlink.h>
|
#include <linux/netlink.h>
|
||||||
#include <linux/rtnetlink.h>
|
#include <linux/rtnetlink.h>
|
||||||
|
|
||||||
|
/* Blergh. Radv does this, so that's our excuse. */
|
||||||
|
#ifndef SOL_NETLINK
|
||||||
|
#define SOL_NETLINK 270
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NETLINK_NO_ENOBUFS
|
||||||
|
#define NETLINK_NO_ENOBUFS 5
|
||||||
|
#endif
|
||||||
|
|
||||||
/* linux 2.6.19 buggers up the headers, patch it up here. */
|
/* linux 2.6.19 buggers up the headers, patch it up here. */
|
||||||
#ifndef IFA_RTA
|
#ifndef IFA_RTA
|
||||||
# define IFA_RTA(r) \
|
# define IFA_RTA(r) \
|
||||||
@@ -40,10 +49,11 @@ static u32 netlink_pid;
|
|||||||
|
|
||||||
static void nl_async(struct nlmsghdr *h);
|
static void nl_async(struct nlmsghdr *h);
|
||||||
|
|
||||||
void netlink_init(void)
|
char *netlink_init(void)
|
||||||
{
|
{
|
||||||
struct sockaddr_nl addr;
|
struct sockaddr_nl addr;
|
||||||
socklen_t slen = sizeof(addr);
|
socklen_t slen = sizeof(addr);
|
||||||
|
int opt = 1;
|
||||||
|
|
||||||
addr.nl_family = AF_NETLINK;
|
addr.nl_family = AF_NETLINK;
|
||||||
addr.nl_pad = 0;
|
addr.nl_pad = 0;
|
||||||
@@ -51,11 +61,10 @@ void netlink_init(void)
|
|||||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
||||||
if (option_bool(OPT_CLEVERBIND))
|
if (option_bool(OPT_CLEVERBIND))
|
||||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
#endif
|
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
if (daemon->doing_ra || daemon->doing_dhcp6)
|
if (daemon->doing_ra || daemon->doing_dhcp6)
|
||||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||||
@@ -75,12 +84,19 @@ void netlink_init(void)
|
|||||||
if (daemon->netlinkfd == -1 ||
|
if (daemon->netlinkfd == -1 ||
|
||||||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
|
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
|
||||||
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
|
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
|
||||||
/* save pid assigned by bind() and retrieved by getsockname() */
|
/* save pid assigned by bind() and retrieved by getsockname() */
|
||||||
netlink_pid = addr.nl_pid;
|
netlink_pid = addr.nl_pid;
|
||||||
|
|
||||||
iov.iov_len = 100;
|
iov.iov_len = 100;
|
||||||
iov.iov_base = safe_malloc(iov.iov_len);
|
iov.iov_base = safe_malloc(iov.iov_len);
|
||||||
|
|
||||||
|
if (daemon->kernel_version >= KERNEL_VERSION(2,6,30) &&
|
||||||
|
setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1)
|
||||||
|
return _("warning: failed to set NETLINK_NO_ENOBUFS on netlink socket");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t netlink_recv(void)
|
static ssize_t netlink_recv(void)
|
||||||
@@ -149,10 +165,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
struct rtgenmsg g;
|
struct rtgenmsg g;
|
||||||
} req;
|
} req;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
|
||||||
addr.nl_family = AF_NETLINK;
|
addr.nl_family = AF_NETLINK;
|
||||||
addr.nl_pad = 0;
|
|
||||||
addr.nl_groups = 0;
|
|
||||||
addr.nl_pid = 0; /* address to kernel */
|
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (family == AF_UNSPEC)
|
if (family == AF_UNSPEC)
|
||||||
@@ -235,7 +251,6 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm)))
|
if (!((*callback)(addr, ifa->ifa_index, label, netmask, broadcast, parm)))
|
||||||
callback_ok = 0;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (ifa->ifa_family == AF_INET6)
|
else if (ifa->ifa_family == AF_INET6)
|
||||||
{
|
{
|
||||||
struct in6_addr *addrp = NULL;
|
struct in6_addr *addrp = NULL;
|
||||||
@@ -270,7 +285,6 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
|||||||
(int) preferred, (int)valid, parm)))
|
(int) preferred, (int)valid, parm)))
|
||||||
callback_ok = 0;
|
callback_ok = 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC)
|
else if (h->nlmsg_type == RTM_NEWNEIGH && family == AF_UNSPEC)
|
||||||
@@ -363,7 +377,9 @@ static void nl_async(struct nlmsghdr *h)
|
|||||||
failing. */
|
failing. */
|
||||||
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 &&
|
||||||
|
(rtm->rtm_table == RT_TABLE_MAIN ||
|
||||||
|
rtm->rtm_table == RT_TABLE_LOCAL))
|
||||||
queue_event(EVENT_NEWROUTE);
|
queue_event(EVENT_NEWROUTE);
|
||||||
}
|
}
|
||||||
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
else if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
|
||||||
|
|||||||
+208
-124
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -29,7 +29,7 @@ int indextoname(int fd, int index, char *name)
|
|||||||
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
|
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -82,12 +82,12 @@ int indextoname(int fd, int index, char *name)
|
|||||||
for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
|
for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
|
||||||
{
|
{
|
||||||
struct lifreq lifr;
|
struct lifreq lifr;
|
||||||
strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
||||||
if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
|
if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (lifr.lifr_index == index) {
|
if (lifr.lifr_index == index) {
|
||||||
strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +109,7 @@ int indextoname(int fd, int index, char *name)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||||
{
|
{
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
int ret = 1, match_addr = 0;
|
int ret = 1, match_addr = 0;
|
||||||
@@ -135,14 +135,12 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
|||||||
if (tmp->addr.sa.sa_family == family)
|
if (tmp->addr.sa.sa_family == family)
|
||||||
{
|
{
|
||||||
if (family == AF_INET &&
|
if (family == AF_INET &&
|
||||||
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||||
ret = match_addr = tmp->used = 1;
|
ret = match_addr = tmp->used = 1;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (family == AF_INET6 &&
|
else if (family == AF_INET6 &&
|
||||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
|
||||||
&addr->addr.addr6))
|
&addr->addr6))
|
||||||
ret = match_addr = tmp->used = 1;
|
ret = match_addr = tmp->used = 1;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,13 +158,11 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||||
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||||
break;
|
break;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6))
|
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
if (tmp && auth)
|
if (tmp && auth)
|
||||||
{
|
{
|
||||||
@@ -183,12 +179,12 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
|||||||
an interface other than the loopback. Accept packet if it arrived via a loopback
|
an interface other than the loopback. Accept packet if it arrived via a loopback
|
||||||
interface, even when we're not accepting packets that way, as long as the destination
|
interface, even when we're not accepting packets that way, as long as the destination
|
||||||
address is one we're believing. Interface list must be up-to-date before calling. */
|
address is one we're believing. Interface list must be up-to-date before calling. */
|
||||||
int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
int loopback_exception(int fd, int family, union all_addr *addr, char *name)
|
||||||
{
|
{
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
|
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
|
||||||
ifr.ifr_flags & IFF_LOOPBACK)
|
ifr.ifr_flags & IFF_LOOPBACK)
|
||||||
{
|
{
|
||||||
@@ -197,14 +193,11 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
|||||||
{
|
{
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
{
|
{
|
||||||
if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
if (iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr6))
|
||||||
else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.addr6))
|
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -214,7 +207,7 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
|||||||
on the relevant address, but the name of the arrival interface, derived from the
|
on the relevant address, but the name of the arrival interface, derived from the
|
||||||
index won't match the config. Check that we found an interface address for the arrival
|
index won't match the config. Check that we found an interface address for the arrival
|
||||||
interface: daemon->interfaces must be up-to-date. */
|
interface: daemon->interfaces must be up-to-date. */
|
||||||
int label_exception(int index, int family, struct all_addr *addr)
|
int label_exception(int index, int family, union all_addr *addr)
|
||||||
{
|
{
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
|
|
||||||
@@ -224,7 +217,7 @@ int label_exception(int index, int family, struct all_addr *addr)
|
|||||||
|
|
||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
|
if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
|
||||||
iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr)
|
iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -289,22 +282,18 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET)
|
if (addr->sa.sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
al->addr.addr.addr4 = addr->in.sin_addr;
|
al->addr.addr4 = addr->in.sin_addr;
|
||||||
al->flags = 0;
|
al->flags = 0;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
al->addr.addr6 = addr->in6.sin6_addr;
|
||||||
al->flags = ADDRLIST_IPV6;
|
al->flags = ADDRLIST_IPV6;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#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))
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
struct interface_name *int_name;
|
struct interface_name *int_name;
|
||||||
struct addrlist *al;
|
struct addrlist *al;
|
||||||
@@ -332,12 +321,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
al->next = zone->subnet;
|
al->next = zone->subnet;
|
||||||
zone->subnet = al;
|
zone->subnet = al;
|
||||||
al->prefixlen = prefixlen;
|
al->prefixlen = prefixlen;
|
||||||
al->addr.addr.addr4 = addr->in.sin_addr;
|
al->addr.addr4 = addr->in.sin_addr;
|
||||||
al->flags = 0;
|
al->flags = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
|
if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
|
||||||
{
|
{
|
||||||
if (param->spare)
|
if (param->spare)
|
||||||
@@ -353,12 +341,10 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
al->next = zone->subnet;
|
al->next = zone->subnet;
|
||||||
zone->subnet = al;
|
zone->subnet = al;
|
||||||
al->prefixlen = prefixlen;
|
al->prefixlen = prefixlen;
|
||||||
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
al->addr.addr6 = addr->in6.sin6_addr;
|
||||||
al->flags = ADDRLIST_IPV6;
|
al->flags = ADDRLIST_IPV6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -383,20 +369,18 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET)
|
if (addr->sa.sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
al->addr.addr.addr4 = addr->in.sin_addr;
|
al->addr.addr4 = addr->in.sin_addr;
|
||||||
al->flags = 0;
|
al->flags = 0;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
al->addr.addr.addr6 = addr->in6.sin6_addr;
|
al->addr.addr6 = addr->in6.sin6_addr;
|
||||||
al->flags = ADDRLIST_IPV6;
|
al->flags = ADDRLIST_IPV6;
|
||||||
/* Privacy addresses and addresses still undergoing DAD and deprecated addresses
|
/* Privacy addresses and addresses still undergoing DAD and deprecated addresses
|
||||||
don't appear in forward queries, but will in reverse ones. */
|
don't appear in forward queries, but will in reverse ones. */
|
||||||
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
|
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE_DEPRECATED | IFACE_TENTATIVE)))
|
||||||
al->flags |= ADDRLIST_REVONLY;
|
al->flags |= ADDRLIST_REVONLY;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -404,10 +388,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
/* check whether the interface IP has been added already
|
/* check whether the interface IP has been added already
|
||||||
we call this routine multiple times. */
|
we call this routine multiple times. */
|
||||||
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->index == if_index)
|
||||||
{
|
{
|
||||||
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
|
||||||
iface->found = 1; /* for garbage collection */
|
iface->found = 1; /* for garbage collection */
|
||||||
|
iface->netmask = netmask;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -435,14 +420,12 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (addr->sa.sa_family == AF_INET &&
|
if (addr->sa.sa_family == AF_INET &&
|
||||||
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
!iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
if (addr->sa.sa_family == AF_INET6 &&
|
||||||
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
|
!iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &auth_dns))
|
||||||
return 1;
|
return 1;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
/* No DHCP where we're doing auth DNS. */
|
/* No DHCP where we're doing auth DNS. */
|
||||||
@@ -501,7 +484,6 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
static int iface_allowed_v6(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)
|
||||||
@@ -529,7 +511,6 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
|
|||||||
|
|
||||||
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
|
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netmask, prefix, flags);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
static int iface_allowed_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)
|
||||||
@@ -552,7 +533,82 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
|||||||
|
|
||||||
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
|
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clean old interfaces no longer found.
|
||||||
|
*/
|
||||||
|
static void clean_interfaces()
|
||||||
|
{
|
||||||
|
struct irec *iface;
|
||||||
|
struct irec **up = &daemon->interfaces;
|
||||||
|
|
||||||
|
for (iface = *up; iface; iface = *up)
|
||||||
|
{
|
||||||
|
if (!iface->found && !iface->done)
|
||||||
|
{
|
||||||
|
*up = iface->next;
|
||||||
|
free(iface->name);
|
||||||
|
free(iface);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
up = &iface->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Release listener if no other interface needs it.
|
||||||
|
*
|
||||||
|
* @return 1 if released, 0 if still required
|
||||||
|
*/
|
||||||
|
static int release_listener(struct listener *l)
|
||||||
|
{
|
||||||
|
if (l->used > 1)
|
||||||
|
{
|
||||||
|
struct irec *iface;
|
||||||
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
|
if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
|
||||||
|
{
|
||||||
|
if (iface->found)
|
||||||
|
{
|
||||||
|
/* update listener to point to active interface instead */
|
||||||
|
if (!l->iface->found)
|
||||||
|
l->iface = iface;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
l->used--;
|
||||||
|
iface->done = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Someone is still using this listener, skip its deletion */
|
||||||
|
if (l->used > 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->iface->done)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
|
||||||
|
port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
|
||||||
|
my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
|
||||||
|
l->iface->name, l->iface->index, daemon->addrbuff, port);
|
||||||
|
/* In case it ever returns */
|
||||||
|
l->iface->done = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->fd != -1)
|
||||||
|
close(l->fd);
|
||||||
|
if (l->tcpfd != -1)
|
||||||
|
close(l->tcpfd);
|
||||||
|
if (l->tftpfd != -1)
|
||||||
|
close(l->tftpfd);
|
||||||
|
|
||||||
|
free(l);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int enumerate_interfaces(int reset)
|
int enumerate_interfaces(int reset)
|
||||||
{
|
{
|
||||||
static struct addrlist *spare = NULL;
|
static struct addrlist *spare = NULL;
|
||||||
@@ -633,9 +689,7 @@ int enumerate_interfaces(int reset)
|
|||||||
|
|
||||||
param.spare = spare;
|
param.spare = spare;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
|
ret = iface_enumerate(AF_INET6, ¶m, iface_allowed_v6);
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
ret = iface_enumerate(AF_INET, ¶m, iface_allowed_v4);
|
||||||
@@ -652,6 +706,7 @@ int enumerate_interfaces(int reset)
|
|||||||
in OPT_CLEVERBIND mode, that at listener will just disappear after
|
in OPT_CLEVERBIND mode, that at listener will just disappear after
|
||||||
a call to enumerate_interfaces, this is checked OK on all calls. */
|
a call to enumerate_interfaces, this is checked OK on all calls. */
|
||||||
struct listener *l, *tmp, **up;
|
struct listener *l, *tmp, **up;
|
||||||
|
int freed = 0;
|
||||||
|
|
||||||
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
|
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
|
||||||
{
|
{
|
||||||
@@ -659,25 +714,17 @@ int enumerate_interfaces(int reset)
|
|||||||
|
|
||||||
if (!l->iface || l->iface->found)
|
if (!l->iface || l->iface->found)
|
||||||
up = &l->next;
|
up = &l->next;
|
||||||
else
|
else if (release_listener(l))
|
||||||
{
|
{
|
||||||
*up = l->next;
|
*up = tmp;
|
||||||
|
freed = 1;
|
||||||
/* In case it ever returns */
|
|
||||||
l->iface->done = 0;
|
|
||||||
|
|
||||||
if (l->fd != -1)
|
|
||||||
close(l->fd);
|
|
||||||
if (l->tcpfd != -1)
|
|
||||||
close(l->tcpfd);
|
|
||||||
if (l->tftpfd != -1)
|
|
||||||
close(l->tftpfd);
|
|
||||||
|
|
||||||
free(l);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (freed)
|
||||||
|
clean_interfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
errno = errsave;
|
errno = errsave;
|
||||||
spare = param.spare;
|
spare = param.spare;
|
||||||
|
|
||||||
@@ -740,16 +787,19 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
|||||||
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
|
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_fd(fd))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
|
if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
|
||||||
goto err;
|
goto err;
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
|
if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (type == SOCK_STREAM)
|
if (type == SOCK_STREAM)
|
||||||
{
|
{
|
||||||
|
#ifdef TCP_FASTOPEN
|
||||||
|
int qlen = 5;
|
||||||
|
setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (listen(fd, TCP_BACKLOG) == -1)
|
if (listen(fd, TCP_BACKLOG) == -1)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@@ -767,15 +817,12 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else if (!set_ipv6pktinfo(fd))
|
else if (!set_ipv6pktinfo(fd))
|
||||||
goto err;
|
goto err;
|
||||||
#endif
|
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
int set_ipv6pktinfo(int fd)
|
int set_ipv6pktinfo(int fd)
|
||||||
{
|
{
|
||||||
int opt = 1;
|
int opt = 1;
|
||||||
@@ -802,12 +849,13 @@ int set_ipv6pktinfo(int fd)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
|
/* Find the interface on which a TCP connection arrived, if possible, or zero otherwise. */
|
||||||
int tcp_interface(int fd, int af)
|
int tcp_interface(int fd, int af)
|
||||||
{
|
{
|
||||||
|
(void)fd; /* suppress potential unused warning */
|
||||||
|
(void)af; /* suppress potential unused warning */
|
||||||
int if_index = 0;
|
int if_index = 0;
|
||||||
|
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
@@ -842,7 +890,6 @@ int tcp_interface(int fd, int af)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Only the RFC-2292 API has the ability to find the interface for TCP connections,
|
/* Only the RFC-2292 API has the ability to find the interface for TCP connections,
|
||||||
@@ -874,7 +921,6 @@ int tcp_interface(int fd, int af)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* IPV6 */
|
|
||||||
#endif /* Linux */
|
#endif /* Linux */
|
||||||
|
|
||||||
return if_index;
|
return if_index;
|
||||||
@@ -904,7 +950,6 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
|||||||
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
|
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
|
||||||
addr->in.sin_port = save;
|
addr->in.sin_port = save;
|
||||||
}
|
}
|
||||||
# ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
short save = addr->in6.sin6_port;
|
short save = addr->in6.sin6_port;
|
||||||
@@ -912,7 +957,6 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
|||||||
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
|
tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
|
||||||
addr->in6.sin6_port = save;
|
addr->in6.sin6_port = save;
|
||||||
}
|
}
|
||||||
# endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -920,10 +964,11 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
|
|||||||
{
|
{
|
||||||
l = safe_malloc(sizeof(struct listener));
|
l = safe_malloc(sizeof(struct listener));
|
||||||
l->next = NULL;
|
l->next = NULL;
|
||||||
l->family = addr->sa.sa_family;
|
|
||||||
l->fd = fd;
|
l->fd = fd;
|
||||||
l->tcpfd = tcpfd;
|
l->tcpfd = tcpfd;
|
||||||
l->tftpfd = tftpfd;
|
l->tftpfd = tftpfd;
|
||||||
|
l->addr = *addr;
|
||||||
|
l->used = 1;
|
||||||
l->iface = NULL;
|
l->iface = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -945,11 +990,10 @@ void create_wildcard_listeners(void)
|
|||||||
|
|
||||||
l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
# ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
addr.in6.sin6_len = sizeof(addr.in6);
|
addr.in6.sin6_len = sizeof(addr.in6);
|
||||||
# endif
|
#endif
|
||||||
addr.in6.sin6_family = AF_INET6;
|
addr.in6.sin6_family = AF_INET6;
|
||||||
addr.in6.sin6_addr = in6addr_any;
|
addr.in6.sin6_addr = in6addr_any;
|
||||||
addr.in6.sin6_port = htons(daemon->port);
|
addr.in6.sin6_port = htons(daemon->port);
|
||||||
@@ -959,25 +1003,52 @@ void create_wildcard_listeners(void)
|
|||||||
l->next = l6;
|
l->next = l6;
|
||||||
else
|
else
|
||||||
l = l6;
|
l = l6;
|
||||||
#endif
|
|
||||||
|
|
||||||
daemon->listeners = l;
|
daemon->listeners = l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct listener *find_listener(union mysockaddr *addr)
|
||||||
|
{
|
||||||
|
struct listener *l;
|
||||||
|
for (l = daemon->listeners; l; l = l->next)
|
||||||
|
if (sockaddr_isequal(&l->addr, addr))
|
||||||
|
return l;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void create_bound_listeners(int dienow)
|
void create_bound_listeners(int dienow)
|
||||||
{
|
{
|
||||||
struct listener *new;
|
struct listener *new;
|
||||||
struct irec *iface;
|
struct irec *iface;
|
||||||
struct iname *if_tmp;
|
struct iname *if_tmp;
|
||||||
|
struct listener *existing;
|
||||||
|
|
||||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||||
if (!iface->done && !iface->dad && iface->found &&
|
if (!iface->done && !iface->dad && iface->found)
|
||||||
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
|
|
||||||
{
|
{
|
||||||
new->iface = iface;
|
existing = find_listener(&iface->addr);
|
||||||
new->next = daemon->listeners;
|
if (existing)
|
||||||
daemon->listeners = new;
|
{
|
||||||
iface->done = 1;
|
iface->done = 1;
|
||||||
|
existing->used++; /* increase usage counter */
|
||||||
|
}
|
||||||
|
else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
|
||||||
|
{
|
||||||
|
new->iface = iface;
|
||||||
|
new->next = daemon->listeners;
|
||||||
|
daemon->listeners = new;
|
||||||
|
iface->done = 1;
|
||||||
|
|
||||||
|
/* Don't log the initial set of listen addresses created
|
||||||
|
at startup, since this is happening before the logging
|
||||||
|
system is initialised and the sign-on printed. */
|
||||||
|
if (!dienow)
|
||||||
|
{
|
||||||
|
int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
|
||||||
|
my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
|
||||||
|
iface->name, iface->index, daemon->addrbuff, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for --listen-address options that haven't been used because there's
|
/* Check for --listen-address options that haven't been used because there's
|
||||||
@@ -997,6 +1068,12 @@ void create_bound_listeners(int dienow)
|
|||||||
{
|
{
|
||||||
new->next = daemon->listeners;
|
new->next = daemon->listeners;
|
||||||
daemon->listeners = new;
|
daemon->listeners = new;
|
||||||
|
|
||||||
|
if (!dienow)
|
||||||
|
{
|
||||||
|
int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
|
||||||
|
my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1149,10 +1226,7 @@ int random_sock(int family)
|
|||||||
if (fix_fd(fd))
|
if (fix_fd(fd))
|
||||||
while(tries--)
|
while(tries--)
|
||||||
{
|
{
|
||||||
unsigned short port = rand16();
|
unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
|
||||||
|
|
||||||
if (daemon->min_port != 0 || daemon->max_port != MAX_PORT)
|
|
||||||
port = htons(daemon->min_port + (port % ((unsigned short)ports_avail)));
|
|
||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
{
|
{
|
||||||
@@ -1162,7 +1236,6 @@ int random_sock(int family)
|
|||||||
addr.in.sin_len = sizeof(struct sockaddr_in);
|
addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addr.in6.sin6_addr = in6addr_any;
|
addr.in6.sin6_addr = in6addr_any;
|
||||||
@@ -1171,7 +1244,6 @@ int random_sock(int family)
|
|||||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
|
if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
|
||||||
return fd;
|
return fd;
|
||||||
@@ -1187,7 +1259,7 @@ int random_sock(int family)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
|
||||||
{
|
{
|
||||||
union mysockaddr addr_copy = *addr;
|
union mysockaddr addr_copy = *addr;
|
||||||
|
|
||||||
@@ -1196,15 +1268,32 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
|||||||
{
|
{
|
||||||
if (addr_copy.sa.sa_family == AF_INET)
|
if (addr_copy.sa.sa_family == AF_INET)
|
||||||
addr_copy.in.sin_port = 0;
|
addr_copy.in.sin_port = 0;
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
addr_copy.in6.sin6_port = 0;
|
addr_copy.in6.sin6_port = 0;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
|
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!is_tcp && ifindex > 0)
|
||||||
|
{
|
||||||
|
#if defined(IP_UNICAST_IF)
|
||||||
|
if (addr_copy.sa.sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
uint32_t ifindex_opt = htonl(ifindex);
|
||||||
|
return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if defined (IPV6_UNICAST_IF)
|
||||||
|
if (addr_copy.sa.sa_family == AF_INET6)
|
||||||
|
{
|
||||||
|
uint32_t ifindex_opt = htonl(ifindex);
|
||||||
|
return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, sizeof(ifindex_opt)) == 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)intname; /* suppress potential unused warning */
|
||||||
#if defined(SO_BINDTODEVICE)
|
#if defined(SO_BINDTODEVICE)
|
||||||
if (intname[0] != 0 &&
|
if (intname[0] != 0 &&
|
||||||
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
|
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
|
||||||
@@ -1219,7 +1308,8 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|||||||
struct serverfd *sfd;
|
struct serverfd *sfd;
|
||||||
unsigned int ifindex = 0;
|
unsigned int ifindex = 0;
|
||||||
int errsave;
|
int errsave;
|
||||||
|
int opt = 1;
|
||||||
|
|
||||||
/* when using random ports, servers which would otherwise use
|
/* when using random ports, servers which would otherwise use
|
||||||
the INADDR_ANY/port0 socket have sfd set to NULL */
|
the INADDR_ANY/port0 socket have sfd set to NULL */
|
||||||
if (!daemon->osport && intname[0] == 0)
|
if (!daemon->osport && intname[0] == 0)
|
||||||
@@ -1231,12 +1321,10 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|||||||
addr->in.sin_port == htons(0))
|
addr->in.sin_port == htons(0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6 &&
|
if (addr->sa.sa_family == AF_INET6 &&
|
||||||
memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
|
memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
|
||||||
addr->in6.sin6_port == htons(0))
|
addr->in6.sin6_port == htons(0))
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (intname && strlen(intname) != 0)
|
if (intname && strlen(intname) != 0)
|
||||||
@@ -1259,20 +1347,22 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|||||||
free(sfd);
|
free(sfd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!local_bind(sfd->fd, addr, intname, 0) || !fix_fd(sfd->fd))
|
if ((addr->sa.sa_family == AF_INET6 && setsockopt(sfd->fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1) ||
|
||||||
|
!local_bind(sfd->fd, addr, intname, ifindex, 0) || !fix_fd(sfd->fd))
|
||||||
{
|
{
|
||||||
errsave = errno; /* save error from bind. */
|
errsave = errno; /* save error from bind/setsockopt. */
|
||||||
close(sfd->fd);
|
close(sfd->fd);
|
||||||
free(sfd);
|
free(sfd);
|
||||||
errno = errsave;
|
errno = errsave;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(sfd->interface, intname);
|
safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
|
||||||
sfd->source_addr = *addr;
|
sfd->source_addr = *addr;
|
||||||
sfd->next = daemon->sfds;
|
sfd->next = daemon->sfds;
|
||||||
sfd->ifindex = ifindex;
|
sfd->ifindex = ifindex;
|
||||||
|
sfd->preallocated = 0;
|
||||||
daemon->sfds = sfd;
|
daemon->sfds = sfd;
|
||||||
|
|
||||||
return sfd;
|
return sfd;
|
||||||
@@ -1283,6 +1373,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|||||||
void pre_allocate_sfds(void)
|
void pre_allocate_sfds(void)
|
||||||
{
|
{
|
||||||
struct server *srv;
|
struct server *srv;
|
||||||
|
struct serverfd *sfd;
|
||||||
|
|
||||||
if (daemon->query_port != 0)
|
if (daemon->query_port != 0)
|
||||||
{
|
{
|
||||||
@@ -1294,8 +1385,9 @@ void pre_allocate_sfds(void)
|
|||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
addr.in.sin_len = sizeof(struct sockaddr_in);
|
addr.in.sin_len = sizeof(struct sockaddr_in);
|
||||||
#endif
|
#endif
|
||||||
allocate_sfd(&addr, "");
|
if ((sfd = allocate_sfd(&addr, "")))
|
||||||
#ifdef HAVE_IPV6
|
sfd->preallocated = 1;
|
||||||
|
|
||||||
memset(&addr, 0, sizeof(addr));
|
memset(&addr, 0, sizeof(addr));
|
||||||
addr.in6.sin6_family = AF_INET6;
|
addr.in6.sin6_family = AF_INET6;
|
||||||
addr.in6.sin6_addr = in6addr_any;
|
addr.in6.sin6_addr = in6addr_any;
|
||||||
@@ -1303,8 +1395,8 @@ void pre_allocate_sfds(void)
|
|||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||||
#endif
|
#endif
|
||||||
allocate_sfd(&addr, "");
|
if ((sfd = allocate_sfd(&addr, "")))
|
||||||
#endif
|
sfd->preallocated = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (srv = daemon->servers; srv; srv = srv->next)
|
for (srv = daemon->servers; srv; srv = srv->next)
|
||||||
@@ -1313,7 +1405,7 @@ void pre_allocate_sfds(void)
|
|||||||
errno != 0 &&
|
errno != 0 &&
|
||||||
option_bool(OPT_NOWILD))
|
option_bool(OPT_NOWILD))
|
||||||
{
|
{
|
||||||
prettyprint_addr(&srv->source_addr, daemon->namebuff);
|
(void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
|
||||||
if (srv->interface[0] != 0)
|
if (srv->interface[0] != 0)
|
||||||
{
|
{
|
||||||
strcat(daemon->namebuff, " ");
|
strcat(daemon->namebuff, " ");
|
||||||
@@ -1437,7 +1529,7 @@ void add_update_server(int flags,
|
|||||||
serv->flags |= SERV_HAS_DOMAIN;
|
serv->flags |= SERV_HAS_DOMAIN;
|
||||||
|
|
||||||
if (interface)
|
if (interface)
|
||||||
strcpy(serv->interface, interface);
|
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
||||||
if (addr)
|
if (addr)
|
||||||
serv->addr = *addr;
|
serv->addr = *addr;
|
||||||
if (source_addr)
|
if (source_addr)
|
||||||
@@ -1456,16 +1548,10 @@ void check_servers(void)
|
|||||||
/* 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 (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
|
||||||
sfd->used = 0;
|
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
/* don't garbage collect pre-allocated sfds. */
|
||||||
/* Disable DNSSEC validation when using server=/domain/.... servers
|
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
||||||
unless there's a configured trust anchor. */
|
sfd->used = sfd->preallocated;
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
|
||||||
serv->flags |= SERV_DO_DNSSEC;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||||
{
|
{
|
||||||
@@ -1478,6 +1564,11 @@ void check_servers(void)
|
|||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
if (option_bool(OPT_DNSSEC_VALID))
|
||||||
{
|
{
|
||||||
|
if (!(serv->flags & SERV_FOR_NODOTS))
|
||||||
|
serv->flags |= SERV_DO_DNSSEC;
|
||||||
|
|
||||||
|
/* Disable DNSSEC validation when using server=/domain/.... servers
|
||||||
|
unless there's a configured trust anchor. */
|
||||||
if (serv->flags & SERV_HAS_DOMAIN)
|
if (serv->flags & SERV_HAS_DOMAIN)
|
||||||
{
|
{
|
||||||
struct ds_config *ds;
|
struct ds_config *ds;
|
||||||
@@ -1494,8 +1585,6 @@ void check_servers(void)
|
|||||||
if (!ds)
|
if (!ds)
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
serv->flags &= ~SERV_DO_DNSSEC;
|
||||||
}
|
}
|
||||||
else if (serv->flags & SERV_FOR_NODOTS)
|
|
||||||
serv->flags &= ~SERV_DO_DNSSEC;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1558,7 +1647,7 @@ void check_servers(void)
|
|||||||
{
|
{
|
||||||
count--;
|
count--;
|
||||||
if (++locals <= LOCALS_LOGGED)
|
if (++locals <= LOCALS_LOGGED)
|
||||||
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
|
my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
|
||||||
}
|
}
|
||||||
else if (serv->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);
|
||||||
@@ -1640,7 +1729,6 @@ int reload_servers(char *fname)
|
|||||||
source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
source_addr.in.sin_addr.s_addr = INADDR_ANY;
|
||||||
source_addr.in.sin_port = htons(daemon->query_port);
|
source_addr.in.sin_port = htons(daemon->query_port);
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int scope_index = 0;
|
int scope_index = 0;
|
||||||
@@ -1668,10 +1756,6 @@ int reload_servers(char *fname)
|
|||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#else /* IPV6 */
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
|
add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
|
||||||
gotone = 1;
|
gotone = 1;
|
||||||
|
|||||||
+993
-605
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
-16
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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,7 +288,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
|||||||
context->netid.next = &context->netid;
|
context->netid.next = &context->netid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!iface_enumerate(AF_INET6, &parm, add_prefixes))
|
/* If no link-local address then we can't advertise since source address of
|
||||||
|
advertisement must be link local address: RFC 4861 para 6.1.2. */
|
||||||
|
if (!iface_enumerate(AF_INET6, &parm, add_prefixes) ||
|
||||||
|
parm.link_pref_time == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Find smallest preferred time within address classes,
|
/* Find smallest preferred time within address classes,
|
||||||
@@ -407,12 +410,12 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
|||||||
if (ra_param)
|
if (ra_param)
|
||||||
mtu = ra_param->mtu;
|
mtu = ra_param->mtu;
|
||||||
#ifdef HAVE_LINUX_NETWORK
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
/* Note that IPv6 MTU is not neccessarily the same as the IPv4 MTU
|
/* Note that IPv6 MTU is not necessarily the same as the IPv4 MTU
|
||||||
available from SIOCGIFMTU */
|
available from SIOCGIFMTU */
|
||||||
if (mtu == 0)
|
if (mtu == 0)
|
||||||
{
|
{
|
||||||
char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
|
char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
|
||||||
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? : iface_name);
|
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? mtu_name : iface_name);
|
||||||
if ((f = fopen(daemon->namebuff, "r")))
|
if ((f = fopen(daemon->namebuff, "r")))
|
||||||
{
|
{
|
||||||
if (fgets(daemon->namebuff, MAXDNAME, f))
|
if (fgets(daemon->namebuff, MAXDNAME, f))
|
||||||
@@ -623,8 +626,11 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
|||||||
real_prefix = context->prefix;
|
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 the lease time has been left as default, don't
|
||||||
|
use that as a floor. */
|
||||||
|
if ((context->flags & CONTEXT_SETLEASE) &&
|
||||||
|
time > context->lease_time)
|
||||||
{
|
{
|
||||||
time = context->lease_time;
|
time = context->lease_time;
|
||||||
if (time < ((unsigned int)(3 * param->adv_interval)))
|
if (time < ((unsigned int)(3 * param->adv_interval)))
|
||||||
@@ -888,11 +894,21 @@ static int iface_search(struct in6_addr *local, int prefix,
|
|||||||
{
|
{
|
||||||
struct search_param *param = vparam;
|
struct search_param *param = vparam;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
struct iname *tmp;
|
||||||
|
|
||||||
(void)scope;
|
(void)scope;
|
||||||
(void)preferred;
|
(void)preferred;
|
||||||
(void)valid;
|
(void)valid;
|
||||||
|
|
||||||
|
/* ignore interfaces we're not doing DHCP on. */
|
||||||
|
if (!indextoname(daemon->icmp6fd, if_index, param->name) ||
|
||||||
|
!iface_check(AF_LOCAL, NULL, param->name, NULL))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
|
||||||
|
if (tmp->name && wildcard_match(tmp->name, param->name))
|
||||||
|
return 1;
|
||||||
|
|
||||||
for (context = daemon->dhcp6; context; context = context->next)
|
for (context = daemon->dhcp6; context; context = context->next)
|
||||||
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
if (!(context->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
||||||
prefix <= context->prefix &&
|
prefix <= context->prefix &&
|
||||||
@@ -904,17 +920,9 @@ static int iface_search(struct in6_addr *local, int prefix,
|
|||||||
/* found an interface that's overdue for RA determine new
|
/* found an interface that's overdue for RA determine new
|
||||||
timeout value and arrange for RA to be sent unless interface is
|
timeout value and arrange for RA to be sent unless interface is
|
||||||
still doing DAD.*/
|
still doing DAD.*/
|
||||||
|
|
||||||
if (!(flags & IFACE_TENTATIVE))
|
if (!(flags & IFACE_TENTATIVE))
|
||||||
param->iface = if_index;
|
param->iface = if_index;
|
||||||
|
|
||||||
/* should never fail */
|
|
||||||
if (!indextoname(daemon->icmp6fd, if_index, param->name))
|
|
||||||
{
|
|
||||||
param->iface = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_timeout(context, param->name, param->now);
|
new_timeout(context, param->name, param->now);
|
||||||
|
|
||||||
/* zero timers for other contexts on the same subnet, so they don't timeout
|
/* zero timers for other contexts on the same subnet, so they don't timeout
|
||||||
|
|||||||
+362
-289
File diff suppressed because it is too large.
Load diff
+146
-58
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -75,7 +75,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
struct dhcp_vendor *vendor;
|
struct dhcp_vendor *vendor;
|
||||||
struct dhcp_mac *mac;
|
struct dhcp_mac *mac;
|
||||||
struct dhcp_netid_list *id_list;
|
struct dhcp_netid_list *id_list;
|
||||||
int clid_len = 0, ignore = 0, do_classes = 0, selecting = 0, pxearch = -1;
|
int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
|
||||||
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
||||||
unsigned char *end = (unsigned char *)(mess + 1);
|
unsigned char *end = (unsigned char *)(mess + 1);
|
||||||
unsigned char *real_end = (unsigned char *)(mess + 1);
|
unsigned char *real_end = (unsigned char *)(mess + 1);
|
||||||
@@ -234,7 +234,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
subnet_addr = option_addr(opt);
|
subnet_addr = option_addr(opt);
|
||||||
|
|
||||||
/* If there is no client identifier option, use the hardware address */
|
/* If there is no client identifier option, use the hardware address */
|
||||||
if ((opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
|
if (!option_bool(OPT_IGNORE_CLID) && (opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
|
||||||
{
|
{
|
||||||
clid_len = option_len(opt);
|
clid_len = option_len(opt);
|
||||||
clid = option_ptr(opt, 0);
|
clid = option_ptr(opt, 0);
|
||||||
@@ -274,8 +274,9 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
|
if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
|
||||||
{
|
{
|
||||||
struct dhcp_context *context_tmp, *context_new = NULL;
|
struct dhcp_context *context_tmp, *context_new = NULL;
|
||||||
|
struct shared_network *share = NULL;
|
||||||
struct in_addr addr;
|
struct in_addr addr;
|
||||||
int force = 0;
|
int force = 0, via_relay = 0;
|
||||||
|
|
||||||
if (subnet_addr.s_addr)
|
if (subnet_addr.s_addr)
|
||||||
{
|
{
|
||||||
@@ -286,6 +287,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
{
|
{
|
||||||
addr = mess->giaddr;
|
addr = mess->giaddr;
|
||||||
force = 1;
|
force = 1;
|
||||||
|
via_relay = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -302,42 +304,65 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!context_new)
|
if (!context_new)
|
||||||
for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
|
{
|
||||||
{
|
for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
|
||||||
struct in_addr netmask = context_tmp->netmask;
|
{
|
||||||
|
struct in_addr netmask = context_tmp->netmask;
|
||||||
|
|
||||||
|
/* guess the netmask for relayed networks */
|
||||||
|
if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
|
||||||
|
{
|
||||||
|
if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
|
||||||
|
netmask.s_addr = htonl(0xff000000);
|
||||||
|
else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
|
||||||
|
netmask.s_addr = htonl(0xffff0000);
|
||||||
|
else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
|
||||||
|
netmask.s_addr = htonl(0xffffff00);
|
||||||
|
}
|
||||||
|
|
||||||
/* guess the netmask for relayed networks */
|
/* check to see is a context is OK because of a shared address on
|
||||||
if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
|
the relayed subnet. */
|
||||||
{
|
if (via_relay)
|
||||||
if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
|
for (share = daemon->shared_networks; share; share = share->next)
|
||||||
netmask.s_addr = htonl(0xff000000);
|
{
|
||||||
else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
|
#ifdef HAVE_DHCP6
|
||||||
netmask.s_addr = htonl(0xffff0000);
|
if (share->shared_addr.s_addr == 0)
|
||||||
else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
|
continue;
|
||||||
netmask.s_addr = htonl(0xffffff00);
|
#endif
|
||||||
}
|
if (share->if_index != 0 ||
|
||||||
|
share->match_addr.s_addr != mess->giaddr.s_addr)
|
||||||
/* This section fills in context mainly when a client which is on a remote (relayed)
|
continue;
|
||||||
network renews a lease without using the relay, after dnsmasq has restarted. */
|
|
||||||
if (netmask.s_addr != 0 &&
|
if (netmask.s_addr != 0 &&
|
||||||
is_same_net(addr, context_tmp->start, netmask) &&
|
is_same_net(share->shared_addr, context_tmp->start, netmask) &&
|
||||||
is_same_net(addr, context_tmp->end, netmask))
|
is_same_net(share->shared_addr, context_tmp->end, netmask))
|
||||||
{
|
break;
|
||||||
context_tmp->netmask = netmask;
|
}
|
||||||
if (context_tmp->local.s_addr == 0)
|
|
||||||
context_tmp->local = fallback;
|
/* This section fills in context mainly when a client which is on a remote (relayed)
|
||||||
if (context_tmp->router.s_addr == 0)
|
network renews a lease without using the relay, after dnsmasq has restarted. */
|
||||||
context_tmp->router = mess->giaddr;
|
if (share ||
|
||||||
|
(netmask.s_addr != 0 &&
|
||||||
/* fill in missing broadcast addresses for relayed ranges */
|
is_same_net(addr, context_tmp->start, netmask) &&
|
||||||
if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
|
is_same_net(addr, context_tmp->end, netmask)))
|
||||||
context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
|
{
|
||||||
|
context_tmp->netmask = netmask;
|
||||||
context_tmp->current = context_new;
|
if (context_tmp->local.s_addr == 0)
|
||||||
context_new = context_tmp;
|
context_tmp->local = fallback;
|
||||||
}
|
if (context_tmp->router.s_addr == 0 && !share)
|
||||||
}
|
context_tmp->router = mess->giaddr;
|
||||||
|
|
||||||
|
/* fill in missing broadcast addresses for relayed ranges */
|
||||||
|
if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
|
||||||
|
context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
|
||||||
|
|
||||||
|
context_tmp->current = context_new;
|
||||||
|
context_new = context_tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (context_new || force)
|
if (context_new || force)
|
||||||
context = context_new;
|
context = context_new;
|
||||||
}
|
}
|
||||||
@@ -388,7 +413,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
|
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
|
||||||
{
|
{
|
||||||
elen = option_uint(opt, o2, 1);
|
elen = option_uint(opt, o2, 1);
|
||||||
if ((o2 + elen + 1 <= option_len(opt)) &&
|
if ((o2 + elen + 1 <= (unsigned)option_len(opt)) &&
|
||||||
(match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
|
(match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -479,7 +504,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
mess->op = BOOTREPLY;
|
mess->op = BOOTREPLY;
|
||||||
|
|
||||||
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
|
config = find_config(daemon->dhcp_conf, context, clid, clid_len,
|
||||||
mess->chaddr, mess->hlen, mess->htype, NULL);
|
mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid));
|
||||||
|
|
||||||
/* set "known" tag for known hosts */
|
/* set "known" tag for known hosts */
|
||||||
if (config)
|
if (config)
|
||||||
@@ -489,7 +514,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
netid = &known_id;
|
netid = &known_id;
|
||||||
}
|
}
|
||||||
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
|
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
|
||||||
mess->chaddr, mess->hlen, mess->htype, NULL))
|
mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid)))
|
||||||
{
|
{
|
||||||
known_id.net = "known-othernet";
|
known_id.net = "known-othernet";
|
||||||
known_id.next = netid;
|
known_id.next = netid;
|
||||||
@@ -626,6 +651,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_BOOTP]++;
|
||||||
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
|
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
|
||||||
|
|
||||||
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
||||||
@@ -699,8 +725,37 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
client_hostname = daemon->dhcp_buff;
|
client_hostname = daemon->dhcp_buff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client_hostname && option_bool(OPT_LOG_OPTS))
|
if (client_hostname)
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
|
{
|
||||||
|
struct dhcp_match_name *m;
|
||||||
|
size_t nl = strlen(client_hostname);
|
||||||
|
|
||||||
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
|
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
|
||||||
|
for (m = daemon->dhcp_name_match; m; m = m->next)
|
||||||
|
{
|
||||||
|
size_t ml = strlen(m->name);
|
||||||
|
char save = 0;
|
||||||
|
|
||||||
|
if (nl < ml)
|
||||||
|
continue;
|
||||||
|
if (nl > ml)
|
||||||
|
{
|
||||||
|
save = client_hostname[ml];
|
||||||
|
client_hostname[ml] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname_isequal(client_hostname, m->name) &&
|
||||||
|
(save == 0 || m->wildcard))
|
||||||
|
{
|
||||||
|
m->netid->next = netid;
|
||||||
|
netid = m->netid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save != 0)
|
||||||
|
client_hostname[ml] = save;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (have_config(config, CONFIG_NAME))
|
if (have_config(config, CONFIG_NAME))
|
||||||
{
|
{
|
||||||
@@ -718,6 +773,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (strlen(client_hostname) != 0)
|
if (strlen(client_hostname) != 0)
|
||||||
{
|
{
|
||||||
hostname = client_hostname;
|
hostname = client_hostname;
|
||||||
|
|
||||||
if (!config)
|
if (!config)
|
||||||
{
|
{
|
||||||
/* Search again now we have a hostname.
|
/* Search again now we have a hostname.
|
||||||
@@ -725,7 +781,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
to avoid impersonation by name. */
|
to avoid impersonation by name. */
|
||||||
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
|
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
|
||||||
mess->chaddr, mess->hlen,
|
mess->chaddr, mess->hlen,
|
||||||
mess->htype, hostname);
|
mess->htype, hostname, run_tag_if(netid));
|
||||||
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
||||||
{
|
{
|
||||||
config = new;
|
config = new;
|
||||||
@@ -909,7 +965,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (!workaround && boot)
|
if (!workaround && boot)
|
||||||
{
|
{
|
||||||
/* Provide the bootfile here, for gPXE, and in case we have no menu items
|
/* Provide the bootfile here, for iPXE, and in case we have no menu items
|
||||||
and set discovery_control = 8 */
|
and set discovery_control = 8 */
|
||||||
if (boot->next_server.s_addr)
|
if (boot->next_server.s_addr)
|
||||||
mess->siaddr = boot->next_server;
|
mess->siaddr = boot->next_server;
|
||||||
@@ -917,7 +973,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
|
mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
|
||||||
|
|
||||||
if (boot->file)
|
if (boot->file)
|
||||||
strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
||||||
}
|
}
|
||||||
|
|
||||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
||||||
@@ -928,6 +984,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if ((pxe && !workaround) || !redirect4011)
|
if ((pxe && !workaround) || !redirect4011)
|
||||||
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->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);
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_PXE]++;
|
||||||
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));
|
||||||
if (!ignore)
|
if (!ignore)
|
||||||
@@ -962,6 +1019,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPDECLINE]++;
|
||||||
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
|
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
|
||||||
|
|
||||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||||
@@ -994,6 +1052,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
else
|
else
|
||||||
message = _("unknown lease");
|
message = _("unknown lease");
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPRELEASE]++;
|
||||||
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1060,6 +1119,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
message = _("no address available");
|
message = _("no address available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPDISCOVER]++;
|
||||||
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
|
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||||
|
|
||||||
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
|
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
|
||||||
@@ -1073,6 +1133,14 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
log_tags(tagif_netid, ntohl(mess->xid));
|
log_tags(tagif_netid, ntohl(mess->xid));
|
||||||
apply_delay(mess->xid, recvtime, tagif_netid);
|
apply_delay(mess->xid, recvtime, tagif_netid);
|
||||||
|
|
||||||
|
if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
|
||||||
|
{
|
||||||
|
rapid_commit = 1;
|
||||||
|
goto rapid_commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPOFFER]++;
|
||||||
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||||
|
|
||||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||||
@@ -1085,7 +1153,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
|
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);
|
||||||
|
|
||||||
|
|
||||||
case DHCPREQUEST:
|
case DHCPREQUEST:
|
||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1183,9 +1252,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
fuzz = rand16();
|
fuzz = rand16();
|
||||||
mess->yiaddr = mess->ciaddr;
|
mess->yiaddr = mess->ciaddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPREQUEST]++;
|
||||||
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||||
|
|
||||||
|
rapid_commit:
|
||||||
if (!message)
|
if (!message)
|
||||||
{
|
{
|
||||||
struct dhcp_config *addr_config;
|
struct dhcp_config *addr_config;
|
||||||
@@ -1256,7 +1327,12 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
if (message)
|
if (message)
|
||||||
{
|
{
|
||||||
log_packet("DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
|
||||||
|
log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||||
|
|
||||||
|
/* rapid commit case: lease allocate failed but don't send DHCPNAK */
|
||||||
|
if (rapid_commit)
|
||||||
|
return 0;
|
||||||
|
|
||||||
mess->yiaddr.s_addr = 0;
|
mess->yiaddr.s_addr = 0;
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
@@ -1413,13 +1489,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
else
|
else
|
||||||
override = lease->override;
|
override = lease->override;
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPACK]++;
|
||||||
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||||
|
|
||||||
clear_packet(mess, end);
|
clear_packet(mess, end);
|
||||||
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);
|
||||||
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
|
if (rapid_commit)
|
||||||
|
option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
|
||||||
|
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, time, fuzz);
|
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1429,6 +1508,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||||
message = _("ignored");
|
message = _("ignored");
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPINFORM]++;
|
||||||
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
|
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
|
||||||
|
|
||||||
if (message || mess->ciaddr.s_addr == 0)
|
if (message || mess->ciaddr.s_addr == 0)
|
||||||
@@ -1455,6 +1535,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
|||||||
|
|
||||||
log_tags(tagif_netid, ntohl(mess->xid));
|
log_tags(tagif_netid, ntohl(mess->xid));
|
||||||
|
|
||||||
|
daemon->metrics[METRIC_DHCPACK]++;
|
||||||
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||||
|
|
||||||
if (lease)
|
if (lease)
|
||||||
@@ -1621,6 +1702,13 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
|||||||
daemon->namebuff,
|
daemon->namebuff,
|
||||||
string ? string : "",
|
string ? string : "",
|
||||||
err ? err : "");
|
err ? err : "");
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
if (!strcmp(type, "DHCPACK"))
|
||||||
|
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
||||||
|
else if (!strcmp(type, "DHCPRELEASE"))
|
||||||
|
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void log_options(unsigned char *start, u32 xid)
|
static void log_options(unsigned char *start, u32 xid)
|
||||||
@@ -2284,7 +2372,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
/* See if we can send the boot stuff as options.
|
/* See if we can send the boot stuff as options.
|
||||||
To do this we need a requested option list, BOOTP
|
To do this we need a requested option list, BOOTP
|
||||||
and very old DHCP clients won't have this, we also
|
and very old DHCP clients won't have this, we also
|
||||||
provide an manual option to disable it.
|
provide a manual option to disable it.
|
||||||
Some PXE ROMs have bugs (surprise!) and need zero-terminated
|
Some PXE ROMs have bugs (surprise!) and need zero-terminated
|
||||||
names, so we always send those. */
|
names, so we always send those. */
|
||||||
if ((boot = find_boot(tagif)))
|
if ((boot = find_boot(tagif)))
|
||||||
@@ -2296,7 +2384,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
in_list(req_options, OPTION_SNAME))
|
in_list(req_options, OPTION_SNAME))
|
||||||
option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
|
option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
|
||||||
else
|
else
|
||||||
strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
|
safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boot->file)
|
if (boot->file)
|
||||||
@@ -2306,7 +2394,7 @@ static void do_options(struct dhcp_context *context,
|
|||||||
in_list(req_options, OPTION_FILENAME))
|
in_list(req_options, OPTION_FILENAME))
|
||||||
option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
|
option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
|
||||||
else
|
else
|
||||||
strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (boot->next_server.s_addr)
|
if (boot->next_server.s_addr)
|
||||||
@@ -2323,14 +2411,14 @@ static void do_options(struct dhcp_context *context,
|
|||||||
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
|
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
|
||||||
(opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
|
(opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
|
||||||
{
|
{
|
||||||
strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
|
safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
|
||||||
done_file = 1;
|
done_file = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
|
if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
|
||||||
(opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
|
(opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
|
||||||
{
|
{
|
||||||
strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
|
safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
|
||||||
done_server = 1;
|
done_server = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+272
-263
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -21,19 +21,16 @@
|
|||||||
|
|
||||||
struct state {
|
struct state {
|
||||||
unsigned char *clid;
|
unsigned char *clid;
|
||||||
int clid_len, iaid, ia_type, interface, hostname_auth, lease_allocate;
|
int clid_len, ia_type, interface, hostname_auth, lease_allocate;
|
||||||
char *client_hostname, *hostname, *domain, *send_domain;
|
char *client_hostname, *hostname, *domain, *send_domain;
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
|
struct in6_addr *link_address, *fallback, *ll_addr, *ula_addr;
|
||||||
unsigned int xid, fqdn_flags;
|
unsigned int xid, fqdn_flags, iaid;
|
||||||
char *iface_name;
|
char *iface_name;
|
||||||
void *packet_options, *end;
|
void *packet_options, *end;
|
||||||
struct dhcp_netid *tags, *context_tags;
|
struct dhcp_netid *tags, *context_tags;
|
||||||
unsigned char mac[DHCP_CHADDR_MAX];
|
unsigned char mac[DHCP_CHADDR_MAX];
|
||||||
unsigned int mac_len, mac_type;
|
unsigned int mac_len, mac_type;
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
struct prefix_class *send_prefix_class;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||||
@@ -49,12 +46,11 @@ static void get_context_tag(struct state *state, struct dhcp_context *context);
|
|||||||
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
|
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option);
|
||||||
static int build_ia(struct state *state, int *t1cntr);
|
static int build_ia(struct state *state, int *t1cntr);
|
||||||
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
|
static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz);
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context);
|
|
||||||
#endif
|
|
||||||
static void mark_context_used(struct state *state, struct in6_addr *addr);
|
static void mark_context_used(struct state *state, struct in6_addr *addr);
|
||||||
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
|
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr);
|
||||||
static int check_address(struct state *state, struct in6_addr *addr);
|
static int check_address(struct state *state, struct in6_addr *addr);
|
||||||
|
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now);
|
||||||
|
static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr);
|
||||||
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
|
static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option,
|
||||||
unsigned int *min_time, struct in6_addr *addr, time_t now);
|
unsigned int *min_time, struct in6_addr *addr, time_t now);
|
||||||
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
|
static void update_leases(struct state *state, struct dhcp_context *context, struct in6_addr *addr, unsigned int lease_time, time_t now);
|
||||||
@@ -134,21 +130,41 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct dhcp_context *c;
|
struct dhcp_context *c;
|
||||||
|
struct shared_network *share = NULL;
|
||||||
state->context = NULL;
|
state->context = NULL;
|
||||||
|
|
||||||
if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
|
if (!IN6_IS_ADDR_LOOPBACK(state->link_address) &&
|
||||||
!IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
|
!IN6_IS_ADDR_LINKLOCAL(state->link_address) &&
|
||||||
!IN6_IS_ADDR_MULTICAST(state->link_address))
|
!IN6_IS_ADDR_MULTICAST(state->link_address))
|
||||||
for (c = daemon->dhcp6; c; c = c->next)
|
for (c = daemon->dhcp6; c; c = c->next)
|
||||||
if ((c->flags & CONTEXT_DHCP) &&
|
{
|
||||||
!(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
for (share = daemon->shared_networks; share; share = share->next)
|
||||||
is_same_net6(state->link_address, &c->start6, c->prefix) &&
|
{
|
||||||
is_same_net6(state->link_address, &c->end6, c->prefix))
|
if (share->shared_addr.s_addr != 0)
|
||||||
{
|
continue;
|
||||||
c->preferred = c->valid = 0xffffffff;
|
|
||||||
c->current = state->context;
|
if (share->if_index != 0 ||
|
||||||
state->context = c;
|
!IN6_ARE_ADDR_EQUAL(state->link_address, &share->match_addr6))
|
||||||
}
|
continue;
|
||||||
|
|
||||||
|
if ((c->flags & CONTEXT_DHCP) &&
|
||||||
|
!(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
||||||
|
is_same_net6(&share->shared_addr6, &c->start6, c->prefix) &&
|
||||||
|
is_same_net6(&share->shared_addr6, &c->end6, c->prefix))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (share ||
|
||||||
|
((c->flags & CONTEXT_DHCP) &&
|
||||||
|
!(c->flags & (CONTEXT_TEMPLATE | CONTEXT_OLD)) &&
|
||||||
|
is_same_net6(state->link_address, &c->start6, c->prefix) &&
|
||||||
|
is_same_net6(state->link_address, &c->end6, c->prefix)))
|
||||||
|
{
|
||||||
|
c->preferred = c->valid = 0xffffffff;
|
||||||
|
c->current = state->context;
|
||||||
|
state->context = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!state->context)
|
if (!state->context)
|
||||||
{
|
{
|
||||||
@@ -216,24 +232,28 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
|||||||
|
|
||||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||||
{
|
{
|
||||||
if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
|
if (opt6_ptr(opt, 0) + opt6_len(opt) > end)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
int o = new_opt6(opt6_type(opt));
|
/* Don't copy MAC address into reply. */
|
||||||
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
if (opt6_type(opt) != OPTION6_CLIENT_MAC)
|
||||||
{
|
{
|
||||||
struct in6_addr align;
|
int o = new_opt6(opt6_type(opt));
|
||||||
/* the packet data is unaligned, copy to aligned storage */
|
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||||
memcpy(&align, inbuff + 2, IN6ADDRSZ);
|
{
|
||||||
state->link_address = &align;
|
struct in6_addr align;
|
||||||
/* zero is_unicast since that is now known to refer to the
|
/* the packet data is unaligned, copy to aligned storage */
|
||||||
relayed packet, not the original sent by the client */
|
memcpy(&align, inbuff + 2, IN6ADDRSZ);
|
||||||
if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
|
state->link_address = &align;
|
||||||
return 0;
|
/* zero is_unicast since that is now known to refer to the
|
||||||
|
relayed packet, not the original sent by the client */
|
||||||
|
if (!dhcp6_maybe_relay(state, opt6_ptr(opt, 0), opt6_len(opt), client_addr, 0, now))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||||
|
end_opt6(o);
|
||||||
}
|
}
|
||||||
else if (opt6_type(opt) != OPTION6_CLIENT_MAC)
|
|
||||||
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
|
||||||
end_opt6(o);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -252,10 +272,6 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
struct dhcp_context *context_tmp;
|
struct dhcp_context *context_tmp;
|
||||||
struct dhcp_mac *mac_opt;
|
struct dhcp_mac *mac_opt;
|
||||||
unsigned int ignore = 0;
|
unsigned int ignore = 0;
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
struct prefix_class *p;
|
|
||||||
int dump_all_prefix_classes = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
state->packet_options = inbuff + 4;
|
state->packet_options = inbuff + 4;
|
||||||
state->end = inbuff + sz;
|
state->end = inbuff + sz;
|
||||||
@@ -269,9 +285,6 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
state->hostname = NULL;
|
state->hostname = NULL;
|
||||||
state->client_hostname = NULL;
|
state->client_hostname = NULL;
|
||||||
state->fqdn_flags = 0x01; /* default to send if we receive no FQDN option */
|
state->fqdn_flags = 0x01; /* default to send if we receive no FQDN option */
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
state->send_prefix_class = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* set tag with name == interface */
|
/* set tag with name == interface */
|
||||||
iface_id.net = state->iface_name;
|
iface_id.net = state->iface_name;
|
||||||
@@ -477,39 +490,66 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
|
|
||||||
if (legal_hostname(daemon->dhcp_buff))
|
if (legal_hostname(daemon->dhcp_buff))
|
||||||
{
|
{
|
||||||
|
struct dhcp_match_name *m;
|
||||||
|
size_t nl = strlen(daemon->dhcp_buff);
|
||||||
|
|
||||||
state->client_hostname = daemon->dhcp_buff;
|
state->client_hostname = daemon->dhcp_buff;
|
||||||
|
|
||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname);
|
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), state->xid, state->client_hostname);
|
||||||
|
|
||||||
|
for (m = daemon->dhcp_name_match; m; m = m->next)
|
||||||
|
{
|
||||||
|
size_t ml = strlen(m->name);
|
||||||
|
char save = 0;
|
||||||
|
|
||||||
|
if (nl < ml)
|
||||||
|
continue;
|
||||||
|
if (nl > ml)
|
||||||
|
{
|
||||||
|
save = state->client_hostname[ml];
|
||||||
|
state->client_hostname[ml] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hostname_isequal(state->client_hostname, m->name) &&
|
||||||
|
(save == 0 || m->wildcard))
|
||||||
|
{
|
||||||
|
m->netid->next = state->tags;
|
||||||
|
state->tags = m->netid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save != 0)
|
||||||
|
state->client_hostname[ml] = save;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->clid)
|
if (state->clid &&
|
||||||
|
(config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len,
|
||||||
|
state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags))) &&
|
||||||
|
have_config(config, CONFIG_NAME))
|
||||||
{
|
{
|
||||||
config = find_config(daemon->dhcp_conf, state->context, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL);
|
state->hostname = config->hostname;
|
||||||
|
state->domain = config->domain;
|
||||||
|
state->hostname_auth = 1;
|
||||||
|
}
|
||||||
|
else if (state->client_hostname)
|
||||||
|
{
|
||||||
|
state->domain = strip_hostname(state->client_hostname);
|
||||||
|
|
||||||
if (have_config(config, CONFIG_NAME))
|
if (strlen(state->client_hostname) != 0)
|
||||||
{
|
{
|
||||||
state->hostname = config->hostname;
|
state->hostname = state->client_hostname;
|
||||||
state->domain = config->domain;
|
|
||||||
state->hostname_auth = 1;
|
|
||||||
}
|
|
||||||
else if (state->client_hostname)
|
|
||||||
{
|
|
||||||
state->domain = strip_hostname(state->client_hostname);
|
|
||||||
|
|
||||||
if (strlen(state->client_hostname) != 0)
|
if (!config)
|
||||||
{
|
{
|
||||||
state->hostname = state->client_hostname;
|
/* Search again now we have a hostname.
|
||||||
if (!config)
|
Only accept configs without CLID here, (it won't match)
|
||||||
{
|
to avoid impersonation by name. */
|
||||||
/* Search again now we have a hostname.
|
struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname, run_tag_if(state->tags));
|
||||||
Only accept configs without CLID here, (it won't match)
|
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
||||||
to avoid impersonation by name. */
|
config = new;
|
||||||
struct dhcp_config *new = find_config(daemon->dhcp_conf, state->context, NULL, 0, NULL, 0, 0, state->hostname);
|
|
||||||
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
|
||||||
config = new;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -533,38 +573,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
ignore = 1;
|
ignore = 1;
|
||||||
}
|
}
|
||||||
else if (state->clid &&
|
else if (state->clid &&
|
||||||
find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL))
|
find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len,
|
||||||
|
state->mac, state->mac_len, state->mac_type, NULL, run_tag_if(state->tags)))
|
||||||
{
|
{
|
||||||
known_id.net = "known-othernet";
|
known_id.net = "known-othernet";
|
||||||
known_id.next = state->tags;
|
known_id.next = state->tags;
|
||||||
state->tags = &known_id;
|
state->tags = &known_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
|
|
||||||
if (daemon->prefix_classes && (msg_type == DHCP6SOLICIT || msg_type == DHCP6REQUEST))
|
|
||||||
{
|
|
||||||
void *oro;
|
|
||||||
|
|
||||||
if ((oro = opt6_find(state->packet_options, state->end, OPTION6_ORO, 0)))
|
|
||||||
for (i = 0; i < opt6_len(oro) - 1; i += 2)
|
|
||||||
if (opt6_uint(oro, i, 2) == OPTION6_PREFIX_CLASS)
|
|
||||||
{
|
|
||||||
dump_all_prefix_classes = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg_type != DHCP6SOLICIT || dump_all_prefix_classes)
|
|
||||||
/* Add the tags associated with prefix classes so we can use the DHCP ranges.
|
|
||||||
Not done for SOLICIT as we add them one-at-time. */
|
|
||||||
for (p = daemon->prefix_classes; p ; p = p->next)
|
|
||||||
{
|
|
||||||
p->tag.next = state->tags;
|
|
||||||
state->tags = &p->tag;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tagif = run_tag_if(state->tags);
|
tagif = run_tag_if(state->tags);
|
||||||
|
|
||||||
/* if all the netids in the ignore list are present, ignore this client */
|
/* if all the netids in the ignore list are present, ignore this client */
|
||||||
@@ -639,9 +655,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
int plain_range = 1;
|
int plain_range = 1;
|
||||||
u32 lease_time;
|
u32 lease_time;
|
||||||
struct dhcp_lease *ltmp;
|
struct dhcp_lease *ltmp;
|
||||||
struct in6_addr *req_addr;
|
struct in6_addr req_addr, addr;
|
||||||
struct in6_addr addr;
|
|
||||||
|
|
||||||
if (!check_ia(state, opt, &ia_end, &ia_option))
|
if (!check_ia(state, opt, &ia_end, &ia_option))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -649,93 +664,36 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
for (c = state->context; c; c = c->current)
|
for (c = state->context; c; c = c->current)
|
||||||
c->flags &= ~CONTEXT_USED;
|
c->flags &= ~CONTEXT_USED;
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
if (daemon->prefix_classes && state->ia_type == OPTION6_IA_NA)
|
|
||||||
{
|
|
||||||
void *prefix_opt;
|
|
||||||
int prefix_class;
|
|
||||||
|
|
||||||
if (dump_all_prefix_classes)
|
|
||||||
/* OPTION_PREFIX_CLASS in ORO, send addresses in all prefix classes */
|
|
||||||
plain_range = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((prefix_opt = opt6_find(opt6_ptr(opt, 12), ia_end, OPTION6_PREFIX_CLASS, 2)))
|
|
||||||
{
|
|
||||||
|
|
||||||
prefix_class = opt6_uint(prefix_opt, 0, 2);
|
|
||||||
|
|
||||||
for (p = daemon->prefix_classes; p ; p = p->next)
|
|
||||||
if (p->class == prefix_class)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!p)
|
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("unknown prefix-class %d"), prefix_class);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* add tag to list, and exclude undecorated dhcp-ranges */
|
|
||||||
p->tag.next = state->tags;
|
|
||||||
solicit_tags = run_tag_if(&p->tag);
|
|
||||||
plain_range = 0;
|
|
||||||
state->send_prefix_class = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* client didn't ask for a prefix class, lets see if we can find one. */
|
|
||||||
for (p = daemon->prefix_classes; p ; p = p->next)
|
|
||||||
{
|
|
||||||
p->tag.next = NULL;
|
|
||||||
if (match_netid(&p->tag, solicit_tags, 1))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p)
|
|
||||||
{
|
|
||||||
plain_range = 0;
|
|
||||||
state->send_prefix_class = p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p && option_bool(OPT_LOG_OPTS))
|
|
||||||
my_syslog(MS_DHCP | LOG_INFO, "%u prefix class %d tag:%s", state->xid, p->class, p->tag.net);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
o = build_ia(state, &t1cntr);
|
o = build_ia(state, &t1cntr);
|
||||||
if (address_assigned)
|
if (address_assigned)
|
||||||
address_assigned = 2;
|
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))
|
||||||
{
|
{
|
||||||
req_addr = opt6_ptr(ia_option, 0);
|
/* worry about alignment here. */
|
||||||
|
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
|
|
||||||
if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
|
if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
|
||||||
{
|
{
|
||||||
lease_time = c->lease_time;
|
lease_time = c->lease_time;
|
||||||
/* If the client asks for an address on the same network as a configured address,
|
/* If the client asks for an address on the same network as a configured address,
|
||||||
offer the configured address instead, to make moving to newly-configured
|
offer the configured address instead, to make moving to newly-configured
|
||||||
addresses automatic. */
|
addresses automatic. */
|
||||||
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
|
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now))
|
||||||
{
|
{
|
||||||
req_addr = &addr;
|
req_addr = addr;
|
||||||
mark_config_used(c, &addr);
|
mark_config_used(c, &addr);
|
||||||
if (have_config(config, CONFIG_TIME))
|
if (have_config(config, CONFIG_TIME))
|
||||||
lease_time = config->lease_time;
|
lease_time = config->lease_time;
|
||||||
}
|
}
|
||||||
else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
|
else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
|
||||||
continue; /* not an address we're allowed */
|
continue; /* not an address we're allowed */
|
||||||
else if (!check_address(state, req_addr))
|
else if (!check_address(state, &req_addr))
|
||||||
continue; /* address leased elsewhere */
|
continue; /* address leased elsewhere */
|
||||||
|
|
||||||
/* add address to output packet */
|
/* add address to output packet */
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
|
||||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
mark_context_used(state, &req_addr);
|
||||||
state->send_prefix_class = prefix_class_from_context(c);
|
|
||||||
#endif
|
|
||||||
add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
|
|
||||||
mark_context_used(state, req_addr);
|
|
||||||
get_context_tag(state, c);
|
get_context_tag(state, c);
|
||||||
address_assigned = 1;
|
address_assigned = 1;
|
||||||
}
|
}
|
||||||
@@ -745,19 +703,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
for (c = state->context; c; c = c->current)
|
for (c = state->context; c; c = c->current)
|
||||||
if (!(c->flags & CONTEXT_CONF_USED) &&
|
if (!(c->flags & CONTEXT_CONF_USED) &&
|
||||||
match_netid(c->filter, solicit_tags, plain_range) &&
|
match_netid(c->filter, solicit_tags, plain_range) &&
|
||||||
config_valid(config, c, &addr) &&
|
config_valid(config, c, &addr, state, now))
|
||||||
check_address(state, &addr))
|
|
||||||
{
|
{
|
||||||
mark_config_used(state->context, &addr);
|
mark_config_used(state->context, &addr);
|
||||||
if (have_config(config, CONFIG_TIME))
|
if (have_config(config, CONFIG_TIME))
|
||||||
lease_time = config->lease_time;
|
lease_time = config->lease_time;
|
||||||
else
|
else
|
||||||
lease_time = c->lease_time;
|
lease_time = c->lease_time;
|
||||||
|
|
||||||
/* add address to output packet */
|
/* add address to output packet */
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
|
||||||
state->send_prefix_class = prefix_class_from_context(c);
|
|
||||||
#endif
|
|
||||||
add_address(state, c, lease_time, NULL, &min_time, &addr, now);
|
add_address(state, c, lease_time, NULL, &min_time, &addr, now);
|
||||||
mark_context_used(state, &addr);
|
mark_context_used(state, &addr);
|
||||||
get_context_tag(state, c);
|
get_context_tag(state, c);
|
||||||
@@ -768,15 +722,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
ltmp = NULL;
|
ltmp = NULL;
|
||||||
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
|
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
|
||||||
{
|
{
|
||||||
req_addr = <mp->addr6;
|
req_addr = ltmp->addr6;
|
||||||
if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
|
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
|
||||||
{
|
{
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
|
||||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
mark_context_used(state, &req_addr);
|
||||||
state->send_prefix_class = prefix_class_from_context(c);
|
|
||||||
#endif
|
|
||||||
add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
|
|
||||||
mark_context_used(state, req_addr);
|
|
||||||
get_context_tag(state, c);
|
get_context_tag(state, c);
|
||||||
address_assigned = 1;
|
address_assigned = 1;
|
||||||
}
|
}
|
||||||
@@ -786,10 +736,6 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
|
while ((c = address6_allocate(state->context, state->clid, state->clid_len, state->ia_type == OPTION6_IA_TA,
|
||||||
state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
|
state->iaid, ia_counter, solicit_tags, plain_range, &addr)))
|
||||||
{
|
{
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
|
||||||
state->send_prefix_class = prefix_class_from_context(c);
|
|
||||||
#endif
|
|
||||||
add_address(state, c, c->lease_time, NULL, &min_time, &addr, now);
|
add_address(state, c, c->lease_time, NULL, &min_time, &addr, now);
|
||||||
mark_context_used(state, &addr);
|
mark_context_used(state, &addr);
|
||||||
get_context_tag(state, c);
|
get_context_tag(state, c);
|
||||||
@@ -882,7 +828,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
|
|
||||||
if (!ia_option)
|
if (!ia_option)
|
||||||
{
|
{
|
||||||
/* If we get a request with a IA_*A without addresses, treat it exactly like
|
/* If we get a request with an IA_*A without addresses, treat it exactly like
|
||||||
a SOLICT with rapid commit set. */
|
a SOLICT with rapid commit set. */
|
||||||
save_counter(start);
|
save_counter(start);
|
||||||
goto request_no_address;
|
goto request_no_address;
|
||||||
@@ -892,16 +838,18 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
|
|
||||||
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
struct in6_addr req_addr;
|
||||||
struct dhcp_context *dynamic, *c;
|
struct dhcp_context *dynamic, *c;
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
struct in6_addr addr;
|
|
||||||
int config_ok = 0;
|
int config_ok = 0;
|
||||||
|
|
||||||
|
/* align. */
|
||||||
|
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
|
|
||||||
if ((c = address6_valid(state->context, req_addr, tagif, 1)))
|
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||||
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
|
config_ok = (config_implies(config, c, &req_addr) != NULL);
|
||||||
|
|
||||||
if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
|
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
|
||||||
{
|
{
|
||||||
if (!dynamic && !config_ok)
|
if (!dynamic && !config_ok)
|
||||||
{
|
{
|
||||||
@@ -911,7 +859,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
put_opt6_string(_("address unavailable"));
|
put_opt6_string(_("address unavailable"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
}
|
}
|
||||||
else if (!check_address(state, req_addr))
|
else if (!check_address(state, &req_addr))
|
||||||
{
|
{
|
||||||
/* Address leased to another DUID/IAID */
|
/* Address leased to another DUID/IAID */
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
@@ -929,11 +877,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
if (config_ok && have_config(config, CONFIG_TIME))
|
if (config_ok && have_config(config, CONFIG_TIME))
|
||||||
lease_time = config->lease_time;
|
lease_time = config->lease_time;
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
|
||||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
|
||||||
state->send_prefix_class = prefix_class_from_context(c);
|
|
||||||
#endif
|
|
||||||
add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
|
|
||||||
get_context_tag(state, dynamic);
|
get_context_tag(state, dynamic);
|
||||||
address_assigned = 1;
|
address_assigned = 1;
|
||||||
}
|
}
|
||||||
@@ -996,15 +940,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease = NULL;
|
struct dhcp_lease *lease = NULL;
|
||||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
struct in6_addr req_addr;
|
||||||
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
|
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
|
||||||
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
|
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
|
||||||
char *message = NULL;
|
char *message = NULL;
|
||||||
struct dhcp_context *this_context;
|
struct dhcp_context *this_context;
|
||||||
|
|
||||||
|
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
|
|
||||||
if (!(lease = lease6_find(state->clid, state->clid_len,
|
if (!(lease = lease6_find(state->clid, state->clid_len,
|
||||||
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||||
state->iaid, req_addr)))
|
state->iaid, &req_addr)))
|
||||||
{
|
{
|
||||||
/* If the server cannot find a client entry for the IA the server
|
/* If the server cannot find a client entry for the IA the server
|
||||||
returns the IA containing no addresses with a Status Code option set
|
returns the IA containing no addresses with a Status Code option set
|
||||||
@@ -1012,7 +958,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
save_counter(iacntr);
|
save_counter(iacntr);
|
||||||
t1cntr = 0;
|
t1cntr = 0;
|
||||||
|
|
||||||
log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
|
log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
|
||||||
|
|
||||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||||
put_opt6_short(DHCP6NOBINDING);
|
put_opt6_short(DHCP6NOBINDING);
|
||||||
@@ -1024,15 +970,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
|
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
|
||||||
(this_context = address6_valid(state->context, req_addr, tagif, 1)))
|
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||||
{
|
{
|
||||||
struct in6_addr addr;
|
|
||||||
unsigned int lease_time;
|
unsigned int lease_time;
|
||||||
|
|
||||||
get_context_tag(state, this_context);
|
get_context_tag(state, this_context);
|
||||||
|
|
||||||
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
|
if (config_implies(config, this_context, &req_addr) && have_config(config, CONFIG_TIME))
|
||||||
lease_time = config->lease_time;
|
lease_time = config->lease_time;
|
||||||
else
|
else
|
||||||
lease_time = this_context->lease_time;
|
lease_time = this_context->lease_time;
|
||||||
@@ -1045,7 +990,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
|
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
|
||||||
if (state->ia_type == OPTION6_IA_NA && state->hostname)
|
if (state->ia_type == OPTION6_IA_NA && state->hostname)
|
||||||
{
|
{
|
||||||
char *addr_domain = get_domain6(req_addr);
|
char *addr_domain = get_domain6(&req_addr);
|
||||||
if (!state->send_domain)
|
if (!state->send_domain)
|
||||||
state->send_domain = addr_domain;
|
state->send_domain = addr_domain;
|
||||||
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
|
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
|
||||||
@@ -1063,12 +1008,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (message && (message != state->hostname))
|
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);
|
||||||
|
|
||||||
o1 = new_opt6(OPTION6_IAADDR);
|
o1 = new_opt6(OPTION6_IAADDR);
|
||||||
put_opt6(req_addr, sizeof(*req_addr));
|
put_opt6(&req_addr, sizeof(req_addr));
|
||||||
put_opt6_long(preferred_time);
|
put_opt6_long(preferred_time);
|
||||||
put_opt6_long(valid_time);
|
put_opt6_long(valid_time);
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
@@ -1100,19 +1045,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
ia_option;
|
ia_option;
|
||||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
struct in6_addr req_addr;
|
||||||
|
|
||||||
|
/* alignment */
|
||||||
|
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
|
|
||||||
if (!address6_valid(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);
|
||||||
put_opt6_string(_("confirm failed"));
|
put_opt6_string(_("confirm failed"));
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
|
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
good_addr = 1;
|
good_addr = 1;
|
||||||
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
|
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1171,9 +1120,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
/* align */
|
||||||
|
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||||
state->iaid, opt6_ptr(ia_option, 0))))
|
state->iaid, &addr)))
|
||||||
lease_prune(lease, now);
|
lease_prune(lease, now);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1190,7 +1142,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
o1 = new_opt6(OPTION6_IAADDR);
|
o1 = new_opt6(OPTION6_IAADDR);
|
||||||
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
put_opt6(&addr, IN6ADDRSZ);
|
||||||
put_opt6_long(0);
|
put_opt6_long(0);
|
||||||
put_opt6_long(0);
|
put_opt6_long(0);
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
@@ -1233,16 +1185,20 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||||
{
|
{
|
||||||
struct dhcp_lease *lease;
|
struct dhcp_lease *lease;
|
||||||
struct in6_addr *addrp = opt6_ptr(ia_option, 0);
|
struct in6_addr addr;
|
||||||
|
struct addrlist *addr_list;
|
||||||
|
|
||||||
|
/* align */
|
||||||
|
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||||
|
|
||||||
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
|
if ((addr_list = config_implies(config, state->context, &addr)))
|
||||||
{
|
{
|
||||||
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
|
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
|
||||||
inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
||||||
daemon->addrbuff, daemon->dhcp_buff3);
|
daemon->addrbuff, daemon->dhcp_buff3);
|
||||||
config->flags |= CONFIG_DECLINED;
|
addr_list->flags |= ADDRLIST_DECLINED;
|
||||||
config->decline_time = now;
|
addr_list->decline_time = now;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* make sure this host gets a different address next time. */
|
/* make sure this host gets a different address next time. */
|
||||||
@@ -1250,7 +1206,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
context_tmp->addr_epoch++;
|
context_tmp->addr_epoch++;
|
||||||
|
|
||||||
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||||
state->iaid, opt6_ptr(ia_option, 0))))
|
state->iaid, &addr)))
|
||||||
lease_prune(lease, now);
|
lease_prune(lease, now);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1267,7 +1223,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
|||||||
}
|
}
|
||||||
|
|
||||||
o1 = new_opt6(OPTION6_IAADDR);
|
o1 = new_opt6(OPTION6_IAADDR);
|
||||||
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
put_opt6(&addr, IN6ADDRSZ);
|
||||||
put_opt6_long(0);
|
put_opt6_long(0);
|
||||||
put_opt6_long(0);
|
put_opt6_long(0);
|
||||||
end_opt6(o1);
|
end_opt6(o1);
|
||||||
@@ -1355,23 +1311,39 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
|||||||
|
|
||||||
for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
|
for (a = (struct in6_addr *)opt_cfg->val, j = 0; j < opt_cfg->len; j+=IN6ADDRSZ, a++)
|
||||||
{
|
{
|
||||||
|
struct in6_addr *p = NULL;
|
||||||
|
|
||||||
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
if (IN6_IS_ADDR_UNSPECIFIED(a))
|
||||||
{
|
{
|
||||||
if (!add_local_addrs(state->context))
|
if (!add_local_addrs(state->context))
|
||||||
put_opt6(state->fallback, IN6ADDRSZ);
|
p = state->fallback;
|
||||||
}
|
}
|
||||||
else if (IN6_IS_ADDR_ULA_ZERO(a))
|
else if (IN6_IS_ADDR_ULA_ZERO(a))
|
||||||
{
|
{
|
||||||
if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
|
if (!IN6_IS_ADDR_UNSPECIFIED(state->ula_addr))
|
||||||
put_opt6(state->ula_addr, IN6ADDRSZ);
|
p = state->ula_addr;
|
||||||
}
|
}
|
||||||
else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
|
else if (IN6_IS_ADDR_LINK_LOCAL_ZERO(a))
|
||||||
{
|
{
|
||||||
if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
|
if (!IN6_IS_ADDR_UNSPECIFIED(state->ll_addr))
|
||||||
put_opt6(state->ll_addr, IN6ADDRSZ);
|
p = state->ll_addr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
put_opt6(a, IN6ADDRSZ);
|
p = a;
|
||||||
|
|
||||||
|
if (!p)
|
||||||
|
continue;
|
||||||
|
else if (opt_cfg->opt == OPTION6_NTP_SERVER)
|
||||||
|
{
|
||||||
|
if (IN6_IS_ADDR_MULTICAST(p))
|
||||||
|
o1 = new_opt6(NTP_SUBOPTION_MC_ADDR);
|
||||||
|
else
|
||||||
|
o1 = new_opt6(NTP_SUBOPTION_SRV_ADDR);
|
||||||
|
put_opt6(p, IN6ADDRSZ);
|
||||||
|
end_opt6(o1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
put_opt6(p, IN6ADDRSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
end_opt6(o);
|
end_opt6(o);
|
||||||
@@ -1565,21 +1537,6 @@ static void get_context_tag(struct state *state, struct dhcp_context *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
static struct prefix_class *prefix_class_from_context(struct dhcp_context *context)
|
|
||||||
{
|
|
||||||
struct prefix_class *p;
|
|
||||||
struct dhcp_netid *t;
|
|
||||||
|
|
||||||
for (p = daemon->prefix_classes; p ; p = p->next)
|
|
||||||
for (t = context->filter; t; t = t->next)
|
|
||||||
if (strcmp(p->tag.net, t->net) == 0)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
|
static int check_ia(struct state *state, void *opt, void **endp, void **ia_option)
|
||||||
{
|
{
|
||||||
state->ia_type = opt6_type(opt);
|
state->ia_type = opt6_type(opt);
|
||||||
@@ -1625,7 +1582,7 @@ static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz)
|
|||||||
{
|
{
|
||||||
if (t1cntr != 0)
|
if (t1cntr != 0)
|
||||||
{
|
{
|
||||||
/* go back an fill in fields in IA_NA option */
|
/* go back and fill in fields in IA_NA option */
|
||||||
int sav = save_counter(t1cntr);
|
int sav = save_counter(t1cntr);
|
||||||
unsigned int t1, t2, fuzz = 0;
|
unsigned int t1, t2, fuzz = 0;
|
||||||
|
|
||||||
@@ -1664,16 +1621,6 @@ static void add_address(struct state *state, struct dhcp_context *context, unsig
|
|||||||
put_opt6(addr, sizeof(*addr));
|
put_opt6(addr, sizeof(*addr));
|
||||||
put_opt6_long(preferred_time);
|
put_opt6_long(preferred_time);
|
||||||
put_opt6_long(valid_time);
|
put_opt6_long(valid_time);
|
||||||
|
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
if (state->send_prefix_class)
|
|
||||||
{
|
|
||||||
int o1 = new_opt6(OPTION6_PREFIX_CLASS);
|
|
||||||
put_opt6_short(state->send_prefix_class->class);
|
|
||||||
end_opt6(o1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
end_opt6(o);
|
end_opt6(o);
|
||||||
|
|
||||||
if (state->lease_allocate)
|
if (state->lease_allocate)
|
||||||
@@ -1709,16 +1656,9 @@ static void mark_context_used(struct state *state, struct in6_addr *addr)
|
|||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
|
|
||||||
/* Mark that we have an address for this prefix. */
|
/* Mark that we have an address for this prefix. */
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
for (context = state->context; context; context = context->current)
|
|
||||||
if (is_same_net6(addr, &context->start6, context->prefix) &&
|
|
||||||
(!state->send_prefix_class || state->send_prefix_class == prefix_class_from_context(context)))
|
|
||||||
context->flags |= CONTEXT_USED;
|
|
||||||
#else
|
|
||||||
for (context = state->context; context; context = context->current)
|
for (context = state->context; context; context = context->current)
|
||||||
if (is_same_net6(addr, &context->start6, context->prefix))
|
if (is_same_net6(addr, &context->start6, context->prefix))
|
||||||
context->flags |= CONTEXT_USED;
|
context->flags |= CONTEXT_USED;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
|
static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr)
|
||||||
@@ -1745,6 +1685,78 @@ static int check_address(struct state *state, struct in6_addr *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* return true of *addr could have been generated from config. */
|
||||||
|
static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr)
|
||||||
|
{
|
||||||
|
int prefix;
|
||||||
|
struct in6_addr wild_addr;
|
||||||
|
struct addrlist *addr_list;
|
||||||
|
|
||||||
|
if (!config || !(config->flags & CONFIG_ADDR6))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
|
||||||
|
{
|
||||||
|
prefix = (addr_list->flags & ADDRLIST_PREFIX) ? addr_list->prefixlen : 128;
|
||||||
|
wild_addr = addr_list->addr.addr6;
|
||||||
|
|
||||||
|
if ((addr_list->flags & ADDRLIST_WILDCARD) && context->prefix == 64)
|
||||||
|
{
|
||||||
|
wild_addr = context->start6;
|
||||||
|
setaddr6part(&wild_addr, addr6part(&addr_list->addr.addr6));
|
||||||
|
}
|
||||||
|
else if (!is_same_net6(&context->start6, addr, context->prefix))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (is_same_net6(&wild_addr, addr, prefix))
|
||||||
|
return addr_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now)
|
||||||
|
{
|
||||||
|
u64 addrpart, i, addresses;
|
||||||
|
struct addrlist *addr_list;
|
||||||
|
|
||||||
|
if (!config || !(config->flags & CONFIG_ADDR6))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (addr_list = config->addr6; addr_list; addr_list = addr_list->next)
|
||||||
|
if (!(addr_list->flags & ADDRLIST_DECLINED) ||
|
||||||
|
difftime(now, addr_list->decline_time) >= (float)DECLINE_BACKOFF)
|
||||||
|
{
|
||||||
|
addrpart = addr6part(&addr_list->addr.addr6);
|
||||||
|
addresses = 1;
|
||||||
|
|
||||||
|
if (addr_list->flags & ADDRLIST_PREFIX)
|
||||||
|
addresses = (u64)1<<(128-addr_list->prefixlen);
|
||||||
|
|
||||||
|
if ((addr_list->flags & ADDRLIST_WILDCARD))
|
||||||
|
{
|
||||||
|
if (context->prefix != 64)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*addr = context->start6;
|
||||||
|
}
|
||||||
|
else if (is_same_net6(&context->start6, &addr_list->addr.addr6, context->prefix))
|
||||||
|
*addr = addr_list->addr.addr6;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0 ; i < addresses; i++)
|
||||||
|
{
|
||||||
|
setaddr6part(addr, addrpart+i);
|
||||||
|
|
||||||
|
if (check_address(state, addr))
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate valid and preferred times to send in leases/renewals.
|
/* Calculate valid and preferred times to send in leases/renewals.
|
||||||
|
|
||||||
Inputs are:
|
Inputs are:
|
||||||
@@ -1935,19 +1947,16 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
|||||||
}
|
}
|
||||||
else if (type == OPTION6_IAADDR)
|
else if (type == OPTION6_IAADDR)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
|
struct in6_addr addr;
|
||||||
|
|
||||||
|
/* align */
|
||||||
|
memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
|
||||||
|
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
|
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
|
||||||
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
|
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
|
||||||
optname = "iaaddr";
|
optname = "iaaddr";
|
||||||
ia_options = opt6_ptr(opt, 24);
|
ia_options = opt6_ptr(opt, 24);
|
||||||
}
|
}
|
||||||
#ifdef OPTION6_PREFIX_CLASS
|
|
||||||
else if (type == OPTION6_PREFIX_CLASS)
|
|
||||||
{
|
|
||||||
optname = "prefix-class";
|
|
||||||
sprintf(daemon->namebuff, "class=%u", opt6_uint(opt, 0, 2));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (type == OPTION6_STATUS_CODE)
|
else if (type == OPTION6_STATUS_CODE)
|
||||||
{
|
{
|
||||||
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
int len = sprintf(daemon->namebuff, "%u ", opt6_uint(opt, 0, 2));
|
||||||
@@ -2072,7 +2081,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
{
|
{
|
||||||
/* ->local is same value for all relays on ->current chain */
|
/* ->local is same value for all relays on ->current chain */
|
||||||
|
|
||||||
struct all_addr from;
|
union all_addr from;
|
||||||
unsigned char *header;
|
unsigned char *header;
|
||||||
unsigned char *inbuff = daemon->dhcp_packet.iov_base;
|
unsigned char *inbuff = daemon->dhcp_packet.iov_base;
|
||||||
int msg_type = *inbuff;
|
int msg_type = *inbuff;
|
||||||
@@ -2085,7 +2094,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
|
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
|
||||||
|
|
||||||
/* source address == relay address */
|
/* source address == relay address */
|
||||||
from.addr.addr6 = relay->local.addr.addr6;
|
from.addr6 = relay->local.addr6;
|
||||||
|
|
||||||
/* Get hop count from nested relayed message */
|
/* Get hop count from nested relayed message */
|
||||||
if (msg_type == DHCP6RELAYFORW)
|
if (msg_type == DHCP6RELAYFORW)
|
||||||
@@ -2105,7 +2114,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
|
|
||||||
header[0] = DHCP6RELAYFORW;
|
header[0] = DHCP6RELAYFORW;
|
||||||
header[1] = hopcount;
|
header[1] = hopcount;
|
||||||
memcpy(&header[2], &relay->local.addr.addr6, IN6ADDRSZ);
|
memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ);
|
||||||
memcpy(&header[18], peer_address, IN6ADDRSZ);
|
memcpy(&header[18], peer_address, IN6ADDRSZ);
|
||||||
|
|
||||||
/* RFC-6939 */
|
/* RFC-6939 */
|
||||||
@@ -2126,12 +2135,12 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
union mysockaddr to;
|
union mysockaddr to;
|
||||||
|
|
||||||
to.sa.sa_family = AF_INET6;
|
to.sa.sa_family = AF_INET6;
|
||||||
to.in6.sin6_addr = relay->server.addr.addr6;
|
to.in6.sin6_addr = relay->server.addr6;
|
||||||
to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
|
to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
|
||||||
to.in6.sin6_flowinfo = 0;
|
to.in6.sin6_flowinfo = 0;
|
||||||
to.in6.sin6_scope_id = 0;
|
to.in6.sin6_scope_id = 0;
|
||||||
|
|
||||||
if (IN6_ARE_ADDR_EQUAL(&relay->server.addr.addr6, &multicast))
|
if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
|
||||||
{
|
{
|
||||||
int multicast_iface;
|
int multicast_iface;
|
||||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||||
@@ -2170,7 +2179,7 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
|
|||||||
memcpy(&link, &inbuff[2], IN6ADDRSZ);
|
memcpy(&link, &inbuff[2], IN6ADDRSZ);
|
||||||
|
|
||||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||||
if (IN6_ARE_ADDR_EQUAL(&link, &relay->local.addr.addr6) &&
|
if (IN6_ARE_ADDR_EQUAL(&link, &relay->local.addr6) &&
|
||||||
(!relay->interface || wildcard_match(relay->interface, arrival_interface)))
|
(!relay->interface || wildcard_match(relay->interface, arrival_interface)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Code to safely remove RRs from an DNS answer */
|
/* Code to safely remove RRs from a DNS answer */
|
||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
@@ -247,7 +247,7 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||||||
|
|
||||||
check_rrs(p, header, plen, 1, rrs, rr_found);
|
check_rrs(p, header, plen, 1, rrs, rr_found);
|
||||||
|
|
||||||
/* Fouth pass, elide records */
|
/* Fourth pass, elide records */
|
||||||
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
||||||
{
|
{
|
||||||
unsigned char *start = rrs[i];
|
unsigned char *start = rrs[i];
|
||||||
@@ -270,7 +270,7 @@ u16 *rrfilter_desc(int type)
|
|||||||
{
|
{
|
||||||
/* List of RRtypes which include domains in the data.
|
/* List of RRtypes which include domains in the data.
|
||||||
0 -> domain
|
0 -> domain
|
||||||
integer -> no of plain bytes
|
integer -> no. of plain bytes
|
||||||
-1 -> end
|
-1 -> end
|
||||||
|
|
||||||
zero is not a valid RRtype, so the final entry is returned for
|
zero is not a valid RRtype, so the final entry is returned for
|
||||||
|
|||||||
+3
-2
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -166,7 +166,8 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
|||||||
|
|
||||||
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
|
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
|
||||||
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
|
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
|
||||||
errno == EHOSTUNREACH)
|
errno == EHOSTUNREACH &&
|
||||||
|
slaac->backoff == 12)
|
||||||
slaac->ping_time = 0; /* Give up */
|
slaac->ping_time = 0; /* Give up */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
+4
-5
@@ -62,7 +62,7 @@ void ipset_init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
int add_to_ipset(const char *setname, const union all_addr *ipaddr,
|
||||||
int flags, int remove)
|
int flags, int remove)
|
||||||
{
|
{
|
||||||
struct pfr_addr addr;
|
struct pfr_addr addr;
|
||||||
@@ -108,19 +108,18 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
|||||||
my_syslog(LOG_INFO, _("info: table created"));
|
my_syslog(LOG_INFO, _("info: table created"));
|
||||||
|
|
||||||
bzero(&addr, sizeof(addr));
|
bzero(&addr, sizeof(addr));
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (flags & F_IPV6)
|
if (flags & F_IPV6)
|
||||||
{
|
{
|
||||||
addr.pfra_af = AF_INET6;
|
addr.pfra_af = AF_INET6;
|
||||||
addr.pfra_net = 0x80;
|
addr.pfra_net = 0x80;
|
||||||
memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
|
memcpy(&(addr.pfra_ip6addr), ipaddr, sizeof(struct in6_addr));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
addr.pfra_af = AF_INET;
|
addr.pfra_af = AF_INET;
|
||||||
addr.pfra_net = 0x20;
|
addr.pfra_net = 0x20;
|
||||||
addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
|
addr.pfra_ip4addr.s_addr = ipaddr->addr4.s_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bzero(&io, sizeof(io));
|
bzero(&io, sizeof(io));
|
||||||
|
|||||||
+137
-97
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
|
||||||
|
static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len);
|
||||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||||
static void free_transfer(struct tftp_transfer *transfer);
|
static void free_transfer(struct tftp_transfer *transfer);
|
||||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
||||||
@@ -50,7 +51,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
int is_err = 1, if_index = 0, mtu = 0;
|
int is_err = 1, if_index = 0, mtu = 0;
|
||||||
struct iname *tmp;
|
struct iname *tmp;
|
||||||
struct tftp_transfer *transfer;
|
struct tftp_transfer *transfer = NULL, **up;
|
||||||
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
|
int port = daemon->start_tftp_port; /* may be zero to use ephemeral port */
|
||||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||||
int mtuflag = IP_PMTUDISC_DONT;
|
int mtuflag = IP_PMTUDISC_DONT;
|
||||||
@@ -59,24 +60,21 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
char *prefix = daemon->tftp_prefix;
|
char *prefix = daemon->tftp_prefix;
|
||||||
struct tftp_prefix *pref;
|
struct tftp_prefix *pref;
|
||||||
struct all_addr addra;
|
union all_addr addra;
|
||||||
#ifdef HAVE_IPV6
|
int family = listen->addr.sa.sa_family;
|
||||||
/* Can always get recvd interface for IPv6 */
|
/* Can always get recvd interface for IPv6 */
|
||||||
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
|
int check_dest = !option_bool(OPT_NOWILD) || family == AF_INET6;
|
||||||
#else
|
|
||||||
int check_dest = !option_bool(OPT_NOWILD);
|
|
||||||
#endif
|
|
||||||
union {
|
union {
|
||||||
struct cmsghdr align; /* this ensures alignment */
|
struct cmsghdr align; /* this ensures alignment */
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
|
||||||
#endif
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||||
char control[CMSG_SPACE(sizeof(unsigned int))];
|
char control[CMSG_SPACE(sizeof(struct in_addr)) +
|
||||||
|
CMSG_SPACE(sizeof(unsigned int))];
|
||||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||||
char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
|
char control[CMSG_SPACE(sizeof(struct in_addr)) +
|
||||||
|
CMSG_SPACE(sizeof(struct sockaddr_dl))];
|
||||||
#endif
|
#endif
|
||||||
} control_u;
|
} control_u;
|
||||||
|
|
||||||
@@ -124,10 +122,10 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
if (msg.msg_controllen < sizeof(struct cmsghdr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addr.sa.sa_family = listen->family;
|
addr.sa.sa_family = family;
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
if (listen->family == AF_INET)
|
if (family == AF_INET)
|
||||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||||
{
|
{
|
||||||
@@ -141,7 +139,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(HAVE_SOLARIS_NETWORK)
|
#elif defined(HAVE_SOLARIS_NETWORK)
|
||||||
if (listen->family == AF_INET)
|
if (family == AF_INET)
|
||||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@@ -157,7 +155,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
|
||||||
if (listen->family == AF_INET)
|
if (family == AF_INET)
|
||||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@@ -174,8 +172,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
if (family == AF_INET6)
|
||||||
if (listen->family == AF_INET6)
|
|
||||||
{
|
{
|
||||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||||
@@ -190,19 +187,16 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if_index = p.p->ipi6_ifindex;
|
if_index = p.p->ipi6_ifindex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!indextoname(listen->tftpfd, if_index, namebuff))
|
if (!indextoname(listen->tftpfd, if_index, namebuff))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
name = namebuff;
|
name = namebuff;
|
||||||
|
|
||||||
addra.addr.addr4 = addr.in.sin_addr;
|
addra.addr4 = addr.in.sin_addr;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
if (family == AF_INET6)
|
||||||
if (listen->family == AF_INET6)
|
addra.addr6 = addr.in6.sin6_addr;
|
||||||
addra.addr.addr6 = addr.in6.sin6_addr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (daemon->tftp_interfaces)
|
if (daemon->tftp_interfaces)
|
||||||
{
|
{
|
||||||
@@ -217,12 +211,12 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Do the same as DHCP */
|
/* Do the same as DHCP */
|
||||||
if (!iface_check(listen->family, &addra, name, NULL))
|
if (!iface_check(family, &addra, name, NULL))
|
||||||
{
|
{
|
||||||
if (!option_bool(OPT_CLEVERBIND))
|
if (!option_bool(OPT_CLEVERBIND))
|
||||||
enumerate_interfaces(0);
|
enumerate_interfaces(0);
|
||||||
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
|
if (!loopback_exception(listen->tftpfd, family, &addra, name) &&
|
||||||
!label_exception(if_index, listen->family, &addra) )
|
!label_exception(if_index, family, &addra))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +228,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||||
{
|
{
|
||||||
mtu = ifr.ifr_mtu;
|
mtu = ifr.ifr_mtu;
|
||||||
@@ -247,6 +241,39 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if (mtu == 0)
|
if (mtu == 0)
|
||||||
mtu = daemon->tftp_mtu;
|
mtu = daemon->tftp_mtu;
|
||||||
|
|
||||||
|
/* data transfer via server listening socket */
|
||||||
|
if (option_bool(OPT_SINGLE_PORT))
|
||||||
|
{
|
||||||
|
int tftp_cnt;
|
||||||
|
|
||||||
|
for (tftp_cnt = 0, transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; up = &transfer->next, transfer = transfer->next)
|
||||||
|
{
|
||||||
|
tftp_cnt++;
|
||||||
|
|
||||||
|
if (sockaddr_isequal(&peer, &transfer->peer))
|
||||||
|
{
|
||||||
|
if (ntohs(*((unsigned short *)packet)) == OP_RRQ)
|
||||||
|
{
|
||||||
|
/* Handle repeated RRQ or abandoned transfer from same host and port
|
||||||
|
by unlinking and reusing the struct transfer. */
|
||||||
|
*up = transfer->next;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handle_tftp(now, transfer, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Enforce simultaneous transfer limit. In non-single-port mode
|
||||||
|
this is doene by not listening on the server socket when
|
||||||
|
too many transfers are in progress. */
|
||||||
|
if (!transfer && tftp_cnt >= daemon->tftp_max)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (name)
|
if (name)
|
||||||
{
|
{
|
||||||
/* check for per-interface prefix */
|
/* check for per-interface prefix */
|
||||||
@@ -255,14 +282,13 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
prefix = pref->prefix;
|
prefix = pref->prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listen->family == AF_INET)
|
if (family == AF_INET)
|
||||||
{
|
{
|
||||||
addr.in.sin_port = htons(port);
|
addr.in.sin_port = htons(port);
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
addr.in.sin_len = sizeof(addr.in);
|
addr.in.sin_len = sizeof(addr.in);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addr.in6.sin6_port = htons(port);
|
addr.in6.sin6_port = htons(port);
|
||||||
@@ -272,18 +298,22 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
addr.in6.sin6_len = sizeof(addr.in6);
|
addr.in6.sin6_len = sizeof(addr.in6);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!(transfer = whine_malloc(sizeof(struct tftp_transfer))))
|
/* May reuse struct transfer from abandoned transfer in single port mode. */
|
||||||
|
if (!transfer && !(transfer = whine_malloc(sizeof(struct tftp_transfer))))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
|
if (option_bool(OPT_SINGLE_PORT))
|
||||||
|
transfer->sockfd = listen->tftpfd;
|
||||||
|
else if ((transfer->sockfd = socket(family, SOCK_DGRAM, 0)) == -1)
|
||||||
{
|
{
|
||||||
free(transfer);
|
free(transfer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer->peer = peer;
|
transfer->peer = peer;
|
||||||
|
transfer->source = addra;
|
||||||
|
transfer->if_index = if_index;
|
||||||
transfer->timeout = now + 2;
|
transfer->timeout = now + 2;
|
||||||
transfer->backoff = 1;
|
transfer->backoff = 1;
|
||||||
transfer->block = 1;
|
transfer->block = 1;
|
||||||
@@ -293,10 +323,10 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
transfer->opt_blocksize = transfer->opt_transize = 0;
|
transfer->opt_blocksize = transfer->opt_transize = 0;
|
||||||
transfer->netascii = transfer->carrylf = 0;
|
transfer->netascii = transfer->carrylf = 0;
|
||||||
|
|
||||||
prettyprint_addr(&peer, daemon->addrbuff);
|
(void)prettyprint_addr(&peer, daemon->addrbuff);
|
||||||
|
|
||||||
/* if we have a nailed-down range, iterate until we find a free one. */
|
/* if we have a nailed-down range, iterate until we find a free one. */
|
||||||
while (1)
|
while (!option_bool(OPT_SINGLE_PORT))
|
||||||
{
|
{
|
||||||
if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
|
if (bind(transfer->sockfd, &addr.sa, sa_len(&addr)) == -1 ||
|
||||||
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
|
||||||
@@ -308,12 +338,11 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
{
|
{
|
||||||
if (++port <= daemon->end_tftp_port)
|
if (++port <= daemon->end_tftp_port)
|
||||||
{
|
{
|
||||||
if (listen->family == AF_INET)
|
if (family == AF_INET)
|
||||||
addr.in.sin_port = htons(port);
|
addr.in.sin_port = htons(port);
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
else
|
else
|
||||||
addr.in6.sin6_port = htons(port);
|
addr.in6.sin6_port = htons(port);
|
||||||
#endif
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
|
my_syslog(MS_TFTP | LOG_ERR, _("unable to get free port for TFTP"));
|
||||||
@@ -326,7 +355,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
|
|
||||||
p = packet + 2;
|
p = packet + 2;
|
||||||
end = packet + len;
|
end = packet + len;
|
||||||
|
|
||||||
if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
|
if (ntohs(*((unsigned short *)packet)) != OP_RRQ ||
|
||||||
!(filename = next(&p, end)) ||
|
!(filename = next(&p, end)) ||
|
||||||
!(mode = next(&p, end)) ||
|
!(mode = next(&p, end)) ||
|
||||||
@@ -347,7 +376,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
|
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
|
||||||
{
|
{
|
||||||
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
|
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
|
||||||
int overhead = (listen->family == AF_INET) ? 32 : 52;
|
int overhead = (family == AF_INET) ? 32 : 52;
|
||||||
transfer->blocksize = atoi(opt);
|
transfer->blocksize = atoi(opt);
|
||||||
if (transfer->blocksize < 1)
|
if (transfer->blocksize < 1)
|
||||||
transfer->blocksize = 1;
|
transfer->blocksize = 1;
|
||||||
@@ -450,9 +479,8 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
is_err = 0;
|
is_err = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (sendto(transfer->sockfd, packet, len, 0,
|
send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index);
|
||||||
(struct sockaddr *)&peer, sa_len(&peer)) == -1 && errno == EINTR);
|
|
||||||
|
|
||||||
if (is_err)
|
if (is_err)
|
||||||
free_transfer(transfer);
|
free_transfer(transfer);
|
||||||
@@ -549,63 +577,28 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
|||||||
void check_tftp_listeners(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;
|
|
||||||
|
|
||||||
struct ack {
|
/* In single port mode, all packets come via port 69 and tftp_request() */
|
||||||
unsigned short op, block;
|
if (!option_bool(OPT_SINGLE_PORT))
|
||||||
} *mess = (struct ack *)daemon->packet;
|
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||||
|
|
||||||
/* Check for activity on any existing transfers */
|
|
||||||
for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
|
|
||||||
{
|
|
||||||
tmp = transfer->next;
|
|
||||||
|
|
||||||
prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
|
||||||
|
|
||||||
if (poll_check(transfer->sockfd, POLLIN))
|
if (poll_check(transfer->sockfd, POLLIN))
|
||||||
{
|
{
|
||||||
/* we overwrote the buffer... */
|
/* we overwrote the buffer... */
|
||||||
daemon->srv_save = NULL;
|
daemon->srv_save = NULL;
|
||||||
|
handle_tftp(now, transfer, recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0));
|
||||||
if ((len = recv(transfer->sockfd, daemon->packet, daemon->packet_buff_sz, 0)) >= (ssize_t)sizeof(struct ack))
|
|
||||||
{
|
|
||||||
if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
|
|
||||||
{
|
|
||||||
/* Got ack, ensure we take the (re)transmit path */
|
|
||||||
transfer->timeout = now;
|
|
||||||
transfer->backoff = 0;
|
|
||||||
if (transfer->block++ != 0)
|
|
||||||
transfer->offset += transfer->blocksize - transfer->expansion;
|
|
||||||
}
|
|
||||||
else if (ntohs(mess->op) == OP_ERR)
|
|
||||||
{
|
|
||||||
char *p = daemon->packet + sizeof(struct ack);
|
|
||||||
char *end = daemon->packet + len;
|
|
||||||
char *err = next(&p, end);
|
|
||||||
|
|
||||||
/* Sanitise error message */
|
|
||||||
if (!err)
|
|
||||||
err = "";
|
|
||||||
else
|
|
||||||
sanitise(err);
|
|
||||||
|
|
||||||
my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
|
|
||||||
(int)ntohs(mess->block), err,
|
|
||||||
daemon->addrbuff);
|
|
||||||
|
|
||||||
/* Got err, ensure we take abort */
|
|
||||||
transfer->timeout = now;
|
|
||||||
transfer->backoff = 100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (transfer = daemon->tftp_trans, up = &daemon->tftp_trans; transfer; transfer = tmp)
|
||||||
|
{
|
||||||
|
tmp = transfer->next;
|
||||||
|
|
||||||
if (difftime(now, transfer->timeout) >= 0.0)
|
if (difftime(now, transfer->timeout) >= 0.0)
|
||||||
{
|
{
|
||||||
int endcon = 0;
|
int endcon = 0;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
/* timeout, retransmit */
|
/* timeout, retransmit */
|
||||||
transfer->timeout += 1 + (1<<transfer->backoff);
|
transfer->timeout += 1 + (1<<(transfer->backoff/2));
|
||||||
|
|
||||||
/* we overwrote the buffer... */
|
/* we overwrote the buffer... */
|
||||||
daemon->srv_save = NULL;
|
daemon->srv_save = NULL;
|
||||||
@@ -615,22 +608,24 @@ void check_tftp_listeners(time_t now)
|
|||||||
len = tftp_err_oops(daemon->packet, transfer->file->filename);
|
len = tftp_err_oops(daemon->packet, transfer->file->filename);
|
||||||
endcon = 1;
|
endcon = 1;
|
||||||
}
|
}
|
||||||
/* don't complain about timeout when we're awaiting the last
|
else if (++transfer->backoff > 7)
|
||||||
ACK, some clients never send it */
|
|
||||||
else if (++transfer->backoff > 7 && len != 0)
|
|
||||||
{
|
{
|
||||||
endcon = 1;
|
/* don't complain about timeout when we're awaiting the last
|
||||||
|
ACK, some clients never send it */
|
||||||
|
if ((unsigned)len == transfer->blocksize + 4)
|
||||||
|
endcon = 1;
|
||||||
len = 0;
|
len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len != 0)
|
if (len != 0)
|
||||||
while(sendto(transfer->sockfd, daemon->packet, len, 0,
|
send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len,
|
||||||
(struct sockaddr *)&transfer->peer, sa_len(&transfer->peer)) == -1 && errno == EINTR);
|
&transfer->peer, &transfer->source, transfer->if_index);
|
||||||
|
|
||||||
if (endcon || len == 0)
|
if (endcon || len == 0)
|
||||||
{
|
{
|
||||||
strcpy(daemon->namebuff, transfer->file->filename);
|
strcpy(daemon->namebuff, transfer->file->filename);
|
||||||
sanitise(daemon->namebuff);
|
sanitise(daemon->namebuff);
|
||||||
|
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
||||||
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
|
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
|
||||||
/* unlink */
|
/* unlink */
|
||||||
*up = tmp;
|
*up = tmp;
|
||||||
@@ -649,15 +644,60 @@ void check_tftp_listeners(time_t now)
|
|||||||
up = &transfer->next;
|
up = &transfer->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* packet in daemon->packet as this is called. */
|
||||||
|
static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
|
||||||
|
{
|
||||||
|
struct ack {
|
||||||
|
unsigned short op, block;
|
||||||
|
} *mess = (struct ack *)daemon->packet;
|
||||||
|
|
||||||
|
if (len >= (ssize_t)sizeof(struct ack))
|
||||||
|
{
|
||||||
|
if (ntohs(mess->op) == OP_ACK && ntohs(mess->block) == (unsigned short)transfer->block)
|
||||||
|
{
|
||||||
|
/* Got ack, ensure we take the (re)transmit path */
|
||||||
|
transfer->timeout = now;
|
||||||
|
transfer->backoff = 0;
|
||||||
|
if (transfer->block++ != 0)
|
||||||
|
transfer->offset += transfer->blocksize - transfer->expansion;
|
||||||
|
}
|
||||||
|
else if (ntohs(mess->op) == OP_ERR)
|
||||||
|
{
|
||||||
|
char *p = daemon->packet + sizeof(struct ack);
|
||||||
|
char *end = daemon->packet + len;
|
||||||
|
char *err = next(&p, end);
|
||||||
|
|
||||||
|
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
||||||
|
|
||||||
|
/* Sanitise error message */
|
||||||
|
if (!err)
|
||||||
|
err = "";
|
||||||
|
else
|
||||||
|
sanitise(err);
|
||||||
|
|
||||||
|
my_syslog(MS_TFTP | LOG_ERR, _("error %d %s received from %s"),
|
||||||
|
(int)ntohs(mess->block), err,
|
||||||
|
daemon->addrbuff);
|
||||||
|
|
||||||
|
/* Got err, ensure we take abort */
|
||||||
|
transfer->timeout = now;
|
||||||
|
transfer->backoff = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void free_transfer(struct tftp_transfer *transfer)
|
static void free_transfer(struct tftp_transfer *transfer)
|
||||||
{
|
{
|
||||||
close(transfer->sockfd);
|
if (!option_bool(OPT_SINGLE_PORT))
|
||||||
|
close(transfer->sockfd);
|
||||||
|
|
||||||
if (transfer->file && (--transfer->file->refcount) == 0)
|
if (transfer->file && (--transfer->file->refcount) == 0)
|
||||||
{
|
{
|
||||||
close(transfer->file->fd);
|
close(transfer->file->fd);
|
||||||
free(transfer->file);
|
free(transfer->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(transfer);
|
free(transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+205
@@ -0,0 +1,205 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_UBUS
|
||||||
|
|
||||||
|
#include <libubus.h>
|
||||||
|
|
||||||
|
static struct blob_buf b;
|
||||||
|
static int notify;
|
||||||
|
static int error_logged = 0;
|
||||||
|
|
||||||
|
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method,
|
||||||
|
struct blob_attr *msg);
|
||||||
|
|
||||||
|
static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj);
|
||||||
|
|
||||||
|
static const struct ubus_method ubus_object_methods[] = {
|
||||||
|
UBUS_METHOD_NOARG("metrics", ubus_handle_metrics),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct ubus_object_type ubus_object_type =
|
||||||
|
UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
|
||||||
|
|
||||||
|
static struct ubus_object ubus_object = {
|
||||||
|
.name = NULL,
|
||||||
|
.type = &ubus_object_type,
|
||||||
|
.methods = ubus_object_methods,
|
||||||
|
.n_methods = ARRAY_SIZE(ubus_object_methods),
|
||||||
|
.subscribe_cb = ubus_subscribe_cb,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ubus_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
|
||||||
|
my_syslog(LOG_DEBUG, _("UBus subscription callback: %s subscriber(s)"), obj->has_subscribers ? "1" : "0");
|
||||||
|
notify = obj->has_subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ubus_destroy(struct ubus_context *ubus)
|
||||||
|
{
|
||||||
|
// Forces re-initialization when we're reusing the same definitions later on.
|
||||||
|
ubus_object.id = 0;
|
||||||
|
ubus_object_type.id = 0;
|
||||||
|
|
||||||
|
ubus_free(ubus);
|
||||||
|
daemon->ubus = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ubus_disconnect_cb(struct ubus_context *ubus)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ubus_reconnect(ubus, NULL);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("Cannot reconnect to UBus: %s"), ubus_strerror(ret));
|
||||||
|
|
||||||
|
ubus_destroy(ubus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ubus_init()
|
||||||
|
{
|
||||||
|
struct ubus_context *ubus = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ubus = ubus_connect(NULL);
|
||||||
|
if (!ubus)
|
||||||
|
{
|
||||||
|
if (!error_logged)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("Cannot initialize UBus: connection failed"));
|
||||||
|
error_logged = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_destroy(ubus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus_object.name = daemon->ubus_name;
|
||||||
|
ret = ubus_add_object(ubus, &ubus_object);
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
if (!error_logged)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
|
||||||
|
error_logged = 1;
|
||||||
|
}
|
||||||
|
ubus_destroy(ubus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ubus->connection_lost = ubus_disconnect_cb;
|
||||||
|
daemon->ubus = ubus;
|
||||||
|
error_logged = 0;
|
||||||
|
|
||||||
|
my_syslog(LOG_INFO, _("Connected to system UBus"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ubus_listeners()
|
||||||
|
{
|
||||||
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
|
if (!ubus)
|
||||||
|
{
|
||||||
|
if (!error_logged)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("Cannot set UBus listeners: no connection"));
|
||||||
|
error_logged = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_logged = 0;
|
||||||
|
|
||||||
|
poll_listen(ubus->sock.fd, POLLIN);
|
||||||
|
poll_listen(ubus->sock.fd, POLLERR);
|
||||||
|
poll_listen(ubus->sock.fd, POLLHUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_ubus_listeners()
|
||||||
|
{
|
||||||
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
|
if (!ubus)
|
||||||
|
{
|
||||||
|
if (!error_logged)
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("Cannot poll UBus listeners: no connection"));
|
||||||
|
error_logged = 1;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_logged = 0;
|
||||||
|
|
||||||
|
if (poll_check(ubus->sock.fd, POLLIN))
|
||||||
|
ubus_handle_event(ubus);
|
||||||
|
|
||||||
|
if (poll_check(ubus->sock.fd, POLLHUP | POLLERR))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_INFO, _("Disconnecting from UBus"));
|
||||||
|
|
||||||
|
ubus_destroy(ubus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||||
|
struct ubus_request_data *req, const char *method,
|
||||||
|
struct blob_attr *msg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
(void)obj;
|
||||||
|
(void)method;
|
||||||
|
(void)msg;
|
||||||
|
|
||||||
|
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
|
||||||
|
|
||||||
|
for (i=0; i < __METRIC_MAX; i++)
|
||||||
|
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
|
||||||
|
|
||||||
|
return ubus_send_reply(ctx, req, b.head);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
|
||||||
|
{
|
||||||
|
struct ubus_context *ubus = (struct ubus_context *)daemon->ubus;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!ubus || !notify)
|
||||||
|
return;
|
||||||
|
|
||||||
|
blob_buf_init(&b, BLOBMSG_TYPE_TABLE);
|
||||||
|
if (mac)
|
||||||
|
blobmsg_add_string(&b, "mac", mac);
|
||||||
|
if (ip)
|
||||||
|
blobmsg_add_string(&b, "ip", ip);
|
||||||
|
if (name)
|
||||||
|
blobmsg_add_string(&b, "name", name);
|
||||||
|
if (interface)
|
||||||
|
blobmsg_add_string(&b, "interface", interface);
|
||||||
|
|
||||||
|
ret = ubus_notify(ubus, &ubus_object, type, b.head, -1);
|
||||||
|
if (!ret)
|
||||||
|
my_syslog(LOG_ERR, _("Failed to send UBus event: %s"), ubus_strerror(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* HAVE_UBUS */
|
||||||
+127
-21
@@ -1,4 +1,4 @@
|
|||||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
/* dnsmasq is Copyright (c) 2000-2020 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
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
#include <idna.h>
|
#include <idna.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* SURF random number generator */
|
/* SURF random number generator */
|
||||||
|
|
||||||
static u32 seed[32];
|
static u32 seed[32];
|
||||||
@@ -246,14 +250,16 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
|||||||
|
|
||||||
while (sval && *sval)
|
while (sval && *sval)
|
||||||
{
|
{
|
||||||
if (limit && p + 1 > (unsigned char*)limit)
|
|
||||||
return p;
|
|
||||||
|
|
||||||
unsigned char *cp = p++;
|
unsigned char *cp = p++;
|
||||||
|
|
||||||
|
if (limit && p > (unsigned char*)limit)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||||
{
|
{
|
||||||
if (limit && p + 1 > (unsigned char*)limit)
|
if (limit && p + 1 > (unsigned char*)limit)
|
||||||
return p;
|
return NULL;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||||
*p++ = (*(++sval))-1;
|
*p++ = (*(++sval))-1;
|
||||||
@@ -261,10 +267,12 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
|||||||
#endif
|
#endif
|
||||||
*p++ = *sval;
|
*p++ = *sval;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cp = j;
|
*cp = j;
|
||||||
if (*sval)
|
if (*sval)
|
||||||
sval++;
|
sval++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +285,18 @@ void *safe_malloc(size_t size)
|
|||||||
die(_("could not get memory"), NULL, EC_NOMEM);
|
die(_("could not get memory"), NULL, EC_NOMEM);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ensure limited size string is always terminated.
|
||||||
|
* Can be replaced by (void)strlcpy() on some platforms */
|
||||||
|
void safe_strncpy(char *dest, const char *src, size_t size)
|
||||||
|
{
|
||||||
|
if (size != 0)
|
||||||
|
{
|
||||||
|
dest[size-1] = '\0';
|
||||||
|
strncpy(dest, src, size-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void safe_pipe(int *fd, int read_noblock)
|
void safe_pipe(int *fd, int read_noblock)
|
||||||
{
|
{
|
||||||
@@ -305,13 +324,12 @@ int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2)
|
|||||||
s1->in.sin_port == s2->in.sin_port &&
|
s1->in.sin_port == s2->in.sin_port &&
|
||||||
s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
|
s1->in.sin_addr.s_addr == s2->in.sin_addr.s_addr)
|
||||||
return 1;
|
return 1;
|
||||||
#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 &&
|
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
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -321,11 +339,9 @@ int sa_len(union mysockaddr *addr)
|
|||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
return addr->sa.sa_len;
|
return addr->sa.sa_len;
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET6)
|
if (addr->sa.sa_family == AF_INET6)
|
||||||
return sizeof(addr->in6);
|
return sizeof(addr->in6);
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
return sizeof(addr->in);
|
return sizeof(addr->in);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -351,6 +367,44 @@ int hostname_isequal(const char *a, const char *b)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
|
||||||
|
int hostname_issubdomain(char *a, char *b)
|
||||||
|
{
|
||||||
|
char *ap, *bp;
|
||||||
|
unsigned int c1, c2;
|
||||||
|
|
||||||
|
/* move to the end */
|
||||||
|
for (ap = a; *ap; ap++);
|
||||||
|
for (bp = b; *bp; bp++);
|
||||||
|
|
||||||
|
/* a shorter than b or a empty. */
|
||||||
|
if ((bp - b) < (ap - a) || ap == a)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
c1 = (unsigned char) *(--ap);
|
||||||
|
c2 = (unsigned char) *(--bp);
|
||||||
|
|
||||||
|
if (c1 >= 'A' && c1 <= 'Z')
|
||||||
|
c1 += 'a' - 'A';
|
||||||
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
|
if (c1 != c2)
|
||||||
|
return 0;
|
||||||
|
} while (ap != a);
|
||||||
|
|
||||||
|
if (bp == b)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (*(--bp) == '.')
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
time_t dnsmasq_time(void)
|
time_t dnsmasq_time(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_BROKEN_RTC
|
#ifdef HAVE_BROKEN_RTC
|
||||||
@@ -384,7 +438,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#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)
|
||||||
{
|
{
|
||||||
int pfbytes = prefixlen >> 3;
|
int pfbytes = prefixlen >> 3;
|
||||||
@@ -423,15 +476,12 @@ void setaddr6part(struct in6_addr *addr, u64 host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* returns port number from address */
|
/* returns port number from address */
|
||||||
int prettyprint_addr(union mysockaddr *addr, char *buf)
|
int prettyprint_addr(union mysockaddr *addr, char *buf)
|
||||||
{
|
{
|
||||||
int port = 0;
|
int port = 0;
|
||||||
|
|
||||||
#ifdef HAVE_IPV6
|
|
||||||
if (addr->sa.sa_family == AF_INET)
|
if (addr->sa.sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
|
inet_ntop(AF_INET, &addr->in.sin_addr, buf, ADDRSTRLEN);
|
||||||
@@ -450,10 +500,6 @@ int prettyprint_addr(union mysockaddr *addr, char *buf)
|
|||||||
}
|
}
|
||||||
port = ntohs(addr->in6.sin6_port);
|
port = ntohs(addr->in6.sin6_port);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
strcpy(buf, inet_ntoa(addr->in.sin_addr));
|
|
||||||
port = ntohs(addr->in.sin_port);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
@@ -482,20 +528,20 @@ void prettyprint_time(char *buf, unsigned int t)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
int mask = 0, i = 0;
|
int done = 0, mask = 0, i = 0;
|
||||||
char *r;
|
char *r;
|
||||||
|
|
||||||
if (mac_type)
|
if (mac_type)
|
||||||
*mac_type = 0;
|
*mac_type = 0;
|
||||||
|
|
||||||
while (maxlen == -1 || i < maxlen)
|
while (!done && (maxlen == -1 || i < maxlen))
|
||||||
{
|
{
|
||||||
for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
|
for (r = in; *r != 0 && *r != ':' && *r != '-' && *r != ' '; r++)
|
||||||
if (*r != '*' && !isxdigit((unsigned char)*r))
|
if (*r != '*' && !isxdigit((unsigned char)*r))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (*r == 0)
|
if (*r == 0)
|
||||||
maxlen = i;
|
done = 1;
|
||||||
|
|
||||||
if (r != in )
|
if (r != in )
|
||||||
{
|
{
|
||||||
@@ -663,6 +709,47 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* close all fds except STDIN, STDOUT and STDERR, spare1, spare2 and spare3 */
|
||||||
|
void close_fds(long max_fd, int spare1, int spare2, int spare3)
|
||||||
|
{
|
||||||
|
/* On Linux, use the /proc/ filesystem to find which files
|
||||||
|
are actually open, rather than iterate over the whole space,
|
||||||
|
for efficiency reasons. If this fails we drop back to the dumb code. */
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
DIR *d;
|
||||||
|
|
||||||
|
if ((d = opendir("/proc/self/fd")))
|
||||||
|
{
|
||||||
|
struct dirent *de;
|
||||||
|
|
||||||
|
while ((de = readdir(d)))
|
||||||
|
{
|
||||||
|
long fd;
|
||||||
|
char *e = NULL;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
fd = strtol(de->d_name, &e, 10);
|
||||||
|
|
||||||
|
if (errno != 0 || !e || *e || fd == dirfd(d) ||
|
||||||
|
fd == STDOUT_FILENO || fd == STDERR_FILENO || fd == STDIN_FILENO ||
|
||||||
|
fd == spare1 || fd == spare2 || fd == spare3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(d);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* fallback, dumb code. */
|
||||||
|
for (max_fd--; max_fd >= 0; max_fd--)
|
||||||
|
if (max_fd != STDOUT_FILENO && max_fd != STDERR_FILENO && max_fd != STDIN_FILENO &&
|
||||||
|
max_fd != spare1 && max_fd != spare2 && max_fd != spare3)
|
||||||
|
close(max_fd);
|
||||||
|
}
|
||||||
|
|
||||||
/* Basically match a string value against a wildcard pattern. */
|
/* Basically match a string value against a wildcard pattern. */
|
||||||
int wildcard_match(const char* wildcard, const char* match)
|
int wildcard_match(const char* wildcard, const char* match)
|
||||||
{
|
{
|
||||||
@@ -699,3 +786,22 @@ int wildcard_matchn(const char* wildcard, const char* match, int num)
|
|||||||
|
|
||||||
return (!num) || (*wildcard == *match);
|
return (!num) || (*wildcard == *match);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_LINUX_NETWORK
|
||||||
|
int kernel_version(void)
|
||||||
|
{
|
||||||
|
struct utsname utsname;
|
||||||
|
int version;
|
||||||
|
char *split;
|
||||||
|
|
||||||
|
if (uname(&utsname) < 0)
|
||||||
|
die(_("failed to find kernel version: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
split = strtok(utsname.release, ".");
|
||||||
|
version = (split ? atoi(split) : 0);
|
||||||
|
split = strtok(NULL, ".");
|
||||||
|
version = version * 256 + (split ? atoi(split) : 0);
|
||||||
|
split = strtok(NULL, ".");
|
||||||
|
return version * 256 + (split ? atoi(split) : 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+1
-2
@@ -1,9 +1,8 @@
|
|||||||
# The root DNSSEC trust anchor, valid as at 10/02/2017
|
# The root DNSSEC trust anchor, valid as at 11/01/2019
|
||||||
|
|
||||||
# Note that this is a DS record (ie a hash of the root Zone Signing Key)
|
# 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
|
# If was downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||||
|
|
||||||
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
|
|
||||||
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
|
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user