Compare commits
253 Commits
v2.74test1
...
v2.78
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30df7efc96 | ||
|
|
3e8c42cba5 | ||
|
|
62cb936cb7 | ||
|
|
39921d03ba | ||
|
|
6a0b00f0d6 | ||
|
|
51eadb692a | ||
|
|
897c113fda | ||
|
|
33e3f1029c | ||
|
|
3d4ff1ba84 | ||
|
|
24036ea507 | ||
|
|
0549c73b7e | ||
|
|
b697fbb7f1 | ||
|
|
96e063c43d | ||
|
|
4e841da1a6 | ||
|
|
09ce307bdb | ||
|
|
a3303e196e | ||
|
|
63437ffbb5 | ||
|
|
69a815aa8f | ||
|
|
1d224949cc | ||
|
|
391f708a09 | ||
|
|
cbd29e5da8 | ||
|
|
50a2841d34 | ||
|
|
9396752c11 | ||
|
|
712dadb287 | ||
|
|
32be32eab8 | ||
|
|
1649f709e7 | ||
|
|
50ca85504c | ||
|
|
4bb68866a8 | ||
|
|
2446514e71 | ||
|
|
109d0e74f1 | ||
|
|
74ea91531a | ||
|
|
9828ab115e | ||
|
|
f77700aa27 | ||
|
|
0fbd980639 | ||
|
|
43cdf1c3d0 | ||
|
|
ff19b1a97d | ||
|
|
1835343acd | ||
|
|
2aaea18f43 | ||
|
|
7ab78b937f | ||
|
|
c7be0164ce | ||
|
|
d203af4a02 | ||
|
|
05f76dab89 | ||
|
|
bf05f8ff20 | ||
|
|
09f3b2cd9c | ||
|
|
22827870fa | ||
|
|
4583dd9e42 | ||
|
|
561441320f | ||
|
|
b2a9c571eb | ||
|
|
efff74c1ae | ||
|
|
a9df0e30b0 | ||
|
|
5ce3e76fbf | ||
|
|
6ec5f5c427 | ||
|
|
5a7212c70e | ||
|
|
3a8b0f6fcc | ||
|
|
a24c31e023 | ||
|
|
f5a3679f1d | ||
|
|
5ac813cb86 | ||
|
|
a93b02e321 | ||
|
|
c77fb9d8f0 | ||
|
|
facc18f2a8 | ||
|
|
bc515b71ec | ||
|
|
7bfa26399b | ||
|
|
461b7b43b4 | ||
|
|
b1cefa57f1 | ||
|
|
ce9a9704c6 | ||
|
|
93a9a55055 | ||
|
|
44eb875a5a | ||
|
|
bc87e609c2 | ||
|
|
005c46d6f5 | ||
|
|
503c609149 | ||
|
|
60704f5e2e | ||
|
|
4e7694d710 | ||
|
|
e33b48700e | ||
|
|
ad59f278c6 | ||
|
|
16f03e7139 | ||
|
|
dc99058d83 | ||
|
|
916959c188 | ||
|
|
864913c0f3 | ||
|
|
13dee6f49e | ||
|
|
62f9c0d470 | ||
|
|
54bb3639d4 | ||
|
|
fca008d8d4 | ||
|
|
43517fcaf5 | ||
|
|
88a77a78ad | ||
|
|
3e2496fb16 | ||
|
|
05da782f8f | ||
|
|
361dfe5158 | ||
|
|
68f6312d4b | ||
|
|
730c6745f0 | ||
|
|
d42d4706bb | ||
|
|
0740e43e20 | ||
|
|
903df07bcb | ||
|
|
0ef1334d78 | ||
|
|
5eb9dde09c | ||
|
|
ae3154aca9 | ||
|
|
3ebe62d1b7 | ||
|
|
f89cae3ecf | ||
|
|
09b768efa4 | ||
|
|
a1d973f987 | ||
|
|
0682b7795c | ||
|
|
b637d7815d | ||
|
|
7ac9ae1125 | ||
|
|
c6af3a32f2 | ||
|
|
16800ea072 | ||
|
|
b5e33ae53a | ||
|
|
3c0c1111fe | ||
|
|
2675f20615 | ||
|
|
e94ad0fa01 | ||
|
|
396750cef5 | ||
|
|
6c45519e18 | ||
|
|
6d95099c56 | ||
|
|
c8328ecde8 | ||
|
|
094bfaeb4f | ||
|
|
bf4e62c19e | ||
|
|
6b1c464d6d | ||
|
|
fa78573778 | ||
|
|
cd2ddb9904 | ||
|
|
9bb3998da4 | ||
|
|
d6dce53e08 | ||
|
|
06093a9a84 | ||
|
|
1d07667ac7 | ||
|
|
591ed1e905 | ||
|
|
907efeb2dc | ||
|
|
beea62cb66 | ||
|
|
5874f3e922 | ||
|
|
04cb536f16 | ||
|
|
8ee8524016 | ||
|
|
ce7845bf54 | ||
|
|
d55f81f5fd | ||
|
|
294d36df47 | ||
|
|
f186bdcbc7 | ||
|
|
ed1bd54b5c | ||
|
|
da2cad4b14 | ||
|
|
0a4a04969d | ||
|
|
45cb8dd9be | ||
|
|
88b09aaddc | ||
|
|
fe71bba356 | ||
|
|
cbc100fc81 | ||
|
|
68bea10bbf | ||
|
|
8628cd603f | ||
|
|
ff325644c7 | ||
|
|
b97026035e | ||
|
|
69cbf78bb6 | ||
|
|
c6cdf6bbee | ||
|
|
09217a1a87 | ||
|
|
332c41e2ff | ||
|
|
2c0c36f54b | ||
|
|
d6b749af91 | ||
|
|
14ffa0770b | ||
|
|
87985855ad | ||
|
|
a2bc254bed | ||
|
|
a7b27e84fa | ||
|
|
529b030228 | ||
|
|
4caa86dd7d | ||
|
|
e1abeeeec2 | ||
|
|
40205a053e | ||
|
|
b8ac466209 | ||
|
|
d1377fa3c4 | ||
|
|
fa79466c2a | ||
|
|
a93bd4b016 | ||
|
|
407a1f3e95 | ||
|
|
4b6af5d53f | ||
|
|
7aa3f9af66 | ||
|
|
f7cf749943 | ||
|
|
aa300f7167 | ||
|
|
c7f3bd2ac8 | ||
|
|
22fe2fd038 | ||
|
|
7480aeffc8 | ||
|
|
bec366b404 | ||
|
|
e06e6e34bf | ||
|
|
832e47beab | ||
|
|
df3d54f776 | ||
|
|
22c0f4fe87 | ||
|
|
9e4cf47ee8 | ||
|
|
fdc97e1383 | ||
|
|
a18bf3149a | ||
|
|
1566bacb2c | ||
|
|
e6e751b066 | ||
|
|
8de875f0fb | ||
|
|
4ace25c5d6 | ||
|
|
1e5051228d | ||
|
|
926332a764 | ||
|
|
d05dd58de1 | ||
|
|
f7443d76f7 | ||
|
|
f344dbc622 | ||
|
|
f4d0c660ca | ||
|
|
1801a29226 | ||
|
|
92be34a407 | ||
|
|
bb58f63ce5 | ||
|
|
367341f745 | ||
|
|
eddf365284 | ||
|
|
a63b8b89e6 | ||
|
|
5757371d43 | ||
|
|
b633de9413 | ||
|
|
c49778df4a | ||
|
|
53a9173fc0 | ||
|
|
d917275e48 | ||
|
|
cc7cb0b893 | ||
|
|
ec0628c4b2 | ||
|
|
97b1d25764 | ||
|
|
33702ab1f8 | ||
|
|
11867dc28c | ||
|
|
d3a8b39c7d | ||
|
|
15379ea1f2 | ||
|
|
efef497b89 | ||
|
|
5aa5f0ff2f | ||
|
|
5bb88f0963 | ||
|
|
1d03016bbc | ||
|
|
ce5732e84f | ||
|
|
a86fdf437e | ||
|
|
3e86d316c4 | ||
|
|
d67ecac59d | ||
|
|
fa14bec83b | ||
|
|
14a4ae883d | ||
|
|
3b799c826d | ||
|
|
b40f26c019 | ||
|
|
dd4ad9ac7e | ||
|
|
2dbba34b2c | ||
|
|
c2bcd1e183 | ||
|
|
d64c81fff7 | ||
|
|
93be5b1e02 | ||
|
|
9a31b68b59 | ||
|
|
0007ee9064 | ||
|
|
67ab3285b5 | ||
|
|
41a8d9e99b | ||
|
|
90477fb794 | ||
|
|
98079ea898 | ||
|
|
4790115455 | ||
|
|
27b78d990b | ||
|
|
77607cbea0 | ||
|
|
102208df69 | ||
|
|
6de81f1250 | ||
|
|
20fd11e11a | ||
|
|
9cdcfe9f19 | ||
|
|
5e3e464ac4 | ||
|
|
3a3965ac21 | ||
|
|
a7369bef8a | ||
|
|
d2aa7dfbb6 | ||
|
|
63ec5d1264 | ||
|
|
f6381cf482 | ||
|
|
34b5d19488 | ||
|
|
d6cb7e4815 | ||
|
|
d389e0191b | ||
|
|
d3699bb6bc | ||
|
|
13480e8c2a | ||
|
|
5b3b93f80a | ||
|
|
b69e845b1c | ||
|
|
90c3822bfa | ||
|
|
c895a0626d | ||
|
|
b842bc97bb | ||
|
|
0f38fa05a6 | ||
|
|
45c5cb1f8f | ||
|
|
f6d6956261 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
||||
VERSION export-subst
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -4,8 +4,9 @@ src/dnsmasq.pot
|
||||
src/dnsmasq
|
||||
src/dnsmasq_baseline
|
||||
src/.copts_*
|
||||
contrib/wrt/dhcp_lease_time
|
||||
contrib/wrt/dhcp_release
|
||||
contrib/lease-tools/dhcp_lease_time
|
||||
contrib/lease-tools/dhcp_release
|
||||
contrib/lease-tools/dhcp_release6
|
||||
debian/base/
|
||||
debian/daemon/
|
||||
debian/files
|
||||
|
||||
@@ -56,7 +56,7 @@ release 0.95 Major rewrite: remove calls to gethostbyname() and talk
|
||||
any more memory after start-up. The NAT-like forwarding was
|
||||
inspired by a suggestion from Eli Chen <eli@routefree.com>
|
||||
|
||||
release 0.96 Fixed embarrasing thinko in cache linked-list code.
|
||||
release 0.96 Fixed embarrassing thinko in cache linked-list code.
|
||||
|
||||
release 0.98 Some enhancements and bug-fixes.
|
||||
Thanks to "Denis Carre" <denis.carre@laposte.net> and Martin
|
||||
@@ -78,7 +78,7 @@ release 0.98 Some enhancements and bug-fixes.
|
||||
ids, to thwart DNS spoofers.
|
||||
(7) Dnsmasq no longer forwards queries when the
|
||||
"recursion desired" bit is not set in the header.
|
||||
(8) Fixed getopt code to work on compliers with unsigned char.
|
||||
(8) Fixed getopt code to work on compilers with unsigned char.
|
||||
|
||||
release 0.991 Added -b flag: when set causes dnsmasq to always answer
|
||||
reverse queries on the RFC 1918 private IP space itself and
|
||||
@@ -88,7 +88,7 @@ release 0.991 Added -b flag: when set causes dnsmasq to always answer
|
||||
Fixed a bug which stopped dnsmasq working on a box with
|
||||
two or more interfaces with the same IP address.
|
||||
|
||||
Fixed cacheing of CNAMEs. Previously, a CNAME which pointed
|
||||
Fixed caching of CNAMEs. Previously, a CNAME which pointed
|
||||
to a name with many A records would not have all the addresses
|
||||
returned when being answered from the cache.
|
||||
|
||||
@@ -191,7 +191,7 @@ release 1.1 Added --user argument to allow user to change to
|
||||
|
||||
release 1.2 Added IPv6 DNS record support. AAAA records are cached
|
||||
and read from /etc/hosts. Reverse-lookups in the
|
||||
ip6.int and ip6.arpa domains are suppored. Dnsmasq can
|
||||
ip6.int and ip6.arpa domains are supported. Dnsmasq can
|
||||
talk to upstream servers via IPv6 if it finds IP6 addresses
|
||||
in /etc/resolv.conf and it offers DNS service automatically
|
||||
if IPv6 support is present in the kernel.
|
||||
@@ -214,7 +214,7 @@ release 1.3 Some versions of the Linux kernel return EINVAL rather
|
||||
starting, rather than after the first query - principle
|
||||
of least surprise applies here.
|
||||
|
||||
release 1.4 Fix a bug with DHPC lease parsing which broke in
|
||||
release 1.4 Fix a bug with DHCP lease parsing which broke in
|
||||
non-UTC timezones. Thanks to Mark Wormgoor for
|
||||
spotting and diagnosing this. Fixed versions in
|
||||
the .spec files this time. Fixed bug in Suse startup
|
||||
@@ -258,7 +258,7 @@ release 1.7 Fix a problem with cache not clearing properly
|
||||
on receipt of SIGHUP. Bug spotted by Sat Deshpande.
|
||||
|
||||
In group-id changing code:
|
||||
1) Drop supplimentary groups.
|
||||
1) Drop supplementary groups.
|
||||
2) Change gid before dropping root (patch from Soewono Effendi.)
|
||||
3) Change group to "dip" if it exists, to allow access
|
||||
to /etc/ppp/resolv.conf (suggestion from Jorg Sommer.)
|
||||
@@ -297,7 +297,7 @@ release 1.9 Fixes to rpm .spec files.
|
||||
required. The difference is not really visible with
|
||||
bloated libcs like glibc, but should dramatically reduce
|
||||
memory requirements when linked against ulibc for use on
|
||||
embeded routers, and that's the point really. Thanks to
|
||||
embedded routers, and that's the point really. Thanks to
|
||||
Matthew Natalier for prompting this.
|
||||
|
||||
Changed debug mode (-d) so that all logging appears on
|
||||
@@ -319,12 +319,12 @@ release 1.9 Fixes to rpm .spec files.
|
||||
uClinux. Thanks to Matthew Natalier for uClinux stuff.
|
||||
|
||||
release 1.10 Log warnings if resolv.conf or dhcp.leases are not
|
||||
accessable for any reason, as suggested by Hinrich Eilts.
|
||||
accessible for any reason, as suggested by Hinrich Eilts.
|
||||
|
||||
Fixed wrong address printing in error message about
|
||||
no interface with address.
|
||||
|
||||
Updated docs and split installation instuctions into setup.html.
|
||||
Updated docs and split installation instructions into setup.html.
|
||||
|
||||
Fix bug in CNAME chasing code: One CNAME pointing
|
||||
to many A records would lose A records after the
|
||||
@@ -346,7 +346,7 @@ release 1.10 Log warnings if resolv.conf or dhcp.leases are not
|
||||
|
||||
Added -S option to directly specify upstream servers and
|
||||
added ability to direct queries for specific domains to
|
||||
specfic servers. Suggested by Jens Vonderheide.
|
||||
specific servers. Suggested by Jens Vonderheide.
|
||||
|
||||
Upgraded random ID generation - patch from Rob Funk.
|
||||
|
||||
@@ -386,13 +386,13 @@ release 1.11 Actually implement the -R flag promised in the 1.10 man page.
|
||||
names in /etc/hosts -suggestion from Phil Harman.
|
||||
|
||||
Always return a zero time-to-live for names derived from
|
||||
DHCP which stops anthing else caching these
|
||||
DHCP which stops anything else caching these
|
||||
names. Previously the TTL was derived from the lease
|
||||
time but that is incorrect since a lease can be given
|
||||
up early: dnsmasq would know this but anything with the
|
||||
name cached with long TTL would not be updated.
|
||||
|
||||
Extended HAVE_IPV6 config flag to allow compliation on
|
||||
Extended HAVE_IPV6 config flag to allow compilation on
|
||||
old systems which don't have modern library routines
|
||||
like inet_ntop(). Thanks to Phil Harman for the patch.
|
||||
|
||||
@@ -471,7 +471,7 @@ release 1.14 Fixed man page description of -b option which confused
|
||||
/etc/resolv.conf.
|
||||
(Thanks to Klaas Teschauer)
|
||||
|
||||
Check that recieved queries have only rfc1035-legal characters
|
||||
Check that received queries have only rfc1035-legal characters
|
||||
in them. This check is mainly to avoid bad strings being
|
||||
sent to syslog.
|
||||
|
||||
@@ -549,7 +549,7 @@ release 1.16 Allow "/" characters in domain names - this fixes
|
||||
|
||||
release 1.17 Fixed crash with DHCP hostnames > 40 characters.
|
||||
|
||||
Fixed name-comparision routines to not depend on Locale,
|
||||
Fixed name-comparison routines to not depend on Locale,
|
||||
in theory this versions since 1.15 could lock up or give
|
||||
wrong results when run with locale != 'C'.
|
||||
|
||||
@@ -574,7 +574,7 @@ release 1.18 Added round-robin DNS for names which have more than one
|
||||
forwarded because -D is in effect, return NXDOMAIN not
|
||||
an empty reply.
|
||||
|
||||
Add code to return the software version in repsonse to the
|
||||
Add code to return the software version in response to the
|
||||
correct magic query in the same way as BIND. Use
|
||||
"dig version.bind chaos txt" to make the query.
|
||||
|
||||
@@ -635,7 +635,7 @@ release 2.0
|
||||
dynamic allocation.
|
||||
|
||||
Allow dhcp-host options for the same host with different
|
||||
IP adresses where the correct one will be selected for
|
||||
IP addresses where the correct one will be selected for
|
||||
the network the host appears on.
|
||||
|
||||
Fix parsing of --dhcp-option to allow more than one
|
||||
@@ -674,7 +674,7 @@ release 2.1
|
||||
|
||||
Fix unaligned access warnings on BSD/Alpha.
|
||||
|
||||
Allow empty DHCP options, like so: dhpc-option=44
|
||||
Allow empty DHCP options, like so: dhcp-option=44
|
||||
|
||||
Allow single-byte DHCP options like so: dhcp-option=20,1
|
||||
|
||||
@@ -745,7 +745,7 @@ release 2.3
|
||||
around a bug in the DHCP client in HP Jetdirect printers.
|
||||
Thanks to Marko Stolle for finding this problem.
|
||||
|
||||
Return DHCP T1 and T2 times, with "fuzz" to desychronise lease
|
||||
Return DHCP T1 and T2 times, with "fuzz" to desynchronise lease
|
||||
renewals, as specified in the RFC.
|
||||
|
||||
Ensure that the END option is always present in DHCP
|
||||
@@ -838,7 +838,7 @@ release 2.4
|
||||
by Chad Skeeters.
|
||||
|
||||
Fixed bug in /etc/ethers parsing code triggered by tab
|
||||
characters. Qudos to Dag Wieers for hepling to nail that
|
||||
characters. Kudos to Dag Wieers for helping to nail that
|
||||
one.
|
||||
|
||||
Added "bind-interfaces" option correctly.
|
||||
@@ -975,7 +975,7 @@ release 2.8
|
||||
configuration. Specifically: (1) options are matched on
|
||||
the netids from dhcp-range, dhcp-host, vendor class and
|
||||
user class(es). Multiple net-ids are allowed and options
|
||||
are searched on them all. (2) matches agains vendor class
|
||||
are searched on them all. (2) matches against vendor class
|
||||
and user class are now on a substring, if the given
|
||||
string is a substring of the vendor/user class, then a
|
||||
match occurs. Thanks again to Richard Musil for prompting
|
||||
@@ -997,7 +997,7 @@ release 2.8
|
||||
|
||||
Add checks against DHCP clients which return zero-length
|
||||
hostnames. This avoids the potential lease-loss problems
|
||||
reffered to above. Also, if a client sends a hostname when
|
||||
referred to above. Also, if a client sends a hostname when
|
||||
it creates a lease but subsequently sends no or a
|
||||
zero-length hostname whilst renewing, continue to use the
|
||||
existing hostname, don't wipe it out.
|
||||
@@ -1019,7 +1019,7 @@ release 2.9
|
||||
broken. The new algorithm is to pick as before for the
|
||||
first try, but if a query is retried, to send to all
|
||||
available servers in parallel. The first one to reply
|
||||
then becomes prefered for the next query. This should
|
||||
then becomes preferred for the next query. This should
|
||||
improve reliability without generating significant extra
|
||||
upstream load.
|
||||
|
||||
@@ -1027,7 +1027,7 @@ release 2.9
|
||||
unqualified domains introduced in version 2.8
|
||||
|
||||
Allow fallback to "bind-interfaces" at runtime: Some
|
||||
verions of *BSD seem to have enough stuff in the header
|
||||
versions of *BSD seem to have enough stuff in the header
|
||||
files to build but no kernel support. Also now log if
|
||||
"bind-interfaces" is forced on.
|
||||
|
||||
@@ -1049,7 +1049,7 @@ release 2.9
|
||||
first name found is now returned for reverse lookups,
|
||||
rather than all of them.
|
||||
|
||||
Add back fatal errors when nonexistant
|
||||
Add back fatal errors when nonexistent
|
||||
interfaces or interface addresses are given but only in
|
||||
"bind-interfaces" mode. Principle of least surprise applies.
|
||||
|
||||
@@ -1193,7 +1193,7 @@ version 2.14
|
||||
|
||||
version 2.15
|
||||
Fixed NXDOMAIN/NODATA confusion for locally known
|
||||
names. We now return a NODATA reponse for names which are
|
||||
names. We now return a NODATA response for names which are
|
||||
locally known. Now a query for (eg AAAA or MX) for a name
|
||||
with an IPv4 address in /etc/hosts which fails upstream
|
||||
will generate a NODATA response. Note that the query
|
||||
@@ -1229,7 +1229,7 @@ version 2.16
|
||||
|
||||
Set NONBLOCK on all listening sockets to workaround non-POSIX
|
||||
compliance in Linux 2.4 and 2.6. This fixes rare hangs which
|
||||
occured when corrupted packets were received. Thanks to
|
||||
occurred when corrupted packets were received. Thanks to
|
||||
Joris van Rantwijk for chasing that down.
|
||||
|
||||
Updated config.h for NetBSD. Thanks to Martin Lambers.
|
||||
@@ -1297,7 +1297,7 @@ version 2.18
|
||||
interfaces with more than one IPv6 address. Thanks to
|
||||
Martin Pels for help with that.
|
||||
|
||||
Fix problems which occured when more than one dhcp-range
|
||||
Fix problems which occurred when more than one dhcp-range
|
||||
was specified in the same subnet: sometimes parameters
|
||||
(lease time, network-id tag) from the wrong one would be
|
||||
used. Thanks to Rory Campbell-Lange for the bug report.
|
||||
@@ -1314,7 +1314,7 @@ version 2.19
|
||||
Thanks to Richard Atterer for the bug report.
|
||||
|
||||
Check for under-length option fields in DHCP packets, a
|
||||
zero length client-id, in particluar, could seriously
|
||||
zero length client-id, in particular, could seriously
|
||||
confuse dnsmasq 'till now. Thanks to Will Murname for help
|
||||
with that.
|
||||
|
||||
@@ -1389,7 +1389,7 @@ version 2.21
|
||||
recursive queries.
|
||||
|
||||
Fix DHCP address allocation problem when netid tags are in
|
||||
use. Thanks to Will Murnane for the bug report and
|
||||
use. Thanks to Will Murname for the bug report and
|
||||
subsequent testing.
|
||||
|
||||
Add an additional data section to the reply for MX and SRV
|
||||
@@ -1505,7 +1505,7 @@ version 2.23
|
||||
from dnsmasq --version. Thanks to Dirk Schenkewitz for
|
||||
the suggestion.
|
||||
|
||||
Fix pathalogical behaviour when a broken client keeps sending
|
||||
Fix pathological behaviour when a broken client keeps sending
|
||||
DHCPDISCOVER messages repeatedly and fast. Because dealing with
|
||||
each of these takes a few seconds, (because of the ping) then a
|
||||
queue of DHCP packets could build up. Now, the results of a ping
|
||||
@@ -1593,7 +1593,7 @@ version 2.24
|
||||
than one dhcp-range is available. Thanks to Sorin Panca
|
||||
for help chasing this down.
|
||||
|
||||
Added more explict error mesages to the hosts file and
|
||||
Added more explicit error messages to the hosts file and
|
||||
ethers file reading code. Markus Kaiserswerth suffered to
|
||||
make this happen.
|
||||
|
||||
@@ -1617,7 +1617,7 @@ version 2.25
|
||||
|
||||
Fixed Suse spec file - thanks to Steven Springl.
|
||||
|
||||
Fixed DHCP bug when two distict subnets are on the same
|
||||
Fixed DHCP bug when two distinct subnets are on the same
|
||||
physical interface. Thanks to Pawel Zawora for finding
|
||||
this and suggesting the fix.
|
||||
|
||||
@@ -1740,7 +1740,7 @@ version 2.28
|
||||
Fixed regression in netlink code under 2.2.x kernels which
|
||||
occurred in 2.27. Erik Jan Tromp is the vintage kernel fan
|
||||
who found this. P.S. It looks like this "netlink bind:
|
||||
permission denied" problem occured in kernels at least as
|
||||
permission denied" problem occurred in kernels at least as
|
||||
late a 2.4.18. Good information from Alain Richoux.
|
||||
|
||||
Added a warning when it's impossible to give a host its
|
||||
@@ -1761,7 +1761,7 @@ version 2.28
|
||||
Eric House and Eric Spakman for help in chasing this down.
|
||||
|
||||
Tolerate configuration screwups which lead to the DHCP
|
||||
server attemping to allocate its own address to a
|
||||
server attempting to allocate its own address to a
|
||||
client; eg setting the whole subnet range as a DHCP
|
||||
range. Addresses in use by the server are now excluded
|
||||
from use by clients.
|
||||
@@ -2273,7 +2273,7 @@ version 2.40
|
||||
this.
|
||||
|
||||
Use client-id as hash-seed for DHCP address allocation
|
||||
with Firewire and Infiniband, as these don't supply an MAC
|
||||
with Firewire and InfiniBand, as these don't supply an MAC
|
||||
address.
|
||||
|
||||
Tweaked TFTP file-open code to make it behave sensibly
|
||||
@@ -2307,7 +2307,7 @@ version 2.40
|
||||
Continue to use unqualified hostnames provided by DHCP
|
||||
clients, even if the domain part is illegal. (The domain
|
||||
is ignored, and an error logged.) Previously in this
|
||||
situation, the whole name whould have been
|
||||
situation, the whole name would have been
|
||||
rejected. Thanks to Jima for the patch.
|
||||
|
||||
Handle EINTR returns from wait() correctly and reap
|
||||
@@ -2319,7 +2319,7 @@ version 2.40
|
||||
leases file and passed to the lease-change
|
||||
script. Suggestion from Ben Voigt.
|
||||
|
||||
Re-run the lease chamge script with an "old" event for
|
||||
Re-run the lease change script with an "old" event for
|
||||
each lease when dnsmasq receives a SIGHUP.
|
||||
|
||||
Added more useful exit codes, including passing on a
|
||||
@@ -2417,7 +2417,7 @@ version 2.41
|
||||
Changed behavior of DHCP server to always return total length of
|
||||
a new lease in DHCPOFFER, even if an existing lease
|
||||
exists. (It used to return the time remaining on the lease
|
||||
whne one existed.) This fixes problems with the Sony Ericsson
|
||||
when one existed.) This fixes problems with the Sony Ericsson
|
||||
K610i phone. Thanks to Hakon Stordahl for finding and
|
||||
fixing this.
|
||||
|
||||
@@ -2476,7 +2476,7 @@ version 2.42
|
||||
|
||||
Fix OS detection logic to cope with GNU/FreeBSD.
|
||||
|
||||
Fix unitialised variable in DBus code - thanks to Roy
|
||||
Fix uninitialised variable in DBus code - thanks to Roy
|
||||
Marples.
|
||||
|
||||
Fix network enumeration code to work on later NetBSD -
|
||||
|
||||
88
FAQ
88
FAQ
@@ -59,7 +59,7 @@ A: Yes, there is explicit support for *BSD and MacOS X and Solaris.
|
||||
|
||||
Q: My company's nameserver knows about some names which aren't in the
|
||||
public DNS. Even though I put it first in /etc/resolv.conf, it
|
||||
dosen't work: dnsmasq seems not to use the nameservers in the order
|
||||
doesn't work: dnsmasq seems not to use the nameservers in the order
|
||||
given. What am I doing wrong?
|
||||
|
||||
A: By default, dnsmasq treats all the nameservers it knows about as
|
||||
@@ -144,19 +144,19 @@ Q: Who are Verisign, what do they have to do with the bogus-nxdomain
|
||||
option in dnsmasq and why should I wory about it?
|
||||
|
||||
A: [note: this was written in September 2003, things may well change.]
|
||||
Versign run the .com and .net top-level-domains. They have just
|
||||
Verisign run the .com and .net top-level-domains. They have just
|
||||
changed the configuration of their servers so that unknown .com and
|
||||
.net domains, instead of returning an error code NXDOMAIN, (no such
|
||||
domain) return the address of a host at Versign which runs a web
|
||||
domain) return the address of a host at Verisign which runs a web
|
||||
server showing a search page. Most right-thinking people regard
|
||||
this new behaviour as broken :-). You can test to see if you are
|
||||
suffering Versign brokeness by run a command like
|
||||
suffering Verisign brokenness by run a command like
|
||||
|
||||
host jlsdajkdalld.com
|
||||
|
||||
If you get "jlsdajkdalld.com" does not exist, then all is fine, if
|
||||
host returns an IP address, then the DNS is broken. (Try a few
|
||||
different unlikely domains, just in case you picked a wierd one
|
||||
different unlikely domains, just in case you picked a weird one
|
||||
which really _is_ registered.)
|
||||
|
||||
Assuming that your DNS is broken, and you want to fix it, simply
|
||||
@@ -180,7 +180,7 @@ A: There are a couple of configuration gotchas which have been
|
||||
whilst the ISC one works.
|
||||
|
||||
The first thing to check is the broadcast address set for the
|
||||
ethernet interface. This is normally the adddress on the connected
|
||||
ethernet interface. This is normally the address on the connected
|
||||
network with all ones in the host part. For instance if the
|
||||
address of the ethernet interface is 192.168.55.7 and the netmask
|
||||
is 255.255.255.0 then the broadcast address should be
|
||||
@@ -205,7 +205,7 @@ A: By default, none of the DHCP clients send the host-name when asking
|
||||
send with the "hostname" keyword in /etc/network/interfaces. (See
|
||||
"man interfaces" for details.) That doesn't work for dhclient, were
|
||||
you have to add something like "send host-name daisy" to
|
||||
/etc/dhclient.conf [Update: the lastest dhcpcd packages _do_ send
|
||||
/etc/dhclient.conf [Update: the latest dhcpcd packages _do_ send
|
||||
the hostname by default.
|
||||
|
||||
Q: I'm network booting my machines, and trying to give them static
|
||||
@@ -240,7 +240,7 @@ Q: What are these strange "bind-interface" and "bind-dynamic" options?
|
||||
|
||||
A: Dnsmasq from v2.63 can operate in one of three different "networking
|
||||
modes". This is unfortunate as it requires users configuring dnsmasq
|
||||
to take into account some rather bizzare contraints and select the
|
||||
to take into account some rather bizarre constraints and select the
|
||||
mode which best fits the requirements of a particular installation.
|
||||
The origin of these are deficiencies in the Unix networking
|
||||
model and APIs and each mode has different advantages and
|
||||
@@ -252,10 +252,10 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
|
||||
The three modes are "wildcard", "bind-interfaces" and "bind-dynamic".
|
||||
|
||||
In "wildcard" mode, dnsmasq binds the wildcard IP address (0.0.0.0 or
|
||||
::). This allows it to recieve all the packets sent to the server on
|
||||
::). This allows it to receive all the packets sent to the server on
|
||||
the relevant port. Access control (--interface, --except-interface,
|
||||
--listen-address, etc) is implemented by dnsmasq: it queries the
|
||||
kernel to determine the interface on which a packet was recieved and
|
||||
kernel to determine the interface on which a packet was received and
|
||||
the address to which it was sent, and applies the configured
|
||||
rules. Wildcard mode is the default if neither of the other modes are
|
||||
specified.
|
||||
@@ -276,7 +276,7 @@ A: Dnsmasq from v2.63 can operate in one of three different "networking
|
||||
The mode chosen has four different effects: co-existence with other
|
||||
servers, semantics of --interface access control, effect of new
|
||||
interfaces, and legality of --interface specifications for
|
||||
non-existent inferfaces. We will deal with these in order.
|
||||
non-existent interfaces. We will deal with these in order.
|
||||
|
||||
A dnsmasq instance running in wildcard mode precludes a machine from
|
||||
running a second instance of dnsmasq or any other DNS, TFTP or DHCP
|
||||
@@ -313,15 +313,25 @@ Q: Can I get email notification when a new version of dnsmasq is
|
||||
released?
|
||||
|
||||
A: Yes, new releases of dnsmasq are always announced through
|
||||
freshmeat.net, and they allow you to subcribe to email alerts when
|
||||
freshmeat.net, and they allow you to subscribe to email alerts when
|
||||
new versions of particular projects are released. New releases are
|
||||
also announced in the dnsmasq-discuss mailing list, subscribe at
|
||||
http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss
|
||||
|
||||
Q: What does the dhcp-authoritative option do?
|
||||
|
||||
A: See http://www.isc.org/files/auth.html - that's
|
||||
for the ISC daemon, but the same applies to dnsmasq.
|
||||
A: The DHCP spec says that when a DHCP server recieves a renewal request
|
||||
from a client it has no knowledge of, it should just ignore it.
|
||||
This is because it's supported to have more than one DHCP server
|
||||
on a network, and another DHCP server may be dealing with the client.
|
||||
This has the unfortunate effect that when _no_ DHCP replies to
|
||||
the client, it takes some time for the client to time-out and start
|
||||
to get a new lease. Setting this option makes dnsmasq violate the
|
||||
standard to the extent that it will send a NAK reply to the client,
|
||||
causing it to immediately start to get a new lease. This improves
|
||||
behaviour when machines move networks, and in the case that the DHCP
|
||||
lease database is lost. As long as there are not more tha one DHCP
|
||||
server on the network, it's safe to enable the option.
|
||||
|
||||
Q: Why does my Gentoo box pause for a minute before getting a new
|
||||
lease?
|
||||
@@ -349,18 +359,64 @@ A: By default, the identity of a machine is determined by using the
|
||||
method for setting the client-id varies with DHCP client software,
|
||||
dhcpcd uses the "-I" flag. Windows uses a registry setting,
|
||||
see http://www.jsiinc.com/SUBF/TIP2800/rh2845.htm
|
||||
|
||||
Addendum:
|
||||
From version 2.46, dnsmasq has a solution to this which doesn't
|
||||
involve setting client-IDs. It's possible to put more than one MAC
|
||||
address in a --dhcp-host configuration. This tells dnsmasq that it
|
||||
should use the specified IP for any of the specified MAC addresses,
|
||||
and furthermore it gives dnsmasq permission to sumarily abandon a
|
||||
and furthermore it gives dnsmasq permission to summarily abandon a
|
||||
lease to one of the MAC addresses if another one comes along. Note
|
||||
that this will work fine only as longer as only one interface is
|
||||
up at any time. There is no way for dnsmasq to enforce this
|
||||
constraint: if you configure multiple MAC addresses and violate
|
||||
this rule, bad things will happen.
|
||||
|
||||
Addendum-II: The link above is dead, the former contents of the link are:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
How can I keep the same DHCP client reservation, if the MAC address changes?
|
||||
|
||||
When you reserve an IP address for a DHCP client, you provide the
|
||||
MAC address of the client's NIC.
|
||||
|
||||
It is possible to use a custom identifier, which is sent as
|
||||
option 61 in the client's DHCP Discover and Request packet.
|
||||
|
||||
The DhcpClientIdentifier is a REG_DWORD value that is located at:
|
||||
|
||||
Windows NT 4.0 SP2+
|
||||
|
||||
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<Adapter Name>'X'\Parameters\Tcpip
|
||||
|
||||
where <Adapter Name> is the NIC driver name and 'X' is the number of the NIC.
|
||||
|
||||
Windows 2000
|
||||
|
||||
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\TcpIp\Parameters\Interfaces\<NIC GUID>
|
||||
|
||||
where <NIC GUID> is the GUID of the NIC.
|
||||
|
||||
The valid range of data is 0x0 - 0xFFFFFFFF. The custom identifier is send as 4 bytes,
|
||||
8 hexadecimal character, in groups of 2 hexadecimal characters, with the groups being
|
||||
sent in reverse order. If the custom identifier is less than 8 hexadeciaml characters,
|
||||
it is zero padded at the end. Examples:
|
||||
|
||||
Custom Client Client Reservation
|
||||
Identifier on DHCP Server
|
||||
12345678 78563412
|
||||
123456 56341200
|
||||
1234 34120000
|
||||
1234567 67452301
|
||||
12345 45230100
|
||||
123 23010000
|
||||
A18F42 428FA100
|
||||
CF432 32F40C00
|
||||
C32D1BE BED1320C
|
||||
|
||||
-------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Q: Can dnsmasq do DHCP on IP-alias interfaces?
|
||||
|
||||
A: Yes, from version-2.21. The support is only available running under
|
||||
@@ -488,7 +544,7 @@ Q: DHCP doesn't work with windows 7 but everything else is fine.
|
||||
|
||||
A: There seems to be a problem if Windows 7 doesn't get a value for
|
||||
DHCP option 252 in DHCP packets it gets from the server. The
|
||||
symtoms have beeen variously reported as continual DHCPINFORM
|
||||
symptoms have been variously reported as continual DHCPINFORM
|
||||
requests in an attempt to get an option-252, or even ignoring DHCP
|
||||
offers completely (and failing to get an IP address) if there is no
|
||||
option-252 supplied. DHCP option 252 is for WPAD, WWW Proxy
|
||||
|
||||
23
Makefile
23
Makefile
@@ -1,4 +1,4 @@
|
||||
# dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
# dnsmasq is Copyright (c) 2000-2016 Simon Kelley
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -55,10 +55,12 @@ dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG)
|
||||
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
||||
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
||||
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
||||
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
|
||||
idn2_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --libs libidn2`
|
||||
ct_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --cflags libnetfilter_conntrack`
|
||||
ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
|
||||
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.1`
|
||||
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.1`
|
||||
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.2`
|
||||
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2`
|
||||
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
|
||||
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
|
||||
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
|
||||
@@ -73,7 +75,8 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
|
||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o
|
||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||
poll.o rrfilter.o edns0.o arp.o
|
||||
|
||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
dns-protocol.h radv-protocol.h ip6addr.h
|
||||
@@ -81,8 +84,8 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
all : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
|
||||
mostly_clean :
|
||||
@@ -105,8 +108,8 @@ all-i18n : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||
build_cflags="$(version) $(dbus_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) `$(PKG_CONFIG) --cflags libidn`" \
|
||||
build_libs="$(dbus_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) `$(PKG_CONFIG) --libs libidn`" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
for f in `cd $(PO); echo *.po`; do \
|
||||
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
||||
@@ -122,7 +125,7 @@ merge :
|
||||
echo -n msgmerge $(PO)/$$f && $(MSGMERGE) --no-wrap -U $(PO)/$$f $(BUILDDIR)/dnsmasq.pot; \
|
||||
done
|
||||
|
||||
# Cannonicalise .po file.
|
||||
# Canonicalise .po file.
|
||||
%.po :
|
||||
@cd $(BUILDDIR) && $(MAKE) -f $(top)/Makefile dnsmasq.pot
|
||||
mv $(PO)/$*.po $(PO)/$*.po.orig && $(MSGMERGE) --no-wrap $(PO)/$*.po.orig $(BUILDDIR)/dnsmasq.pot >$(PO)/$*.po;
|
||||
@@ -141,7 +144,7 @@ bloatcheck : $(BUILDDIR)/dnsmasq_baseline mostly_clean all
|
||||
$(top)/bld/bloat-o-meter dnsmasq_baseline dnsmasq; \
|
||||
size dnsmasq_baseline dnsmasq
|
||||
|
||||
# rules below are targets in recusive makes with cwd=$(BUILDDIR)
|
||||
# rules below are targets in recursive makes with cwd=$(BUILDDIR)
|
||||
|
||||
$(copts_conf): $(hdrs)
|
||||
@rm -f *.o .copts_*
|
||||
|
||||
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
||||
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
|
||||
radv.c slaac.c auth.c ipset.c domain.c \
|
||||
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||
loop.c inotify.c
|
||||
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c
|
||||
|
||||
LOCAL_MODULE := dnsmasq
|
||||
|
||||
|
||||
@@ -11,11 +11,18 @@
|
||||
# If there is more than one v[0-9].* tag, sort them and use the
|
||||
# first. This favours, eg v2.63 over 2.63rc6.
|
||||
|
||||
# Change directory to the toplevel source directory.
|
||||
if test -z "$1" || ! test -d "$1" || ! cd "$1"; then
|
||||
echo "$0: First argument $1 must be toplevel dir." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if which git >/dev/null 2>&1 && \
|
||||
([ -d $1/.git ] || grep '^gitdir:' $1/.git >/dev/null 2>&1); then
|
||||
cd $1; git describe | sed 's/^v//'
|
||||
([ -d .git ] || grep '^gitdir:' .git >/dev/null 2>&1) && \
|
||||
git describe >/dev/null 2>&1; then
|
||||
git describe | sed 's/^v//'
|
||||
elif grep '\$Format:%d\$' $1/VERSION >/dev/null 2>&1; then
|
||||
# unsubstituted VERSION, but no git available.
|
||||
# unsubstituted VERSION, but no git available.
|
||||
echo UNKNOWN
|
||||
else
|
||||
vers=`cat $1/VERSION | sed 's/[(), ]/,/ g' | tr ',' '\n' | grep ^v[0-9]`
|
||||
|
||||
@@ -22,7 +22,7 @@ sudo chmod 644 /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
|
||||
|
||||
Optionally, edit your dnsmasq configuration file to your liking.
|
||||
|
||||
To start the launchd job, which starts dnsmaq, reboot or use the command:
|
||||
To start the launchd job, which starts dnsmasq, reboot or use the command:
|
||||
sudo launchctl load /Library/LaunchDaemons/uk.org.thekelleys.dnsmasq.plist
|
||||
|
||||
To stop the launchd job, which stops dnsmasq, use the command:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
|
||||
It fixes the depancy from the dns daemon name 'named'
|
||||
It fixes the dependency from the dns daemon name 'named'
|
||||
After appending the patch, the SuSEfirewall is again able to autodetect
|
||||
the dnsmasq named service.
|
||||
This is a very old bug in the SuSEfirewall script.
|
||||
The SuSE people think the name of the dns server will allways 'named'
|
||||
The SuSE people think the name of the dns server will always 'named'
|
||||
|
||||
|
||||
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
|
||||
|
||||
@@ -13,10 +13,10 @@ connection comes out of the other side. However, sometimes, we want to
|
||||
maintain that relationship through the proxy and continue the connection
|
||||
mark on packets upstream of our proxy
|
||||
|
||||
DNSMasq includes such a feature enabled by the --conntrack
|
||||
Dnsmasq includes such a feature enabled by the --conntrack
|
||||
option. This allows, for example, using iptables to mark traffic from
|
||||
a particular IP, and that mark to be persisted to requests made *by*
|
||||
DNSMasq. Such a feature could be useful for bandwidth accounting,
|
||||
Dnsmasq. Such a feature could be useful for bandwidth accounting,
|
||||
captive portals and the like. Note a similar feature has been
|
||||
implemented in Squid 2.2
|
||||
|
||||
@@ -40,7 +40,7 @@ on IP address. 3) Saves the firewall mark back to the connection mark
|
||||
(which will persist it across related packets)
|
||||
|
||||
4) is applied to the OUTPUT table, which is where we first see packets
|
||||
generated locally. DNSMasq will have already copied the firewall mark
|
||||
generated locally. Dnsmasq will have already copied the firewall mark
|
||||
from the request, across to the new packet, and so all that remains is
|
||||
for iptables to copy it to the connection mark so it's persisted across
|
||||
packets.
|
||||
|
||||
@@ -55,7 +55,7 @@ Index: src/dnsmasq.c
|
||||
}
|
||||
|
||||
@@ -434,7 +433,7 @@
|
||||
/* lose the setuid and setgid capbilities */
|
||||
/* lose the setuid and setgid capabilities */
|
||||
if (capset(hdr, data) == -1)
|
||||
{
|
||||
- send_event(err_pipe[1], EVENT_CAP_ERR, errno);
|
||||
|
||||
6
contrib/lease-tools/Makefile
Normal file
6
contrib/lease-tools/Makefile
Normal file
@@ -0,0 +1,6 @@
|
||||
CFLAGS?= -O2 -Wall -W
|
||||
|
||||
all: dhcp_release dhcp_release6 dhcp_lease_time
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o core dhcp_release dhcp_release6 dhcp_lease_time
|
||||
@@ -168,7 +168,7 @@ int main(int argc, char **argv)
|
||||
*(p++) = 1;
|
||||
*(p++) = DHCPINFORM;
|
||||
|
||||
/* Explicity request the lease time, it won't be sent otherwise:
|
||||
/* Explicitly request the lease time, it won't be sent otherwise:
|
||||
this is a dnsmasq extension, not standard. */
|
||||
*(p++) = OPTION_REQUESTED_OPTIONS;
|
||||
*(p++) = 1;
|
||||
@@ -206,13 +206,13 @@ int main(int argc, char **argv)
|
||||
{
|
||||
unsigned int x;
|
||||
if ((x = t/86400))
|
||||
printf("%dd", x);
|
||||
printf("%ud", x);
|
||||
if ((x = (t/3600)%24))
|
||||
printf("%dh", x);
|
||||
printf("%uh", x);
|
||||
if ((x = (t/60)%60))
|
||||
printf("%dm", x);
|
||||
printf("%um", x);
|
||||
if ((x = t%60))
|
||||
printf("%ds", x);
|
||||
printf("%us", x);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ static ssize_t netlink_recv(int fd)
|
||||
msg.msg_flags = 0;
|
||||
while ((rc = recvmsg(fd, &msg, MSG_PEEK)) == -1 && errno == EINTR);
|
||||
|
||||
/* 2.2.x doesn't suport MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
|
||||
/* 2.2.x doesn't support MSG_PEEK at all, returning EOPNOTSUPP, so we just grab a
|
||||
big buffer and pray in that case. */
|
||||
if (rc == -1 && errno == EOPNOTSUPP)
|
||||
{
|
||||
38
contrib/lease-tools/dhcp_release6.1
Normal file
38
contrib/lease-tools/dhcp_release6.1
Normal file
@@ -0,0 +1,38 @@
|
||||
.TH DHCP_RELEASE 1
|
||||
.SH NAME
|
||||
dhcp_release6 \- Release a DHCPv6 lease on a the local dnsmasq DHCP server.
|
||||
.SH SYNOPSIS
|
||||
.B dhcp_release6 --iface <interface> --client-id <client-id> --server-id
|
||||
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
|
||||
.SH "DESCRIPTION"
|
||||
A utility which forces the DHCP server running on this machine to release a
|
||||
DHCPv6 lease.
|
||||
.SS OPTIONS
|
||||
.IP "-a, --ip"
|
||||
IPv6 address to release.
|
||||
.IP "-c, --client-id"
|
||||
Colon-separated hex string representing DHCPv6 client id. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
.IP "-d, --dry-run"
|
||||
Print hexadecimal representation of generated DHCPv6 release packet to standard
|
||||
output and exit.
|
||||
.IP "-h, --help"
|
||||
print usage information to standard output and exit.
|
||||
.IP "-i, --iaid"
|
||||
Decimal representation of DHCPv6 IAID. Normally it can be found in leases file
|
||||
both on client and server.
|
||||
.IP "-n, --iface"
|
||||
Network interface to send a DHCPv6 release packet from.
|
||||
.IP "-s, --server-id"
|
||||
Colon-separated hex string representing DHCPv6 server id. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
.SH NOTES
|
||||
MUST be run as root - will fail otherwise.
|
||||
.SH LIMITATIONS
|
||||
Only usable on IPv6 DHCP leases.
|
||||
.SH SEE ALSO
|
||||
.BR dnsmasq (8)
|
||||
.SH AUTHOR
|
||||
This manual page was written by Simon Kelley <simon@thekelleys.org.uk>.
|
||||
|
||||
|
||||
445
contrib/lease-tools/dhcp_release6.c
Normal file
445
contrib/lease-tools/dhcp_release6.c
Normal file
@@ -0,0 +1,445 @@
|
||||
/*
|
||||
dhcp_release6 --iface <interface> --client-id <client-id> --server-id
|
||||
server-id --iaid <iaid> --ip <IP> [--dry-run] [--help]
|
||||
MUST be run as root - will fail otherwise
|
||||
*/
|
||||
|
||||
/* Send a DHCPRELEASE message to IPv6 multicast address via the specified interface
|
||||
to tell the local DHCP server to delete a particular lease.
|
||||
|
||||
The interface argument is the interface in which a DHCP
|
||||
request _would_ be received if it was coming from the client,
|
||||
rather than being faked up here.
|
||||
|
||||
The client-id argument is colon-separated hex string and mandatory. Normally
|
||||
it can be found in leases file both on client and server
|
||||
|
||||
The server-id argument is colon-separated hex string and mandatory. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
|
||||
The iaid argument is numeric string and mandatory. Normally
|
||||
it can be found in leases file both on client and server.
|
||||
|
||||
IP is an IPv6 address to release
|
||||
|
||||
If --dry-run is specified, dhcp_release6 just prints hexadecimal representation of
|
||||
packet to send to stdout and exits.
|
||||
|
||||
If --help is specified, dhcp_release6 print usage information to stdout and exits
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <getopt.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define NOT_REPLY_CODE 115
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
|
||||
enum DHCP6_TYPES{
|
||||
SOLICIT = 1,
|
||||
ADVERTISE = 2,
|
||||
REQUEST = 3,
|
||||
CONFIRM = 4,
|
||||
RENEW = 5,
|
||||
REBIND = 6,
|
||||
REPLY = 7,
|
||||
RELEASE = 8,
|
||||
DECLINE = 9,
|
||||
RECONFIGURE = 10,
|
||||
INFORMATION_REQUEST = 11,
|
||||
RELAY_FORW = 12,
|
||||
RELAY_REPL = 13
|
||||
|
||||
};
|
||||
enum DHCP6_OPTIONS{
|
||||
CLIENTID = 1,
|
||||
SERVERID = 2,
|
||||
IA_NA = 3,
|
||||
IA_TA = 4,
|
||||
IAADDR = 5,
|
||||
ORO = 6,
|
||||
PREFERENCE = 7,
|
||||
ELAPSED_TIME = 8,
|
||||
RELAY_MSG = 9,
|
||||
AUTH = 11,
|
||||
UNICAST = 12,
|
||||
STATUS_CODE = 13,
|
||||
RAPID_COMMIT = 14,
|
||||
USER_CLASS = 15,
|
||||
VENDOR_CLASS = 16,
|
||||
VENDOR_OPTS = 17,
|
||||
INTERFACE_ID = 18,
|
||||
RECONF_MSG = 19,
|
||||
RECONF_ACCEPT = 20,
|
||||
};
|
||||
|
||||
enum DHCP6_STATUSES{
|
||||
SUCCESS = 0,
|
||||
UNSPEC_FAIL = 1,
|
||||
NOADDR_AVAIL=2,
|
||||
NO_BINDING = 3,
|
||||
NOT_ON_LINK = 4,
|
||||
USE_MULTICAST =5
|
||||
};
|
||||
static struct option longopts[] = {
|
||||
{"ip", required_argument, 0, 'a'},
|
||||
{"server-id", required_argument, 0, 's'},
|
||||
{"client-id", required_argument, 0, 'c'},
|
||||
{"iface", required_argument, 0, 'n'},
|
||||
{"iaid", required_argument, 0, 'i'},
|
||||
{"dry-run", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
const short DHCP6_CLIENT_PORT = 546;
|
||||
const short DHCP6_SERVER_PORT = 547;
|
||||
|
||||
const char* DHCP6_MULTICAST_ADDRESS = "ff02::1:2";
|
||||
|
||||
struct dhcp6_option{
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
char value[1024];
|
||||
};
|
||||
|
||||
struct dhcp6_iaaddr_option{
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
struct in6_addr ip;
|
||||
uint32_t preferred_lifetime;
|
||||
uint32_t valid_lifetime;
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct dhcp6_iana_option{
|
||||
uint16_t type;
|
||||
uint16_t len;
|
||||
uint32_t iaid;
|
||||
uint32_t t1;
|
||||
uint32_t t2;
|
||||
char options[1024];
|
||||
};
|
||||
|
||||
|
||||
struct dhcp6_packet{
|
||||
size_t len;
|
||||
char buf[2048];
|
||||
|
||||
} ;
|
||||
|
||||
size_t pack_duid(const char* str, char* dst){
|
||||
|
||||
char* tmp = strdup(str);
|
||||
char* tmp_to_free = tmp;
|
||||
char *ptr;
|
||||
uint8_t write_pos = 0;
|
||||
while ((ptr = strtok (tmp, ":"))) {
|
||||
dst[write_pos] = (uint8_t) strtol(ptr, NULL, 16);
|
||||
write_pos += 1;
|
||||
tmp = NULL;
|
||||
|
||||
}
|
||||
free(tmp_to_free);
|
||||
return write_pos;
|
||||
}
|
||||
|
||||
struct dhcp6_option create_client_id_option(const char* duid){
|
||||
struct dhcp6_option option;
|
||||
option.type = htons(CLIENTID);
|
||||
bzero(option.value, sizeof(option.value));
|
||||
option.len = htons(pack_duid(duid, option.value));
|
||||
return option;
|
||||
}
|
||||
|
||||
struct dhcp6_option create_server_id_option(const char* duid){
|
||||
struct dhcp6_option option;
|
||||
option.type = htons(SERVERID);
|
||||
bzero(option.value, sizeof(option.value));
|
||||
option.len = htons(pack_duid(duid, option.value));
|
||||
return option;
|
||||
}
|
||||
|
||||
struct dhcp6_iaaddr_option create_iaadr_option(const char* ip){
|
||||
struct dhcp6_iaaddr_option result;
|
||||
result.type =htons(IAADDR);
|
||||
/* no suboptions needed here, so length is 24 */
|
||||
result.len = htons(24);
|
||||
result.preferred_lifetime = 0;
|
||||
result.valid_lifetime = 0;
|
||||
int s = inet_pton(AF_INET6, ip, &(result.ip));
|
||||
if (s <= 0) {
|
||||
if (s == 0)
|
||||
fprintf(stderr, "Not in presentation format");
|
||||
else
|
||||
perror("inet_pton");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
struct dhcp6_iana_option create_iana_option(const char * iaid, struct dhcp6_iaaddr_option ia_addr){
|
||||
struct dhcp6_iana_option result;
|
||||
result.type = htons(IA_NA);
|
||||
result.iaid = htonl(atoi(iaid));
|
||||
result.t1 = 0;
|
||||
result.t2 = 0;
|
||||
result.len = htons(12 + ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||
memcpy(result.options, &ia_addr, ntohs(ia_addr.len) + 2 * sizeof(uint16_t));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct dhcp6_packet create_release_packet(const char* iaid, const char* ip, const char* client_id, const char* server_id){
|
||||
struct dhcp6_packet result;
|
||||
bzero(result.buf, sizeof(result.buf));
|
||||
/* message_type */
|
||||
result.buf[0] = RELEASE;
|
||||
/* tx_id */
|
||||
bzero(result.buf+1, 3);
|
||||
|
||||
struct dhcp6_option client_option = create_client_id_option(client_id);
|
||||
struct dhcp6_option server_option = create_server_id_option(server_id);
|
||||
struct dhcp6_iaaddr_option iaaddr_option = create_iaadr_option(ip);
|
||||
struct dhcp6_iana_option iana_option = create_iana_option(iaid, iaaddr_option);
|
||||
int offset = 4;
|
||||
memcpy(result.buf + offset, &client_option, ntohs(client_option.len) + 2*sizeof(uint16_t));
|
||||
offset += (ntohs(client_option.len)+ 2 *sizeof(uint16_t) );
|
||||
memcpy(result.buf + offset, &server_option, ntohs(server_option.len) + 2*sizeof(uint16_t) );
|
||||
offset += (ntohs(server_option.len)+ 2* sizeof(uint16_t));
|
||||
memcpy(result.buf + offset, &iana_option, ntohs(iana_option.len) + 2*sizeof(uint16_t) );
|
||||
offset += (ntohs(iana_option.len)+ 2* sizeof(uint16_t));
|
||||
result.len = offset;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t parse_iana_suboption(char* buf, size_t len){
|
||||
size_t current_pos = 0;
|
||||
char option_value[1024];
|
||||
while (current_pos < len) {
|
||||
uint16_t option_type, option_len;
|
||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||
option_type = ntohs(option_type);
|
||||
option_len = ntohs(option_len);
|
||||
current_pos += 2 * sizeof(uint16_t);
|
||||
if (option_type == STATUS_CODE){
|
||||
uint16_t status;
|
||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||
status = ntohs(status);
|
||||
if (status != SUCCESS){
|
||||
memcpy(option_value, buf + current_pos + sizeof(uint16_t) , option_len - sizeof(uint16_t));
|
||||
option_value[option_len-sizeof(uint16_t)] ='\0';
|
||||
fprintf(stderr, "Error: %s\n", option_value);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int16_t parse_packet(char* buf, size_t len){
|
||||
uint8_t type = buf[0];
|
||||
/*skipping tx id. you need it, uncomment following line
|
||||
uint16_t tx_id = ntohs((buf[1] <<16) + (buf[2] <<8) + buf[3]);
|
||||
*/
|
||||
size_t current_pos = 4;
|
||||
if (type != REPLY ){
|
||||
return NOT_REPLY_CODE;
|
||||
}
|
||||
char option_value[1024];
|
||||
while (current_pos < len) {
|
||||
uint16_t option_type, option_len;
|
||||
memcpy(&option_type,buf + current_pos, sizeof(uint16_t));
|
||||
memcpy(&option_len,buf + current_pos + sizeof(uint16_t), sizeof(uint16_t));
|
||||
option_type = ntohs(option_type);
|
||||
option_len = ntohs(option_len);
|
||||
current_pos += 2 * sizeof(uint16_t);
|
||||
if (option_type == STATUS_CODE){
|
||||
uint16_t status;
|
||||
memcpy(&status, buf + current_pos, sizeof(uint16_t));
|
||||
status = ntohs(status);
|
||||
if (status != SUCCESS){
|
||||
memcpy(option_value, buf + current_pos +sizeof(uint16_t) , option_len -sizeof(uint16_t));
|
||||
fprintf(stderr, "Error: %d %s\n", status, option_value);
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
int send_release_packet(const char* iface, struct dhcp6_packet* packet){
|
||||
|
||||
struct sockaddr_in6 server_addr, client_addr;
|
||||
char response[1400];
|
||||
int sock = socket(PF_INET6, SOCK_DGRAM, 0);
|
||||
int i = 0;
|
||||
if (sock < 0) {
|
||||
perror("creating socket");
|
||||
return -1;
|
||||
}
|
||||
if (setsockopt(sock, SOL_SOCKET, 25, iface, strlen(iface)) == -1) {
|
||||
perror("SO_BINDTODEVICE");
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
server_addr.sin6_family = AF_INET6;
|
||||
client_addr.sin6_family = AF_INET6;
|
||||
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
|
||||
client_addr.sin6_flowinfo = 0;
|
||||
client_addr.sin6_scope_id =0;
|
||||
inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
|
||||
bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
|
||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||
int16_t recv_size = 0;
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (sendto(sock, packet->buf, packet->len, 0,
|
||||
(struct sockaddr *)&server_addr,
|
||||
sizeof(server_addr)) < 0) {
|
||||
perror("sendto failed");
|
||||
exit(4);
|
||||
}
|
||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||
if (recv_size == -1){
|
||||
if (errno == EAGAIN){
|
||||
sleep(1);
|
||||
continue;
|
||||
}else {
|
||||
perror("recvfrom");
|
||||
}
|
||||
}
|
||||
int16_t result = parse_packet(response, recv_size);
|
||||
if (result == NOT_REPLY_CODE){
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
fprintf(stderr, "Response timed out\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char * const argv[]) {
|
||||
const char* UNINITIALIZED = "";
|
||||
const char* iface = UNINITIALIZED;
|
||||
const char* ip = UNINITIALIZED;
|
||||
const char* client_id = UNINITIALIZED;
|
||||
const char* server_id = UNINITIALIZED;
|
||||
const char* iaid = UNINITIALIZED;
|
||||
int dry_run = 0;
|
||||
while (1) {
|
||||
int option_index = 0;
|
||||
int c = getopt_long(argc, argv, "a:s:c:n:i:hd", longopts, &option_index);
|
||||
if (c == -1){
|
||||
break;
|
||||
}
|
||||
switch(c){
|
||||
case 0:
|
||||
if (longopts[option_index].flag !=0){
|
||||
break;
|
||||
}
|
||||
printf ("option %s", longopts[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
case 'i':
|
||||
iaid = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
iface = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
ip = optarg;
|
||||
break;
|
||||
case 'c':
|
||||
client_id = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
dry_run = 1;
|
||||
break;
|
||||
case 's':
|
||||
server_id = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
usage(argv[0], stdout);
|
||||
return 0;
|
||||
case '?':
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
default:
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (iaid == UNINITIALIZED){
|
||||
fprintf(stderr, "Missing required iaid parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
if (server_id == UNINITIALIZED){
|
||||
fprintf(stderr, "Missing required server-id parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
if (client_id == UNINITIALIZED){
|
||||
fprintf(stderr, "Missing required client-id parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
if (ip == UNINITIALIZED){
|
||||
fprintf(stderr, "Missing required ip parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
if (iface == UNINITIALIZED){
|
||||
fprintf(stderr, "Missing required iface parameter\n");
|
||||
usage(argv[0], stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct dhcp6_packet packet = create_release_packet(iaid, ip, client_id, server_id);
|
||||
if (dry_run){
|
||||
uint16_t i;
|
||||
for(i=0;i<packet.len;i++){
|
||||
printf("%hhx", packet.buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
return send_release_packet(iface, &packet);
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
# first column of this file, then a DNAT port-forward will be set up
|
||||
# to the address which has just been allocated by DHCP . The second field
|
||||
# is port number(s). If there is only one, then the port-forward goes to
|
||||
# the same port on the DHCP-client, if there are two seperated with a
|
||||
# the same port on the DHCP-client, if there are two separated with a
|
||||
# colon, then the second number is the port to which the connection
|
||||
# is forwarded on the DHCP-client. By default, forwarding is set up
|
||||
# for TCP, but it can done for UDP instead by prefixing the port to "u".
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The script reads stdin and replaces all IP addresses with names before
|
||||
outputting it again. IPs from private networks are reverse looked up
|
||||
via dns. Other IP adresses are searched for in the dnsmasq query log.
|
||||
via dns. Other IP addresses are searched for in the dnsmasq query log.
|
||||
This gives names (CNAMEs if I understand DNS correctly) that are closer
|
||||
to the name the client originally asked for then the names obtained by
|
||||
reverse lookup. Just run
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
# Parses stdin for IP4 addresses and replaces them
|
||||
# with names retrieved by parsing the dnsmasq log.
|
||||
# This currently only gives CNAMEs. But these
|
||||
# usually tell ou more than the mones from reverse
|
||||
# usually tell you more than the ones from reverse
|
||||
# lookups.
|
||||
#
|
||||
# This has been tested on debian and asuswrt. Plese
|
||||
# This has been tested on debian and asuswrt. Please
|
||||
# report successful tests on other platforms.
|
||||
#
|
||||
# Author: Joachim Zobel <jz-2014@heute-morgen.de>
|
||||
|
||||
@@ -2,7 +2,7 @@ A remake of patch Bob Carroll had posted to dnsmasq,
|
||||
now compatible with version 2.47. Hopefully he doesn't
|
||||
mind (sending a copy of this mail to him too).
|
||||
|
||||
Maybe the patch in question is not acceptible
|
||||
Maybe the patch in question is not acceptable
|
||||
as it doesn't add new switch, rather it binds itself to "strict-order".
|
||||
|
||||
What it does is: if you have strict-order in the
|
||||
|
||||
10
contrib/try-all-ns/README-2.78
Normal file
10
contrib/try-all-ns/README-2.78
Normal file
@@ -0,0 +1,10 @@
|
||||
Hi,
|
||||
I updated the try-all-ns patch to work with the latest version of git. Ended up implementing it on top of master, 2.78test2-7-g63437ff. As that specific if-clause has been changed in the last few commits, it's not compatible for 2.77, sadly.
|
||||
|
||||
Find the patch attached.
|
||||
|
||||
Regards,
|
||||
|
||||
Rasmus Ahlberg
|
||||
Software Developer, R&D
|
||||
Electrolux Small Appliances
|
||||
20
contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch
Normal file
20
contrib/try-all-ns/dnsmasq-2.78xx-try-all-ns.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
diff --git a/src/forward.c b/src/forward.c
|
||||
index e3fa94b..ecf3b98 100644
|
||||
--- a/src/forward.c
|
||||
+++ b/src/forward.c
|
||||
@@ -789,9 +789,12 @@ void reply_query(int fd, int family, time_t now)
|
||||
|
||||
/* Note: if we send extra options in the EDNS0 header, we can't recreate
|
||||
the query from the reply. */
|
||||
- if (RCODE(header) == REFUSED &&
|
||||
- forward->forwardall == 0 &&
|
||||
- !(forward->flags & FREC_HAS_EXTRADATA))
|
||||
+ if ((RCODE(header) == REFUSED &&
|
||||
+ forward->forwardall == 0 &&
|
||||
+ !(forward->flags & FREC_HAS_EXTRADATA)) ||
|
||||
+ /* If strict-order is set, try next server on NXDOMAIN reply */
|
||||
+ (RCODE(header) == NXDOMAIN && option_bool(OPT_ORDER) &&
|
||||
+ server->next != NULL))
|
||||
/* for broken servers, attempt to send to another one. */
|
||||
{
|
||||
unsigned char *pheader;
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
This is the README for the DNSmasq webmin module.
|
||||
This is the README for the Dnsmasq webmin module.
|
||||
|
||||
Problems:
|
||||
|
||||
@@ -48,7 +48,7 @@ wade through the config file and man pages again.
|
||||
|
||||
If you modify it, or add a language file, and you have a spare moment,
|
||||
please e-mail me - I won't be upset at all if you fix my poor coding!
|
||||
(rather the opposite - I'd be pleased someone found it usefull)
|
||||
(rather the opposite - I'd be pleased someone found it useful)
|
||||
|
||||
Cheers,
|
||||
Neil Fisher <neil@magnecor.com.au>
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
CFLAGS?= -O2 -Wall -W
|
||||
|
||||
all: dhcp_release dhcp_lease_time
|
||||
|
||||
clean:
|
||||
rm -f *~ *.o core dhcp_release dhcp_lease_time
|
||||
@@ -4,7 +4,7 @@ reboot, then it will eventually be restored as hosts renew their
|
||||
leases. Until a host renews (which may take hours/days) it will
|
||||
not exist in the DNS if dnsmasq's DDNS function is in use.
|
||||
|
||||
*WRT systems remount all non-volatile fileystems read-only after boot,
|
||||
*WRT systems remount all non-volatile filesystems read-only after boot,
|
||||
so the normal leasefile will not work. They do, however have NV
|
||||
storage, accessed with the nvram command:
|
||||
|
||||
@@ -62,7 +62,7 @@ about 100 bytes, so restricting the number of leases to 50 will limit
|
||||
use to half that. (The default limit in the distributed source is 150)
|
||||
|
||||
Any UI script which reads the dnsmasq leasefile will have to be
|
||||
ammended, probably by changing it to read the output of
|
||||
amended, probably by changing it to read the output of
|
||||
`lease_update init` instead.
|
||||
|
||||
|
||||
|
||||
121
debian/changelog
vendored
121
debian/changelog
vendored
@@ -1,8 +1,103 @@
|
||||
dnsmasq (2.78-1) unstable; urgency=high
|
||||
|
||||
* New upstream.
|
||||
Security fixes for CVE-2017-13704 (closes: #877102)
|
||||
Security fixes for CVE-2017-14491 - CVE-2017-14496 inclusive.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 29 Sep 2017 21:34:00 +0000
|
||||
|
||||
dnsmasq (2.77-2) unstable; urgency=low
|
||||
|
||||
* Improve sed regexp for parsing root.ds.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 5 Jun 2017 20:46:32 +0000
|
||||
|
||||
dnsmasq (2.77-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
* Don't register as a resolvconf source when config file
|
||||
includes port=0 to disable DNS.
|
||||
* Handle gratuitous format change in /usr/share/dns/root.ds
|
||||
(closes: #858506) (closes: #860064)
|
||||
* Add lsb-base dependancy.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Tue, 11 Apr 2017 14:19:20 +0000
|
||||
|
||||
dnsmasq (2.76-5) unstable; urgency=medium
|
||||
|
||||
* Nail libnettle dependency to avoid ABI incompatibility.
|
||||
(closes: #846642)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 14 Dec 2016 17:58:10 +0000
|
||||
|
||||
dnsmasq (2.76-4.1) unstable; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* Add two upstream patches to fix binding to an interface being
|
||||
destroyed and recreated. Closes: #834722.
|
||||
+ 2675f2061525bc954be14988d64384b74aa7bf8b
|
||||
+ 16800ea072dd0cdf14d951c4bb8d2808b3dfe53d
|
||||
|
||||
-- Vincent Bernat <bernat@debian.org> Sat, 26 Nov 2016 20:15:34 +0100
|
||||
|
||||
dnsmasq (2.76-4) unstable; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* Fix FTCBFS: Use triplet-prefixed tools. (closes: #836072)
|
||||
|
||||
-- Helmut Grohne <helmut@subdivi.de> Tue, 30 Aug 2016 13:59:12 +0200
|
||||
|
||||
dnsmasq (2.76-3) unstable; urgency=medium
|
||||
|
||||
* Bump auth zone serial on SIGHUP. (closes: #833733)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 13 Aug 2016 21:43:10 +0000
|
||||
|
||||
dnsmasq (2.76-2) unstable; urgency=medium
|
||||
|
||||
* Fix to systemd to fix failure to start with bridge interface.
|
||||
(Closes: #831372)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 16 Jul 2016 22:09:10 +0000
|
||||
|
||||
dnsmasq (2.76-1.2) unstable; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* dnsmasq: Install marker file to determine package installed state,
|
||||
for the benefit of the init script. (Closes: #819856)
|
||||
|
||||
-- Christian Hofstaedtler <zeha@debian.org> Sat, 16 Jul 2016 00:17:57 +0000
|
||||
|
||||
dnsmasq (2.76-1.1) unstable; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* Provide nss-lookup.target for systemd, without relying on insserv.
|
||||
Patch from Michael Biebl <biebl@debian.org>. (Closes: #826242)
|
||||
|
||||
-- Christian Hofstaedtler <zeha@debian.org> Fri, 01 Jul 2016 13:41:11 +0000
|
||||
|
||||
dnsmasq (2.76-1) unstable; urgency=low
|
||||
|
||||
* New upstream. (closes: #798586)
|
||||
* Use /run/dnsmasq directly, rather than relying on link from /var/run
|
||||
to avoid problems before /var is mounted. (closes: #800351)
|
||||
* Test for the existence of /usr/share/doc/dnsmasq rather then
|
||||
/etc/dnsmasq.d/README in the daemon startup script. (closes: #819856)
|
||||
* Add --help to manpage and mention dhcp6 in summary. (closes: #821226)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 10 Sep 2015 23:07:21 +0000
|
||||
|
||||
dnsmasq (2.75-1) unstable; urgency=low
|
||||
|
||||
* New upstream. (closes: #794095)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 30 Jul 2015 20:58:31 +0000
|
||||
|
||||
dnsmasq (2.74-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:54:11 +0000
|
||||
* New upstream. (LP: #1468611)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 15 Jul 2015 21:54:11 +0000
|
||||
|
||||
dnsmasq (2.73-2) unstable; urgency=low
|
||||
|
||||
@@ -28,7 +123,7 @@ dnsmasq (2.72-3) unstable; urgency=medium
|
||||
work without it. (Closes: #769486, #776530)
|
||||
- debian/init: when called with systemd-exec argument, let dnsmasq
|
||||
go into the background, so Type=forking can detect when it is ready
|
||||
* Remove line containing only whitespace in debian/contol.
|
||||
* Remove line containing only whitespace in debian/control.
|
||||
(closes: #777571)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 11 Feb 2015 21:56:12 +0000
|
||||
@@ -640,7 +735,7 @@ dnsmasq (2.26-1) unstable; urgency=high
|
||||
dnsmasq (2.25-1) unstable; urgency=low
|
||||
|
||||
* Remove bashisms in postinst and prerm scripts.
|
||||
* Remove misconcieved dependency on locales.
|
||||
* Remove misconceived dependency on locales.
|
||||
* Depend on adduser.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 01 Dec 2005 21:02:12 +0000
|
||||
@@ -662,7 +757,7 @@ dnsmasq (2.23-1) unstable; urgency=low
|
||||
* Add support for DNSMASQ_EXCEPT in /etc/defaults/dnsmasq.
|
||||
putting "lo" in this also disables resolvconf support.
|
||||
* No longer delete pre-existing /etc/init.d symlinks. The
|
||||
change in default runlevels which neccesitated this
|
||||
change in default runlevels which necessitated this
|
||||
is now ancient history and anyway the startup script now
|
||||
behaves when called twice. (closes: #312111)
|
||||
* Tightened config-file parser. (closes: #317030)
|
||||
@@ -847,7 +942,7 @@ dnsmasq (2.6-3) unstable; urgency=low
|
||||
|
||||
* Removed reload command from start script and moved force-reload
|
||||
to be equivalent to restart. This is needed to be policy compliant
|
||||
since SIHGUP doesn't cause dnsmasq to reload its configuration file,
|
||||
since SIGHUP doesn't cause dnsmasq to reload its configuration file,
|
||||
only the /etc/hosts, /etc/resolv.conf etc. (closes: #244208)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 18 Apr 2004 14:40:51 +0000
|
||||
@@ -937,8 +1032,8 @@ dnsmasq (2.0-1) unstable; urgency=low
|
||||
* New upstream: This removes the ability to read the
|
||||
the leases file of ISC DHCP and replaces it with a built-in
|
||||
DHCP server. Apologies in advance for breaking backwards
|
||||
compatibilty, but this replaces a bit of a hack (the ISC stuff)
|
||||
with a nicely engineered and much more apropriate solution.
|
||||
compatibility, but this replaces a bit of a hack (the ISC stuff)
|
||||
with a nicely engineered and much more appropriate solution.
|
||||
Wearing my upstream-maintainer hat, I want to lose the hack now,
|
||||
rather than have to support it into Sarge.
|
||||
* New upstream closes some bugs since they become
|
||||
@@ -964,7 +1059,7 @@ dnsmasq (1.18-1) unstable; urgency=low
|
||||
* New upstream which does round-robin. (closes: #215460)
|
||||
* Removed conflicts with other dns servers since it is now
|
||||
possible to control exactly where dnsmasq listens on multi-homed
|
||||
hosts, making co-existance with another nameserver
|
||||
hosts, making co-existence with another nameserver
|
||||
a viable proposition. (closes #176163)
|
||||
* New upstream allows _ in hostnames and check for illegal
|
||||
names in /etc/hosts. (closes: #218842)
|
||||
@@ -1050,13 +1145,13 @@ dnsmasq (1.11-2) unstable; urgency=low
|
||||
|
||||
dnsmasq (1.11-1) unstable; urgency=low
|
||||
|
||||
* New uptream.
|
||||
* New upstream.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Tues, 12 Jan 2003 22:25:17 -0100
|
||||
|
||||
dnsmasq (1.10-1) unstable; urgency=low
|
||||
|
||||
* New uptream.
|
||||
* New upstream.
|
||||
* Force service to stop in postinst before restarting. I don't
|
||||
understand the circumstances under which it would still be running at
|
||||
this point, but this is the correct fix anyway. (closes: #169718)
|
||||
@@ -1068,7 +1163,7 @@ dnsmasq (1.10-1) unstable; urgency=low
|
||||
|
||||
dnsmasq (1.9-1) unstable; urgency=low
|
||||
|
||||
* New uptream.
|
||||
* New upstream.
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 23 Sept 2002 21:35:07 -0100
|
||||
|
||||
|
||||
4
debian/control
vendored
4
debian/control
vendored
@@ -5,12 +5,12 @@ Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
||||
libidn11-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||
nettle-dev (>=2.4-3), libbsd-dev [!linux-any]
|
||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||
Standards-Version: 3.9.5
|
||||
Standards-Version: 3.9.8
|
||||
|
||||
Package: dnsmasq
|
||||
Architecture: all
|
||||
Depends: netbase, dnsmasq-base(>= ${binary:Version}),
|
||||
init-system-helpers (>= 1.18~)
|
||||
init-system-helpers (>= 1.18~), lsb-base (>= 3.0-6)
|
||||
Suggests: resolvconf
|
||||
Conflicts: resolvconf (<<1.15)
|
||||
Description: Small caching DNS proxy and DHCP/TFTP server
|
||||
|
||||
2
debian/copyright
vendored
2
debian/copyright
vendored
@@ -1,4 +1,4 @@
|
||||
dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
dnsmasq is Copyright (c) 2000-2016 Simon Kelley
|
||||
|
||||
It was downloaded from: http://www.thekelleys.org.uk/dnsmasq/
|
||||
|
||||
|
||||
6
debian/dnsmasq-base.postinst
vendored
6
debian/dnsmasq-base.postinst
vendored
@@ -17,8 +17,8 @@ if [ "$1" = "configure" ]; then
|
||||
# dnsmasq-base, but it's much easier to create it here so that
|
||||
# we don't have synchronisation issues with the creation of the
|
||||
# dnsmasq user.
|
||||
if [ ! -d /var/run/dnsmasq ]; then
|
||||
mkdir /var/run/dnsmasq
|
||||
chown dnsmasq:nogroup /var/run/dnsmasq
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq
|
||||
chown dnsmasq:nogroup /run/dnsmasq
|
||||
fi
|
||||
fi
|
||||
|
||||
2
debian/dnsmasq-base.postrm
vendored
2
debian/dnsmasq-base.postrm
vendored
@@ -7,5 +7,5 @@ if [ purge = "$1" ]; then
|
||||
else
|
||||
echo >&2 "not removing dnsmasq system account because deluser command was not found"
|
||||
fi
|
||||
rm -rf /var/run/dnsmasq
|
||||
rm -rf /run/dnsmasq
|
||||
fi
|
||||
|
||||
59
debian/init
vendored
59
debian/init
vendored
@@ -8,7 +8,8 @@
|
||||
# Description: DHCP and DNS server
|
||||
### END INIT INFO
|
||||
|
||||
set +e # Don't exit on error status
|
||||
# Don't exit on error status
|
||||
set +e
|
||||
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
DAEMON=/usr/sbin/dnsmasq
|
||||
@@ -29,12 +30,11 @@ if [ -r /etc/default/locale ]; then
|
||||
export LANG
|
||||
fi
|
||||
|
||||
# /etc/dnsmasq.d/README is a non-conffile installed by the dnsmasq package.
|
||||
# Should the dnsmasq package be removed, the following test ensures that
|
||||
# the daemon is no longer started, even if the dnsmasq-base package is
|
||||
# still in place.
|
||||
test -e /etc/dnsmasq.d/README || exit 0
|
||||
|
||||
# The following test ensures the dnsmasq service is not started, when the
|
||||
# package 'dnsmasq' is removed but not purged, even if the dnsmasq-base
|
||||
# package is still in place.
|
||||
test -e /usr/share/dnsmasq/installed-marker || exit 0
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
# Provide skeleton LSB log functions for backports which don't have LSB functions.
|
||||
@@ -81,7 +81,7 @@ if [ ! "$RESOLV_CONF" ] &&
|
||||
[ "$IGNORE_RESOLVCONF" != "yes" ] &&
|
||||
[ -x /sbin/resolvconf ]
|
||||
then
|
||||
RESOLV_CONF=/var/run/dnsmasq/resolv.conf
|
||||
RESOLV_CONF=/run/dnsmasq/resolv.conf
|
||||
fi
|
||||
|
||||
for INTERFACE in $DNSMASQ_INTERFACE; do
|
||||
@@ -111,7 +111,7 @@ DNSMASQ_OPTS="$DNSMASQ_OPTS --local-service"
|
||||
ROOT_DS="/usr/share/dns/root.ds"
|
||||
|
||||
if [ -f $ROOT_DS ]; then
|
||||
DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -e s/". IN DS "/--trust-anchor=.,/ -e s/" "/,/g $ROOT_DS | tr '\n' ' '`"
|
||||
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' ' '`"
|
||||
fi
|
||||
|
||||
start()
|
||||
@@ -121,16 +121,16 @@ start()
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
|
||||
# /var/run may be volatile, so we need to ensure that
|
||||
# /var/run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /var/run/dnsmasq ]; then
|
||||
mkdir /var/run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
|
||||
# /run may be volatile, so we need to ensure that
|
||||
# /run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||
fi
|
||||
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON -- \
|
||||
-x /var/run/dnsmasq/$NAME.pid \
|
||||
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.pid --exec $DAEMON -- \
|
||||
-x /run/dnsmasq/$NAME.pid \
|
||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||
${MAILTARGET:+ -t $MAILTARGET} \
|
||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||
@@ -154,6 +154,11 @@ start_resolvconf()
|
||||
[ $interface = lo ] && return
|
||||
done
|
||||
|
||||
# Also skip this if DNS functionality is disabled in /etc/dnsmasq.conf
|
||||
if grep -qs '^port=0' /etc/dnsmasq.conf; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [ -x /sbin/resolvconf ] ; then
|
||||
echo "nameserver 127.0.0.1" | /sbin/resolvconf -a lo.$NAME
|
||||
fi
|
||||
@@ -167,7 +172,7 @@ stop()
|
||||
# 1 if daemon was already stopped
|
||||
# 2 if daemon could not be stopped
|
||||
# other if a failure occurred
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /var/run/dnsmasq/$NAME.pid --name $NAME
|
||||
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /run/dnsmasq/$NAME.pid --name $NAME
|
||||
}
|
||||
|
||||
stop_resolvconf()
|
||||
@@ -185,9 +190,9 @@ status()
|
||||
# 1 if daemon is dead and pid file exists
|
||||
# 3 if daemon is not running
|
||||
# 4 if daemon status is unknown
|
||||
start-stop-daemon --start --quiet --pidfile /var/run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null
|
||||
case "$?" in
|
||||
0) [ -e "/var/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
|
||||
0) [ -e "/run/dnsmasq/$NAME.pid" ] && return 1 ; return 3 ;;
|
||||
1) return 0 ;;
|
||||
*) return 4 ;;
|
||||
esac
|
||||
@@ -278,7 +283,7 @@ case "$1" in
|
||||
esac
|
||||
;;
|
||||
dump-stats)
|
||||
kill -s USR1 `cat /var/run/dnsmasq/$NAME.pid`
|
||||
kill -s USR1 `cat /run/dnsmasq/$NAME.pid`
|
||||
;;
|
||||
systemd-start-resolvconf)
|
||||
start_resolvconf
|
||||
@@ -287,13 +292,13 @@ case "$1" in
|
||||
stop_resolvconf
|
||||
;;
|
||||
systemd-exec)
|
||||
# /var/run may be volatile, so we need to ensure that
|
||||
# /var/run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /var/run/dnsmasq ]; then
|
||||
mkdir /var/run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /var/run/dnsmasq || return 2
|
||||
# /run may be volatile, so we need to ensure that
|
||||
# /run/dnsmasq exists here as well as in postinst
|
||||
if [ ! -d /run/dnsmasq ]; then
|
||||
mkdir /run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||
fi
|
||||
exec $DAEMON -x /var/run/dnsmasq/$NAME.pid \
|
||||
exec $DAEMON -x /run/dnsmasq/$NAME.pid \
|
||||
${MAILHOSTNAME:+ -m $MAILHOSTNAME} \
|
||||
${MAILTARGET:+ -t $MAILTARGET} \
|
||||
${DNSMASQ_USER:+ -u $DNSMASQ_USER} \
|
||||
|
||||
2
debian/installed-marker
vendored
Normal file
2
debian/installed-marker
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file indicates dnsmasq (and not just dnsmasq-base) is installed.
|
||||
# It is an implementation detail of the dnsmasq init script.
|
||||
2
debian/postinst
vendored
2
debian/postinst
vendored
@@ -21,7 +21,7 @@ if [ -x /etc/init.d/dnsmasq ]; then
|
||||
update-rc.d dnsmasq defaults 15 85 >/dev/null
|
||||
|
||||
if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
|
||||
if [ -e /var/run/dnsmasq/dnsmasq.pid ]; then
|
||||
if [ -e /run/dnsmasq/dnsmasq.pid ]; then
|
||||
ACTION=restart
|
||||
else
|
||||
ACTION=start
|
||||
|
||||
4
debian/readme
vendored
4
debian/readme
vendored
@@ -31,7 +31,7 @@ Notes on configuring dnsmasq as packaged for Debian.
|
||||
as the first nameserver address in /etc/resolv.conf.
|
||||
|
||||
(6) In the absence of resolvconf, dns-nameservers lines in
|
||||
/etc/network/interfaces are ignored. If you do do not use
|
||||
/etc/network/interfaces are ignored. If you do not use
|
||||
resolvconf, list 127.0.0.1 as the first nameserver address
|
||||
in /etc/resolv.conf and configure your nameservers using
|
||||
"server=<IP-address>" lines in /etc/dnsmasq.conf.
|
||||
@@ -66,7 +66,7 @@ Notes on configuring dnsmasq as packaged for Debian.
|
||||
combined with noi18n to be effective.
|
||||
gitversion : set the version of the produced packages from the
|
||||
git-derived versioning information on the source,
|
||||
rather the the debian changelog.
|
||||
rather than the debian changelog.
|
||||
|
||||
(9) Dnsmasq comes as three packages - dnsmasq-utils, dnsmasq-base and
|
||||
dnsmasq. Dnsmasq-base provides the dnsmasq executable and
|
||||
|
||||
2
debian/resolvconf
vendored
2
debian/resolvconf
vendored
@@ -13,7 +13,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
RUN_DIR="/var/run/dnsmasq"
|
||||
RUN_DIR="/run/dnsmasq"
|
||||
RSLVRLIST_FILE="${RUN_DIR}/resolv.conf"
|
||||
TMP_FILE="${RSLVRLIST_FILE}_new.$$"
|
||||
MY_NAME_FOR_RESOLVCONF="dnsmasq"
|
||||
|
||||
49
debian/rules
vendored
49
debian/rules
vendored
@@ -11,7 +11,7 @@
|
||||
|
||||
package=dnsmasq-base
|
||||
|
||||
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all" dpkg-buildflags
|
||||
dpkg_buildflags := DEB_BUILD_MAINT_OPTIONS="hardening=+all,+pie,+bindnow" dpkg-buildflags
|
||||
|
||||
CFLAGS = $(shell $(dpkg_buildflags) --get CFLAGS)
|
||||
CFLAGS += $(shell $(dpkg_buildflags) --get CPPFLAGS)
|
||||
@@ -24,8 +24,21 @@ DEB_COPTS = $(COPTS)
|
||||
TARGET = install-i18n
|
||||
|
||||
DEB_HOST_ARCH_OS := $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
|
||||
DEB_HOST_GNU_TYPE := $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
BUILD_DATE := $(shell dpkg-parsechangelog --show-field Date)
|
||||
|
||||
ifeq ($(origin CC),default)
|
||||
CC = $(DEB_HOST_GNU_TYPE)-gcc
|
||||
endif
|
||||
|
||||
# Support non-cross-builds on systems without gnu-triplet-binaries for pkg-config.
|
||||
ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
|
||||
PKG_CONFIG=pkg-config
|
||||
else
|
||||
PKG_CONFIG=$(DEB_HOST_GNU_TYPE)-pkg-config
|
||||
endif
|
||||
|
||||
# Force package version based on git tags.
|
||||
ifneq (,$(filter gitversion,$(DEB_BUILD_OPTIONS)))
|
||||
PACKAGE_VERSION = $(shell bld/get-version `pwd` | sed 's/test/~&/; s/[a-z]/~&/; s/-/./g; s/$$/-1/; s/^/-v/';)
|
||||
@@ -35,6 +48,10 @@ ifeq (,$(filter nodbus,$(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_DBUS
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_IDN
|
||||
endif
|
||||
|
||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
DEB_COPTS += -DHAVE_CONNTRACK
|
||||
@@ -71,9 +88,6 @@ endif
|
||||
|
||||
ifneq (,$(filter noi18n,$(DEB_BUILD_OPTIONS)))
|
||||
TARGET = install
|
||||
ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
||||
DEB_COPTS += -DHAVE_IDN
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq (,$(filter uselua,$(DEB_BUILD_OPTIONS)))
|
||||
@@ -93,7 +107,7 @@ clean:
|
||||
$(checkdir)
|
||||
rm -rf debian/daemon debian/base debian/utils debian/*~ debian/files debian/substvars debian/utils-substvars
|
||||
make clean
|
||||
make -C contrib/wrt clean
|
||||
make -C contrib/lease-tools clean
|
||||
|
||||
binary-indep: checkroot
|
||||
$(checkdir)
|
||||
@@ -105,6 +119,7 @@ binary-indep: checkroot
|
||||
-d debian/daemon/etc/dnsmasq.d \
|
||||
-d debian/daemon/etc/resolvconf/update.d \
|
||||
-d debian/daemon/usr/lib/resolvconf/dpkg-event.d \
|
||||
-d debian/daemon/usr/share/dnsmasq \
|
||||
-d debian/daemon/etc/default \
|
||||
-d debian/daemon/lib/systemd/system \
|
||||
-d debian/daemon/etc/insserv.conf.d
|
||||
@@ -113,6 +128,7 @@ binary-indep: checkroot
|
||||
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
|
||||
@@ -134,10 +150,9 @@ binary-arch: checkroot
|
||||
-d debian/base/etc/dbus-1/system.d \
|
||||
-d debian/base/usr/share/doc/$(package) \
|
||||
-d debian/base/usr/share/doc/$(package)/examples \
|
||||
-d debian/base/var/run \
|
||||
-d debian/base/usr/share/$(package) \
|
||||
-d debian/base/var/lib/misc
|
||||
make $(TARGET) PREFIX=/usr DESTDIR=`pwd`/debian/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
||||
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.
|
||||
sed -e /\<H2\>Donations/Q -e /icon.png/d doc.html -e /favicon.ico/d >debian/base/usr/share/doc/$(package)/doc.html
|
||||
@@ -169,7 +184,7 @@ endif
|
||||
fi \
|
||||
done
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/base/usr/sbin/dnsmasq
|
||||
endif
|
||||
cd debian/base && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps --warnings=1 debian/base/usr/sbin/dnsmasq
|
||||
@@ -185,19 +200,23 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||
-d debian/utils/usr/share/man/man1 \
|
||||
-d debian/utils/usr/bin \
|
||||
-d debian/utils/usr/share/doc/dnsmasq-utils
|
||||
make -C contrib/wrt PREFIX=/usr DESTDIR=`pwd`/debian/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=gcc
|
||||
install -m 755 contrib/wrt/dhcp_release debian/utils/usr/bin/dhcp_release
|
||||
install -m 644 contrib/wrt/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
||||
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 contrib/lease-tools/dhcp_release debian/utils/usr/bin/dhcp_release
|
||||
install -m 644 contrib/lease-tools/dhcp_release.1 debian/utils/usr/share/man/man1/dhcp_release.1
|
||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release.1
|
||||
install -m 755 contrib/wrt/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
||||
install -m 644 contrib/wrt/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
install -m 755 contrib/lease-tools/dhcp_release6 debian/utils/usr/bin/dhcp_release6
|
||||
install -m 644 contrib/lease-tools/dhcp_release6.1 debian/utils/usr/share/man/man1/dhcp_release6.1
|
||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_release6.1
|
||||
install -m 755 contrib/lease-tools/dhcp_lease_time debian/utils/usr/bin/dhcp_lease_time
|
||||
install -m 644 contrib/lease-tools/dhcp_lease_time.1 debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
install -m 644 debian/copyright debian/utils/usr/share/doc/dnsmasq-utils/copyright
|
||||
install -m 644 debian/changelog debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
gzip -9n debian/utils/usr/share/doc/dnsmasq-utils/changelog.Debian
|
||||
gzip -9n debian/utils/usr/share/man/man1/dhcp_lease_time.1
|
||||
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
|
||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_release
|
||||
strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
||||
$(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/utils/usr/bin/dhcp_release6
|
||||
$(DEB_HOST_GNU_TYPE)-strip -R .note -R .comment debian/utils/usr/bin/dhcp_lease_time
|
||||
endif
|
||||
cd debian/utils && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
dpkg-shlibdeps -Tdebian/utils-substvars debian/utils/usr/bin/dhcp_release debian/utils/usr/bin/dhcp_lease_time
|
||||
|
||||
1
debian/shlibs.local
vendored
Normal file
1
debian/shlibs.local
vendored
Normal file
@@ -0,0 +1 @@
|
||||
libnettle 6 libnettle6 (>= 3.3)
|
||||
7
debian/systemd.service
vendored
7
debian/systemd.service
vendored
@@ -1,10 +1,13 @@
|
||||
[Unit]
|
||||
Description=dnsmasq - A lightweight DHCP and caching DNS server
|
||||
Requires=network.target
|
||||
Wants=nss-lookup.target
|
||||
Before=nss-lookup.target
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
PIDFile=/var/run/dnsmasq/dnsmasq.pid
|
||||
PIDFile=/run/dnsmasq/dnsmasq.pid
|
||||
|
||||
# Test the config file and refuse starting if it is not valid.
|
||||
ExecStartPre=/usr/sbin/dnsmasq --test
|
||||
@@ -15,7 +18,7 @@ ExecStartPre=/usr/sbin/dnsmasq --test
|
||||
ExecStart=/etc/init.d/dnsmasq systemd-exec
|
||||
|
||||
# The systemd-*-resolvconf functions configure (and deconfigure)
|
||||
# resolvconf to work with the dnsmasq DNS server. They're called liek
|
||||
# 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
|
||||
|
||||
@@ -189,7 +189,7 @@
|
||||
# add names to the DNS for the IPv6 address of SLAAC-configured dual-stack
|
||||
# hosts. Use the DHCPv4 lease to derive the name, network segment and
|
||||
# MAC address and assume that the host will also have an
|
||||
# IPv6 address calculated using the SLAAC alogrithm.
|
||||
# IPv6 address calculated using the SLAAC algorithm.
|
||||
#dhcp-range=1234::, ra-names
|
||||
|
||||
# Do Router Advertisements, BUT NOT DHCP for this subnet.
|
||||
@@ -210,7 +210,7 @@
|
||||
#dhcp-range=1234::, ra-stateless, ra-names
|
||||
|
||||
# Do router advertisements for all subnets where we're doing DHCPv6
|
||||
# Unless overriden by ra-stateless, ra-names, et al, the router
|
||||
# Unless overridden by ra-stateless, ra-names, et al, the router
|
||||
# advertisements will have the M and O bits set, so that the clients
|
||||
# get addresses and configuration from DHCPv6, and the A bit reset, so the
|
||||
# clients don't use SLAAC addresses.
|
||||
@@ -251,7 +251,7 @@
|
||||
# the IP address 192.168.0.60
|
||||
#dhcp-host=id:01:02:02:04,192.168.0.60
|
||||
|
||||
# Always give the Infiniband interface with hardware address
|
||||
# Always give the InfiniBand interface with hardware address
|
||||
# 80:00:00:48:fe:80:00:00:00:00:00:00:f4:52:14:03:00:28:05:81 the
|
||||
# ip address 192.168.0.61. The client id is derived from the prefix
|
||||
# ff:00:00:00:00:00:02:00:00:02:c9:00 and the last 8 pairs of
|
||||
@@ -288,7 +288,7 @@
|
||||
# Give a fixed IPv6 address and name to client with
|
||||
# DUID 00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2
|
||||
# Note the MAC addresses CANNOT be used to identify DHCPv6 clients.
|
||||
# Note also the they [] around the IPv6 address are obilgatory.
|
||||
# Note also the they [] around the IPv6 address are obligatory.
|
||||
#dhcp-host=id:00:01:00:01:16:d2:83:fc:92:d4:19:e2:d8:b2, fred, [1234::5]
|
||||
|
||||
# Ignore any clients which are not specified in dhcp-host lines
|
||||
@@ -525,7 +525,7 @@
|
||||
# (using /etc/hosts) then that name can be specified as the
|
||||
# tftp_servername (the third option to dhcp-boot) and in that
|
||||
# case dnsmasq resolves this name and returns the resultant IP
|
||||
# addresses in round robin fasion. This facility can be used to
|
||||
# addresses in round robin fashion. This facility can be used to
|
||||
# load balance the tftp load among a set of servers.
|
||||
#dhcp-boot=/var/ftpd/pxelinux.0,boothost,tftp_server_name
|
||||
|
||||
|
||||
2
doc.html
2
doc.html
@@ -18,7 +18,7 @@ Linux distributions and the ports systems of FreeBSD, OpenBSD and NetBSD. Dnsmas
|
||||
|
||||
<P>
|
||||
The DNS subsystem provides a local DNS server for the network, with forwarding of all query types to upstream recursive DNS servers and
|
||||
cacheing of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
|
||||
caching of common record types (A, AAAA, CNAME and PTR, also DNSKEY and DS when DNSSEC is enabled).
|
||||
<DIR>
|
||||
<LI>Local DNS names can be defined by reading /etc/hosts, by importing names from the DHCP subsystem, or by configuration of a wide range of useful record types.</LI>
|
||||
<LI>Upstream servers can be configured in a variety of convenient ways, including dynamic configuration as these change on moving upstream network.
|
||||
|
||||
306
man/dnsmasq.8
306
man/dnsmasq.8
@@ -30,7 +30,7 @@ DHCPv4 server, and in addition, it includes router advertisements and
|
||||
a neat feature which allows nameing for clients which use DHCPv4 and
|
||||
stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
|
||||
.PP
|
||||
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows uneeded functions to be omitted from the compiled binary.
|
||||
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows unneeded functions to be omitted from the compiled binary.
|
||||
.SH OPTIONS
|
||||
Note that in general missing parameters are allowed and switch off
|
||||
functions, for instance "--pid-file" disables writing a PID file. On
|
||||
@@ -42,6 +42,13 @@ the configuration file.
|
||||
Read and syntax check configuration file(s). Exit with code 0 if all
|
||||
is OK, or a non-zero code otherwise. Do not start up dnsmasq.
|
||||
.TP
|
||||
.B \-w, --help
|
||||
Display all command-line options.
|
||||
.B --help dhcp
|
||||
will display known DHCPv4 configuration options, and
|
||||
.B --help dhcp6
|
||||
will display DHCPv6 options.
|
||||
.TP
|
||||
.B \-h, --no-hosts
|
||||
Don't read the hostnames in /etc/hosts.
|
||||
.TP
|
||||
@@ -60,7 +67,7 @@ in the same way as for DHCP-derived names. Note that this does not
|
||||
apply to domain names in cnames, PTR records, TXT records etc.
|
||||
.TP
|
||||
.B \-T, --local-ttl=<time>
|
||||
When replying with information from /etc/hosts or the DHCP leases
|
||||
When replying with information from /etc/hosts or configuration or the DHCP leases
|
||||
file dnsmasq by default sets the time-to-live field to zero, meaning
|
||||
that the requester should not itself cache the information. This is
|
||||
the correct thing to do in almost all situations. This option allows a
|
||||
@@ -68,6 +75,9 @@ time-to-live (in seconds) to be given for these replies. This will
|
||||
reduce the load on the server at the expense of clients using stale
|
||||
data under some circumstances.
|
||||
.TP
|
||||
.B --dhcp-ttl=<time>
|
||||
As for --local-ttl, but affects only replies with information from DHCP leases. If both are given, --dhcp-ttl applies for DHCP information, and --local-ttl for others. Setting this to zero eliminates the effect of --local-ttl for DHCP.
|
||||
.TP
|
||||
.B --neg-ttl=<time>
|
||||
Negative replies from upstream servers normally contain time-to-live
|
||||
information in SOA records which dnsmasq uses for caching. If the
|
||||
@@ -174,6 +184,13 @@ queries. Dnsmasq picks random ports as source for outbound queries:
|
||||
when this option is given, the ports used will always to larger
|
||||
than that specified. Useful for systems behind firewalls.
|
||||
.TP
|
||||
.B --max-port=<port>
|
||||
Use ports lower than that given as source for outbound DNS queries.
|
||||
Dnsmasq picks random ports as source for outbound queries:
|
||||
when this option is given, the ports used will always be lower
|
||||
than that specified. Useful for systems behind firewalls.
|
||||
.TP
|
||||
|
||||
.B \-i, --interface=<interface name>
|
||||
Listen only on the specified interface(s). Dnsmasq automatically adds
|
||||
the loopback (local) interface to the list of interfaces to use when
|
||||
@@ -186,12 +203,17 @@ or
|
||||
options are given dnsmasq listens on all available interfaces except any
|
||||
given in
|
||||
.B \--except-interface
|
||||
options. IP alias interfaces (eg "eth1:0") cannot be used with
|
||||
.B --interface
|
||||
options. On Linux, when
|
||||
.B \--bind-interfaces
|
||||
or
|
||||
.B --except-interface
|
||||
options, use --listen-address instead. A simple wildcard, consisting
|
||||
of a trailing '*', can be used in
|
||||
.B \--bind-dynamic
|
||||
are in effect, IP alias interface labels (eg "eth1:0") are checked, rather than
|
||||
interface names. In the degenerate case when an interface has one address, this amounts to the same thing but when an interface has multiple addresses it
|
||||
allows control over which of those addresses are accepted.
|
||||
The same effect is achievable in default mode by using
|
||||
.B \--listen-address.
|
||||
A simple wildcard, consisting of a trailing '*',
|
||||
can be used in
|
||||
.B \--interface
|
||||
and
|
||||
.B \--except-interface
|
||||
@@ -205,7 +227,9 @@ and
|
||||
.B --except-interface
|
||||
options does not matter and that
|
||||
.B --except-interface
|
||||
options always override the others.
|
||||
options always override the others. The comments about interface labels for
|
||||
.B --listen-address
|
||||
apply here.
|
||||
.TP
|
||||
.B --auth-server=<domain>,<interface>|<ip-address>
|
||||
Enable DNS authoritative mode for queries arriving at an interface or address. Note that the interface or address
|
||||
@@ -215,7 +239,7 @@ or
|
||||
.B --listen-address
|
||||
configuration, indeed
|
||||
.B --auth-server
|
||||
will overide these and provide a different DNS service on the
|
||||
will override these and provide a different DNS service on the
|
||||
specified interface. The <domain> is the "glue record". It should
|
||||
resolve in the global DNS to a A and/or AAAA record which points to
|
||||
the address dnsmasq is listening on. When an interface is specified,
|
||||
@@ -225,7 +249,7 @@ addresses associated with the interface.
|
||||
.B --local-service
|
||||
Accept DNS queries only from hosts whose address is on a local subnet,
|
||||
ie a subnet for which an interface exists on the server. This option
|
||||
only has effect is there are no --interface --except-interface,
|
||||
only has effect if there are no --interface --except-interface,
|
||||
--listen-address or --auth-server options. It is intended to be set as
|
||||
a default on installation, to allow unconfigured installations to be
|
||||
useful but also safe from being used for DNS amplification attacks.
|
||||
@@ -272,8 +296,8 @@ option requires non-standard networking APIs and it is only available
|
||||
under Linux. On other platforms it falls-back to --bind-interfaces mode.
|
||||
.TP
|
||||
.B \-y, --localise-queries
|
||||
Return answers to DNS queries from /etc/hosts which depend on the interface over which the query was
|
||||
received. If a name in /etc/hosts has more than one address associated with
|
||||
Return answers to DNS queries from /etc/hosts and --interface-name which depend on the interface over which the query was
|
||||
received. If a name has more than one address associated with
|
||||
it, and at least one of those addresses is on the same subnet as the
|
||||
interface to which the query was sent, then return only the
|
||||
address(es) on that subnet. This allows for a server to have multiple
|
||||
@@ -284,7 +308,8 @@ attached to. Currently this facility is limited to IPv4.
|
||||
.B \-b, --bogus-priv
|
||||
Bogus private reverse lookups. All reverse lookups for private IP ranges (ie 192.168.x.x, etc)
|
||||
which are not found in /etc/hosts or the DHCP leases file are answered
|
||||
with "no such domain" rather than being forwarded upstream.
|
||||
with "no such domain" rather than being forwarded upstream. The
|
||||
set of prefixes affected is the list given in RFC6303, for IPv4 and IPv6.
|
||||
.TP
|
||||
.B \-V, --alias=[<old-ip>]|[<start-ip>-<end-ip>],<new-ip>[,<mask>]
|
||||
Modify IPv4 addresses returned from upstream nameservers; old-ip is
|
||||
@@ -307,7 +332,7 @@ instead of the correct NXDOMAIN response. This option tells dnsmasq to
|
||||
fake the correct response when it sees this behaviour. As at Sept 2003
|
||||
the IP address being returned by Verisign is 64.94.110.11
|
||||
.TP
|
||||
.B \-B, --ignore-address=<ipaddr>
|
||||
.B --ignore-address=<ipaddr>
|
||||
Ignore replies to A-record queries which include the specified address.
|
||||
No error is generated, dnsmasq simply continues to listen for another reply.
|
||||
This is useful to defeat blocking strategies which rely on quickly supplying a
|
||||
@@ -405,7 +430,10 @@ xxx.internal.thekelleys.org.uk at 192.168.1.1 then giving the flag
|
||||
.B -S /internal.thekelleys.org.uk/192.168.1.1
|
||||
will send all queries for
|
||||
internal machines to that nameserver, everything else will go to the
|
||||
servers in /etc/resolv.conf. An empty domain specification,
|
||||
servers in /etc/resolv.conf. DNSSEC validation is turned off for such
|
||||
private nameservers, UNLESS a
|
||||
.B --trust-anchor
|
||||
is specified for the domain in question. An empty domain specification,
|
||||
.B //
|
||||
has the special meaning of "unqualified names only" ie names without any
|
||||
dots in them. A non-standard port may be specified as
|
||||
@@ -414,7 +442,7 @@ address using a # character.
|
||||
More than one -S flag is allowed, with
|
||||
repeated domain or ipaddr parts as required.
|
||||
|
||||
More specific domains take precendence over less specific domains, so:
|
||||
More specific domains take precedence over less specific domains, so:
|
||||
.B --server=/google.com/1.2.3.4
|
||||
.B --server=/www.google.com/2.3.4.5
|
||||
will send queries for *.google.com to 1.2.3.4, except *www.google.com,
|
||||
@@ -439,14 +467,14 @@ to make configuration files clearer in this case.
|
||||
IPv6 addresses may include a %interface scope-id, eg
|
||||
fe80::202:a412:4512:7bbf%eth0.
|
||||
|
||||
The optional string after the @ character tells
|
||||
dnsmasq how to set the source of the queries to this
|
||||
nameserver. It should be an ip-address, which should belong to the machine on which
|
||||
dnsmasq is running otherwise this server line will be logged and then
|
||||
ignored, or an interface name. If an interface name is given, then
|
||||
queries to the server will be forced via that interface; if an
|
||||
ip-address is given then the source address of the queries will be set
|
||||
to that address.
|
||||
The optional string after the @ character tells dnsmasq how to set the source of
|
||||
the queries to this nameserver. It can either be an ip-address, an interface
|
||||
name or both. The ip-address should belong to the machine on which dnsmasq is
|
||||
running, otherwise this server line will be logged and then ignored. If an
|
||||
interface name is given, then queries to the server will be forced via that
|
||||
interface; if an ip-address is given then the source address of the queries will
|
||||
be set to that address; and if both are given then a combination of ip-address
|
||||
and interface name will be used to steer requests to the server.
|
||||
The query-port flag is ignored for any servers which have a
|
||||
source address specified but the port may be specified directly as
|
||||
part of the source address. Forcing queries to an interface is not
|
||||
@@ -460,28 +488,36 @@ but provides some syntactic sugar to make specifying address-to-name queries eas
|
||||
is exactly equivalent to
|
||||
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
|
||||
.TP
|
||||
.B \-A, --address=/<domain>/[domain/][<ipaddr>]
|
||||
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
|
||||
Specify an IP address to return for any host in the given domains.
|
||||
Queries in the domains are never forwarded and always replied to
|
||||
with the specified IP address which may be IPv4 or IPv6. To give
|
||||
both IPv4 and IPv6 addresses for a domain, use repeated -A flags.
|
||||
both IPv4 and IPv6 addresses for a domain, use repeated \fB-A\fP flags.
|
||||
To include multiple IP addresses for a single query, use
|
||||
\fB--addn-hosts=<path>\fP instead.
|
||||
Note that /etc/hosts and DHCP leases override this for individual
|
||||
names. A common use of this is to redirect the entire doubleclick.net
|
||||
domain to some friendly local web server to avoid banner ads. The
|
||||
domain specification works in the same was as for --server, with the
|
||||
additional facility that /#/ matches any domain. Thus
|
||||
--address=/#/1.2.3.4 will always return 1.2.3.4 for any query not
|
||||
answered from /etc/hosts or DHCP and not sent to an upstream
|
||||
nameserver by a more specific --server directive. As for --server,
|
||||
one or more domains with no address returns a no-such-domain answer, so
|
||||
--address=/example.com/ is equivalent to --server=/example.com/ and returns
|
||||
NXDOMAIN for example.com and all its subdomains.
|
||||
domain specification works in the same was as for \fB--server\fP, with
|
||||
the additional facility that \fB/#/\fP matches any domain. Thus
|
||||
\fB--address=/#/1.2.3.4\fP will always return \fB1.2.3.4\fP for any
|
||||
query not answered from \fB/etc/hosts\fP or DHCP and not sent to an
|
||||
upstream nameserver by a more specific \fB--server\fP directive. As for
|
||||
\fB--server\fP, one or more domains with no address returns a
|
||||
no-such-domain answer, so \fB--address=/example.com/\fP is equivalent to
|
||||
\fB--server=/example.com/\fP and returns NXDOMAIN for example.com and
|
||||
all its subdomains.
|
||||
.TP
|
||||
.B --ipset=/<domain>/[domain/]<ipset>[,<ipset>]
|
||||
Places the resolved IP addresses of queries for the specified domains
|
||||
in the specified netfilter ip sets. Domains and subdomains are matched
|
||||
in the same way as --address. These ip sets must already exist. See
|
||||
ipset(8) for more details.
|
||||
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
|
||||
Places the resolved IP addresses of queries for one or more domains in
|
||||
the specified Netfilter IP set. If multiple setnames are given, then the
|
||||
addresses are placed in each of them, subject to the limitations of an
|
||||
IP set (IPv4 addresses cannot be stored in an IPv6 IP set and vice
|
||||
versa). Domains and subdomains are matched in the same way as
|
||||
\fB--address\fP.
|
||||
These IP sets must already exist. See
|
||||
.BR ipset (8)
|
||||
for more details.
|
||||
.TP
|
||||
.B \-m, --mx-host=<mx name>[[,<hostname>],<preference>]
|
||||
Return an MX record named <mx name> pointing to the given hostname (if
|
||||
@@ -519,7 +555,7 @@ zone files: the port, weight and priority numbers are in a different
|
||||
order. More than one SRV record for a given service/domain is allowed,
|
||||
all that match are returned.
|
||||
.TP
|
||||
.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>]
|
||||
.B --host-record=<name>[,<name>....],[<IPv4-address>],[<IPv6-address>][,<TTL>]
|
||||
Add A, AAAA and PTR records to the DNS. This adds one or more names to
|
||||
the DNS with associated IPv4 (A) and IPv6 (AAAA) records. A name may
|
||||
appear in more than one
|
||||
@@ -536,6 +572,10 @@ is in effect. Short and long names may appear in the same
|
||||
.B host-record,
|
||||
eg.
|
||||
.B --host-record=laptop,laptop.thekelleys.org,192.168.0.1,1234::100
|
||||
|
||||
If the time-to-live is given, it overrides the default, which is zero
|
||||
or the value of --local-ttl. The value is a positive integer and gives
|
||||
the time-to-live in seconds.
|
||||
.TP
|
||||
.B \-Y, --txt-record=<name>[[,<text>],<text>]
|
||||
Return a TXT DNS record. The value of TXT record is a set of strings,
|
||||
@@ -549,7 +589,7 @@ Return a PTR DNS record.
|
||||
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
|
||||
Return an NAPTR DNS record, as specified in RFC3403.
|
||||
.TP
|
||||
.B --cname=<cname>,<target>
|
||||
.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
|
||||
Return a CNAME record which indicates that <cname> is really
|
||||
<target>. There are significant limitations on the target; it must be a
|
||||
DNS name which is known to dnsmasq from /etc/hosts (or additional
|
||||
@@ -557,7 +597,13 @@ hosts files), from DHCP, from --interface-name or from another
|
||||
.B --cname.
|
||||
If the target does not satisfy this
|
||||
criteria, the whole cname is ignored. The cname must be unique, but it
|
||||
is permissable to have more than one cname pointing to the same target.
|
||||
is permissable to have more than one cname pointing to the same target. Indeed
|
||||
it's possible to declare multiple cnames to a target in a single line, like so:
|
||||
.B --cname=cname1,cname2,target
|
||||
|
||||
If the time-to-live is given, it overrides the default, which is zero
|
||||
or the value of -local-ttl. The value is a positive integer and gives
|
||||
the time-to-live in seconds.
|
||||
.TP
|
||||
.B --dns-rr=<name>,<RR-number>,[<hex data>]
|
||||
Return an arbitrary DNS Resource Record. The number is the type of the
|
||||
@@ -566,7 +612,7 @@ given by the hex data, which may be of the form 01:23:45 or 01 23 45 or
|
||||
012345 or any mixture of these.
|
||||
.TP
|
||||
.B --interface-name=<name>,<interface>[/4|/6]
|
||||
Return a DNS record associating the name with the primary address on
|
||||
Return DNS records associating the name with the address(es) of
|
||||
the given interface. This flag specifies an A or AAAA record for the given
|
||||
name in the same way as an /etc/hosts line, except that the address is
|
||||
not constant, but taken from the given interface. The interface may be
|
||||
@@ -576,7 +622,8 @@ down, not configured or non-existent, an empty record is returned. The
|
||||
matching PTR record is also created, mapping the interface address to
|
||||
the name. More than one name may be associated with an interface
|
||||
address by repeating the flag; in that case the first instance is used
|
||||
for the reverse address-to-name mapping.
|
||||
for the reverse address-to-name mapping. Note that a name used in
|
||||
--interface-name may not appear in /etc/hosts.
|
||||
.TP
|
||||
.B --synth-domain=<domain>,<address range>[,<prefix>]
|
||||
Create artificial A/AAAA and PTR records for an address range. The
|
||||
@@ -591,10 +638,12 @@ but IPv6 addresses may start with '::'
|
||||
but DNS labels may not start with '-' so in this case if no prefix is
|
||||
configured a zero is added in front of the label. ::1 becomes 0--1.
|
||||
|
||||
V4 mapped IPv6 addresses, which have a representation like ::ffff:1.2.3.4 are handled specially, and become like 0--ffff-1-2-3-4
|
||||
|
||||
The address range can be of the form
|
||||
<ip address>,<ip address> or <ip address>/<netmask>
|
||||
.TP
|
||||
.B --add-mac
|
||||
.B --add-mac[=base64|text]
|
||||
Add the MAC address of the requestor to DNS queries which are
|
||||
forwarded upstream. This may be used to DNS filtering by the upstream
|
||||
server. The MAC address can only be added if the requestor is on the same
|
||||
@@ -602,19 +651,34 @@ subnet as the dnsmasq server. Note that the mechanism used to achieve this (an E
|
||||
is not yet standardised, so this should be considered
|
||||
experimental. Also note that exposing MAC addresses in this way may
|
||||
have security and privacy implications. The warning about caching
|
||||
given for --add-subnet applies to --add-mac too.
|
||||
given for --add-subnet applies to --add-mac too. An alternative encoding of the
|
||||
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
|
||||
.TP
|
||||
.B --add-cpe-id=<string>
|
||||
Add a arbitrary identifying string to o DNS queries which are
|
||||
forwarded upstream.
|
||||
.TP
|
||||
.B --add-subnet[[=<IPv4 prefix length>],<IPv6 prefix length>]
|
||||
Add the subnet address of the requestor to the DNS queries which are
|
||||
forwarded upstream. The amount of the address forwarded depends on the
|
||||
prefix length parameter: 32 (128 for IPv6) forwards the whole address,
|
||||
zero forwards none of it but still marks the request so that no
|
||||
upstream nameserver will add client address information either. The
|
||||
default is zero for both IPv4 and IPv6. Note that upstream nameservers
|
||||
may be configured to return different results based on this
|
||||
information, but the dnsmasq cache does not take account. If a dnsmasq
|
||||
instance is configured such that different results may be encountered,
|
||||
caching should be disabled.
|
||||
.B --add-subnet[[=[<IPv4 address>/]<IPv4 prefix length>][,[<IPv6 address>/]<IPv6 prefix length>]]
|
||||
Add a subnet address to the DNS queries which are forwarded
|
||||
upstream. If an address is specified in the flag, it will be used,
|
||||
otherwise, the address of the requestor will be used. The amount of
|
||||
the address forwarded depends on the prefix length parameter: 32 (128
|
||||
for IPv6) forwards the whole address, zero forwards none of it but
|
||||
still marks the request so that no upstream nameserver will add client
|
||||
address information either. The default is zero for both IPv4 and
|
||||
IPv6. Note that upstream nameservers may be configured to return
|
||||
different results based on this information, but the dnsmasq cache
|
||||
does not take account. If a dnsmasq instance is configured such that
|
||||
different results may be encountered, caching should be disabled.
|
||||
|
||||
For example,
|
||||
.B --add-subnet=24,96
|
||||
will add the /24 and /96 subnets of the requestor for IPv4 and IPv6 requestors, respectively.
|
||||
.B --add-subnet=1.2.3.4/24
|
||||
will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
|
||||
.B --add-subnet=1.2.3.4/24,1.2.3.4/24
|
||||
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
|
||||
|
||||
.TP
|
||||
.B \-c, --cache-size=<cachesize>
|
||||
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching.
|
||||
@@ -644,7 +708,7 @@ permitted to reduce the cache size below the default when DNSSEC is
|
||||
enabled. The nameservers upstream of dnsmasq must be DNSSEC-capable,
|
||||
ie capable of returning DNSSEC records with data. If they are not,
|
||||
then dnsmasq will not be able to determine the trusted status of
|
||||
answers. In the default mode, this menas that all replies will be
|
||||
answers. In the default mode, this means that all replies will be
|
||||
marked as untrusted. If
|
||||
.B --dnssec-check-unsigned
|
||||
is set and the upstream servers don't support DNSSEC, then DNS service will be entirely broken.
|
||||
@@ -696,7 +760,7 @@ a return code of SERVFAIL. Note that
|
||||
setting this may affect DNS behaviour in bad ways, it is not an
|
||||
extra-logging flag and should not be set in production.
|
||||
.TP
|
||||
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....]]
|
||||
.B --auth-zone=<domain>[,<subnet>[/<prefix length>][,<subnet>[/<prefix length>].....][,exclude:<subnet>[/<prefix length>]].....]
|
||||
Define a DNS zone for which dnsmasq acts as authoritative server. Locally defined DNS records which are in the domain
|
||||
will be served. If subnet(s) are given, A and AAAA records must be in one of the
|
||||
specified subnets.
|
||||
@@ -713,6 +777,10 @@ appear in the zone, but RFC1918 IPv4 addresses which should not.
|
||||
Interface-name and address-literal subnet specifications may be used
|
||||
freely in the same --auth-zone declaration.
|
||||
|
||||
It's possible to exclude certain IP addresses from responses. It can be
|
||||
used, to make sure that answers contain only global routeable IP
|
||||
addresses (by excluding loopback, RFC1918 and ULA addresses).
|
||||
|
||||
The subnet(s) are also used to define in-addr.arpa and
|
||||
ip6.arpa domains which are served for reverse-DNS queries. If not
|
||||
specified, the prefix length defaults to 24 for IPv4 and 64 for IPv6.
|
||||
@@ -747,7 +815,7 @@ compiled in and the kernel must have conntrack support
|
||||
included and configured. This option cannot be combined with
|
||||
--query-port.
|
||||
.TP
|
||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>][,<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-addr>[,<end-addr>|<mode>][,<netmask>[,<broadcast>]][,<lease time>]
|
||||
.TP
|
||||
.B \-F, --dhcp-range=[tag:<tag>[,tag:<tag>],][set:<tag>,]<start-IPv6addr>[,<end-IPv6addr>|constructor:<interface>][,<mode>][,<prefix-len>][,<lease time>]
|
||||
|
||||
@@ -779,7 +847,7 @@ For IPv6, the parameters are slightly different: instead of netmask
|
||||
and broadcast address, there is an optional prefix length which must
|
||||
be equal to or larger then the prefix length on the local interface. If not
|
||||
given, this defaults to 64. Unlike the IPv4 case, the prefix length is not
|
||||
automatically derived from the interface configuration. The mimimum
|
||||
automatically derived from the interface configuration. The minimum
|
||||
size of the prefix length is 64.
|
||||
|
||||
IPv6 (only) supports another type of range. In this, the start address and optional end address contain only the network part (ie ::1) and they are followed by
|
||||
@@ -901,7 +969,7 @@ subnets which don't need a pool of dynamically allocated addresses,
|
||||
use the "static" keyword in the dhcp-range declaration.
|
||||
|
||||
It is allowed to use client identifiers (called client
|
||||
DUID in IPv6-land rather than
|
||||
DUID in IPv6-land) rather than
|
||||
hardware addresses to identify hosts by prefixing with 'id:'. Thus:
|
||||
.B --dhcp-host=id:01:02:03:04,.....
|
||||
refers to the host with client identifier 01:02:03:04. It is also
|
||||
@@ -953,6 +1021,8 @@ dhcp-host directive (or one implied by /etc/ethers) then the special
|
||||
tag "known" is set. This allows dnsmasq to be configured to
|
||||
ignore requests from unknown machines using
|
||||
.B --dhcp-ignore=tag:!known
|
||||
If the host matches only a dhcp-host directive which cannot
|
||||
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
|
||||
Ethernet addresses (but not client-ids) may have
|
||||
wildcard bytes, so for example
|
||||
.B --dhcp-host=00:20:e0:3b:13:*,ignore
|
||||
@@ -994,22 +1064,21 @@ is given, then read all the files contained in that directory. The advantage of
|
||||
using this option is the same as for --dhcp-hostsfile: the
|
||||
dhcp-optsfile will be re-read when dnsmasq receives SIGHUP. Note that
|
||||
it is possible to encode the information in a
|
||||
.B --dhcp-boot
|
||||
flag as DHCP options, using the options names bootfile-name,
|
||||
server-ip-address and tftp-server. This allows these to be included
|
||||
in a dhcp-optsfile.
|
||||
.TP
|
||||
.B --dhcp-hostsdir=<path>
|
||||
This is equivalent to dhcp-hostsfile, except for the following. The path MUST be a
|
||||
directory, and not an individual file. Changed or new files within
|
||||
the directory are read automatically, without the need to send SIGHUP.
|
||||
If a file is deleted for changed after it has been read by dnsmasq, then the
|
||||
host record it contained will remain until dnsmasq recieves a SIGHUP, or
|
||||
host record it contained will remain until dnsmasq receives a SIGHUP, or
|
||||
is restarted; ie host records are only added dynamically.
|
||||
.TP
|
||||
.B --dhcp-optsdir=<path>
|
||||
This is equivalent to dhcp-optsfile, with the differences noted for --dhcp-hostsdir.
|
||||
.TP
|
||||
.B --dhcp-boot
|
||||
flag as DHCP options, using the options names bootfile-name,
|
||||
server-ip-address and tftp-server. This allows these to be included
|
||||
in a dhcp-optsfile.
|
||||
.TP
|
||||
.B \-Z, --read-ethers
|
||||
Read /etc/ethers for information about hosts for the DHCP server. The
|
||||
@@ -1315,7 +1384,7 @@ functions when supported by a suitable DHCP server.
|
||||
This specifies a boot option which may appear in a PXE boot menu. <CSA> is
|
||||
client system type, only services of the correct type will appear in a
|
||||
menu. The known types are x86PC, PC98, IA64_EFI, Alpha, Arc_x86,
|
||||
Intel_Lean_Client, IA32_EFI, BC_EFI, Xscale_EFI and X86-64_EFI; an
|
||||
Intel_Lean_Client, IA32_EFI, X86-64_EFI, Xscale_EFI, BC_EFI, ARM32_EFI and ARM64_EFI; an
|
||||
integer may be used for other types. The
|
||||
parameter after the menu text may be a file name, in which case dnsmasq acts as a
|
||||
boot server and directs the PXE client to download the file by TFTP,
|
||||
@@ -1324,8 +1393,9 @@ either from itself (
|
||||
must be set for this to work) or another TFTP server if the final server
|
||||
address/name is given.
|
||||
Note that the "layer"
|
||||
suffix (normally ".0") is supplied by PXE, and should not be added to
|
||||
the basename. If an integer boot service type, rather than a basename
|
||||
suffix (normally ".0") is supplied by PXE, and need not be added to
|
||||
the basename. Alternatively, the basename may be a filename, complete with suffix, in which case
|
||||
no layer suffix is added. If an integer boot service type, rather than a basename
|
||||
is given, then the PXE client will search for a
|
||||
suitable boot service for that type on the network. This search may be done
|
||||
by broadcast, or direct to a server if its IP address/name is provided.
|
||||
@@ -1416,7 +1486,7 @@ DUID automatically when it is first needed. When given, this option
|
||||
provides dnsmasq the data required to create a DUID-EN type DUID. Note
|
||||
that once set, the DUID is stored in the lease database, so to change between DUID-EN and
|
||||
automatically created DUIDs or vice-versa, the lease database must be
|
||||
re-intialised. The enterprise-id is assigned by IANA, and the uid is a
|
||||
re-initialised. The enterprise-id is assigned by IANA, and the uid is a
|
||||
string of hex octets unique to a particular device.
|
||||
.TP
|
||||
.B \-6 --dhcp-script=<path>
|
||||
@@ -1484,6 +1554,8 @@ DHCP relay-agent added any of these options.
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
|
||||
|
||||
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
|
||||
|
||||
For IPv6 only:
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS_ID,
|
||||
@@ -1507,8 +1579,8 @@ database.
|
||||
|
||||
|
||||
All file descriptors are
|
||||
closed except stdin, stdout and stderr which are open to /dev/null
|
||||
(except in debug mode).
|
||||
closed except stdin, which is open to /dev/null, and stdout and stderr which capture output for logging by dnsmasq.
|
||||
(In debug mode, stdio, stdout and stderr file are left as those inherited from the invoker of dnsmasq).
|
||||
|
||||
The script is not invoked concurrently: at most one instance
|
||||
of the script is ever running (dnsmasq waits for an instance of script to exit
|
||||
@@ -1523,11 +1595,11 @@ At dnsmasq startup, the script will be invoked for
|
||||
all existing leases as they are read from the lease file. Expired
|
||||
leases will be called with "del" and others with "old". When dnsmasq
|
||||
receives a HUP signal, the script will be invoked for existing leases
|
||||
with an "old " event.
|
||||
with an "old" event.
|
||||
|
||||
|
||||
There are two further actions which may appear as the first argument
|
||||
to the script, "init" and "tftp". More may be added in the future, so
|
||||
There are four further actions which may appear as the first argument
|
||||
to the script, "init", "arp-add", "arp-del" and "tftp". More may be added in the future, so
|
||||
scripts should be written to ignore unknown actions. "init" is
|
||||
described below in
|
||||
.B --leasefile-ro
|
||||
@@ -1535,11 +1607,16 @@ The "tftp" action is invoked when a TFTP file transfer completes: the
|
||||
arguments are the file size in bytes, the address to which the file
|
||||
was sent, and the complete pathname of the file.
|
||||
|
||||
The "arp-add" and "arp-del" actions are only called if enabled with
|
||||
.B --script-arp
|
||||
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
|
||||
the arrival of a new entry in the ARP or neighbour table, and "arp-del" indicates the deletion of same.
|
||||
|
||||
.TP
|
||||
.B --dhcp-luascript=<path>
|
||||
Specify a script written in Lua, to be run when leases are created,
|
||||
destroyed or changed. To use this option, dnsmasq must be compiled
|
||||
with the correct support. The Lua interpreter is intialised once, when
|
||||
with the correct support. The Lua interpreter is initialised once, when
|
||||
dnsmasq starts, so that global variables persist between lease
|
||||
events. The Lua code must define a
|
||||
.B lease
|
||||
@@ -1581,10 +1658,24 @@ table holds the tags
|
||||
.B file_name
|
||||
and
|
||||
.B file_size.
|
||||
|
||||
The
|
||||
.B arp
|
||||
and
|
||||
.B arp-old
|
||||
functions are called only when enabled with
|
||||
.B --script-arp
|
||||
and have a table which holds the tags
|
||||
.B mac_address
|
||||
and
|
||||
.B client_address.
|
||||
.TP
|
||||
.B --dhcp-scriptuser
|
||||
Specify the user as which to run the lease-change script or Lua script. This defaults to root, but can be changed to another user using this flag.
|
||||
.TP
|
||||
.TP
|
||||
.B --script-arp
|
||||
Enable the "arp" and "arp-old" functions in the dhcp-script and dhcp-luascript.
|
||||
.TP
|
||||
.B \-9, --leasefile-ro
|
||||
Completely suppress use of the lease database file. The file will not
|
||||
be created, read, or written. Change the way the lease-change
|
||||
@@ -1677,17 +1768,17 @@ creation are handled by a different protocol. When DHCP is in use,
|
||||
only a subset of this is needed, and dnsmasq can handle it, using
|
||||
existing DHCP configuration to provide most data. When RA is enabled,
|
||||
dnsmasq will advertise a prefix for each dhcp-range, with default
|
||||
router and recursive DNS server as the relevant link-local address on
|
||||
the machine running dnsmasq. By default, he "managed address" bits are set, and
|
||||
router as the relevant link-local address on
|
||||
the machine running dnsmasq. By default, the "managed address" bits are set, and
|
||||
the "use SLAAC" bit is reset. This can be changed for individual
|
||||
subnets with the mode keywords described in
|
||||
.B --dhcp-range.
|
||||
RFC6106 DNS parameters are included in the advertisements. By default,
|
||||
the relevant link-local address of the machine running dnsmasq is sent
|
||||
as recursive DNS server. If provided, the DHCPv6 options dns-server and
|
||||
domain-search are used for RDNSS and DNSSL.
|
||||
domain-search are used for the DNS server (RDNSS) and the domain search list (DNSSL).
|
||||
.TP
|
||||
.B --ra-param=<interface>,[high|low],[[<ra-interval>],<router lifetime>]
|
||||
.B --ra-param=<interface>,[mtu:<integer>|<interface>|off,][high,|low,]<ra-interval>[,<router lifetime>]
|
||||
Set non-default values for router advertisements sent via an
|
||||
interface. The priority field for the router may be altered from the
|
||||
default of medium with eg
|
||||
@@ -1697,16 +1788,26 @@ The interval between router advertisements may be set (in seconds) with
|
||||
The lifetime of the route may be changed or set to zero, which allows
|
||||
a router to advertise prefixes but not a route via itself.
|
||||
.B --ra-parm=eth0,0,0
|
||||
(A value of zero for the interval means the default value.) All three parameters may be set at once.
|
||||
.B --ra-param=low,60,1200
|
||||
(A value of zero for the interval means the default value.) All four parameters may be set at once.
|
||||
.B --ra-param=eth0,mtu:1280,low,60,1200
|
||||
|
||||
The interface field may include a wildcard.
|
||||
|
||||
The mtu: parameter may be an arbitrary interface name, in which case the MTU value for that interface is used. This is useful
|
||||
for (eg) advertising the MTU of a WAN interface on the other interfaces of a router.
|
||||
.TP
|
||||
.B --dhcp-reply-delay=[tag:<tag>,]<integer>
|
||||
Delays sending DHCPOFFER and proxydhcp replies for at least the specified number of seconds.
|
||||
This can be used as workaround for bugs in PXE boot firmware that does not function properly when
|
||||
receiving an instant reply.
|
||||
This option takes into account the time already spent waiting (e.g. performing ping check) if any.
|
||||
.TP
|
||||
.B --enable-tftp[=<interface>[,<interface>]]
|
||||
Enable the TFTP server function. This is deliberately limited to that
|
||||
needed to net-boot a client. Only reading is allowed; the tsize and
|
||||
blksize extensions are supported (tsize is only supported in octet
|
||||
mode). Without an argument, the TFTP service is provided to the same set of interfaces as DHCP service.
|
||||
If the list of interfaces is provided, that defines which interfaces recieve TFTP service.
|
||||
If the list of interfaces is provided, that defines which interfaces receive TFTP service.
|
||||
.TP
|
||||
.B --tftp-root=<directory>[,<interface>]
|
||||
Look for files to transfer using TFTP relative to the given
|
||||
@@ -1719,12 +1820,16 @@ directory is only used for TFTP requests via that interface.
|
||||
.B --tftp-no-fail
|
||||
Do not abort startup if specified tftp root directories are inaccessible.
|
||||
.TP
|
||||
.B --tftp-unique-root
|
||||
Add the IP address of the TFTP client as a path component on the end
|
||||
of the TFTP-root (in standard dotted-quad format). Only valid if a
|
||||
tftp-root is set and the directory exists. For instance, if tftp-root is "/tftp" and client
|
||||
1.2.3.4 requests file "myfile" then the effective path will be
|
||||
"/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
|
||||
.B --tftp-unique-root[=ip|mac]
|
||||
Add the IP or hardware address of the TFTP client as a path component on the end
|
||||
of the TFTP-root. Only valid if a tftp-root is set and the directory exists.
|
||||
Defaults to adding IP address (in standard dotted-quad format).
|
||||
For instance, if tftp-root is "/tftp" and client 1.2.3.4 requests file "myfile"
|
||||
then the effective path will be "/tftp/1.2.3.4/myfile" if /tftp/1.2.3.4 exists or /tftp/myfile otherwise.
|
||||
When "=mac" is specified it will append the MAC address instead, using lowercase zero padded digits
|
||||
separated by dashes, e.g.: 01-02-03-04-aa-bb
|
||||
Note that resolving MAC addresses is only possible if the client is in the local network or obtained
|
||||
a DHCP lease from us.
|
||||
.TP
|
||||
.B --tftp-secure
|
||||
Enable TFTP secure mode: without this, any file which is readable by
|
||||
@@ -1755,6 +1860,10 @@ require about (2*n) + 10 descriptors. If
|
||||
.B --tftp-port-range
|
||||
is given, that can affect the number of concurrent connections.
|
||||
.TP
|
||||
.B --tftp-mtu=<mtu size>
|
||||
Use size as the ceiling of the MTU supported by the intervening network when
|
||||
negotiating TFTP blocksize, overriding the MTU setting of the local interface if it is larger.
|
||||
.TP
|
||||
.B --tftp-no-blocksize
|
||||
Stop the TFTP server from negotiating the "blocksize" option with a
|
||||
client. Some buggy clients request this option but then behave badly
|
||||
@@ -1790,7 +1899,7 @@ A special case of
|
||||
.B --conf-file
|
||||
which differs in two respects. Firstly, only --server and --rev-server are allowed
|
||||
in the configuration file included. Secondly, the file is re-read and the configuration
|
||||
therein is updated when dnsmasq recieves SIGHUP.
|
||||
therein is updated when dnsmasq receives SIGHUP.
|
||||
.SH CONFIG FILE
|
||||
At startup, dnsmasq reads
|
||||
.I /etc/dnsmasq.conf,
|
||||
@@ -1939,7 +2048,7 @@ include set:<tag>, including one from the
|
||||
.B dhcp-range
|
||||
used to allocate the address, one from any matching
|
||||
.B dhcp-host
|
||||
(and "known" if a dhcp-host matches)
|
||||
(and "known" or "known-othernet" if a dhcp-host matches)
|
||||
The tag "bootp" is set for BOOTP requests, and a tag whose name is the
|
||||
name of the interface on which the request arrived is also set.
|
||||
|
||||
@@ -2126,7 +2235,12 @@ following data is used to populate the authoritative zone.
|
||||
.B --cname
|
||||
as long as the record name is in the authoritative domain. If the
|
||||
target of the CNAME is unqualified, then it is qualified with the
|
||||
authoritative zone name.
|
||||
authoritative zone name. CNAME used in this way (only) may be wildcards, as in
|
||||
|
||||
.nf
|
||||
.B cname=*.example.com,default.example.com
|
||||
.fi
|
||||
|
||||
.PP
|
||||
IPv4 and IPv6 addresses from /etc/hosts (and
|
||||
.B --addn-hosts
|
||||
@@ -2139,7 +2253,7 @@ provided the address falls into one of the subnets specified in the
|
||||
.PP
|
||||
Addresses of DHCP leases, provided the address falls into one of the subnets specified in the
|
||||
.B --auth-zone.
|
||||
(If contructed DHCP ranges are is use, which depend on the address dynamically
|
||||
(If constructed DHCP ranges are is use, which depend on the address dynamically
|
||||
assigned to an interface, then the form of
|
||||
.B --auth-zone
|
||||
which defines subnets by the dynamic address of an interface should
|
||||
|
||||
@@ -1756,20 +1756,20 @@ dnsmasq est spécifiée comme DNS récursif. Si elles sont fournies, les
|
||||
options dns-server et domain-search sont utilisées respectivement pour RDNSS et
|
||||
DNSSL.
|
||||
.TP
|
||||
.B --ra-param=<interface>,[high|low],[[<intervalle d'annonce routeur>],<durée de vie route>]
|
||||
.B --ra-param=<interface>,[mtu:<valeur>|<interface>|off,][high,|low,]<intervalle d'annonce routeur>[,<durée de vie route>]
|
||||
Configure pour une interface donnée des valeurs pour les annonces routeurs
|
||||
différentes des valeurs par défaut. La valeur par défaut du champ priorité
|
||||
pour le routeur peut-être changée de "medium" (moyen) à "high" (haute) ou
|
||||
"low" (basse). Par exemple :
|
||||
.B --ra-param=eth0,high.
|
||||
.B --ra-param=eth0,high,0.
|
||||
Un intervalle (en secondes) entre les annonces routeur peut-être fourni par :
|
||||
.B --ra-param=eth0,60.
|
||||
La durée de vie de la route peut-être changée ou mise à zéro, auquel cas
|
||||
le routeur peut annoncer les préfixes mais pas de route :
|
||||
.B --ra-parm=eth0,0,0
|
||||
(une valeur de zéro pour l'intervalle signifie qu'il garde la valeur par défaut).
|
||||
Ces trois paramètres peuvent-être configurés en une fois :
|
||||
.B --ra-param=low,60,1200
|
||||
Ces quatre paramètres peuvent-être configurés en une fois :
|
||||
.B --ra-param=eth0,mtu:1280,low,60,1200
|
||||
La valeur pour l'interface peut inclure un caractère joker.
|
||||
.TP
|
||||
.B --enable-tftp[=<interface>[,<interface>]]
|
||||
|
||||
1160
po/pt_BR.po
1160
po/pt_BR.po
File diff suppressed because it is too large
Load Diff
@@ -78,7 +78,7 @@ by modifying MODIFY_RESOLV_CONF_DYNAMICALLY="no" in <TT>/etc/sysconfig/network/c
|
||||
|
||||
|
||||
<h3>Automatic DNS server configuration with DHCP.</h3>
|
||||
You need to get your DHCP client to write the addresse(s) of the DNS
|
||||
You need to get your DHCP client to write the address(es) of the DNS
|
||||
servers to a file other than <TT>/etc/resolv.conf</TT>. For dhcpcd, the
|
||||
<TT>dhcpcd.exe</TT> script gets run with the addresses of the nameserver(s) in
|
||||
the shell variable <TT>$DNS</TT>. The following bit of shell script
|
||||
@@ -86,8 +86,8 @@ uses that to write a file suitable for dnsmasq.
|
||||
<PRE>
|
||||
|
||||
echo -n >|/etc/dhcpc/resolv.conf
|
||||
dnsservs=${DNS//,/ }
|
||||
for serv in $dnsservs; do
|
||||
dnsservers=${DNS//,/ }
|
||||
for serv in $dnsservers; do
|
||||
echo "nameserver $serv" >>/etc/dhcpc/resolv.conf
|
||||
done
|
||||
|
||||
@@ -186,7 +186,7 @@ more than one nameserver just include as many
|
||||
|
||||
<H2>Local domains.</H2>
|
||||
Sometimes people have local domains which they do not want forwarded
|
||||
to upstream servers. This is accomodated by using server options
|
||||
to upstream servers. This is accommodated by using server options
|
||||
without the server IP address. To make things clearer <TT>local</TT>
|
||||
is a synonym for <TT>server</TT>. For example the option
|
||||
<TT>local=/localnet/</TT> ensures that any domain name query which ends in
|
||||
|
||||
247
src/arp.c
Normal file
247
src/arp.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
/* Time between forced re-loads from kernel. */
|
||||
#define INTERVAL 90
|
||||
|
||||
#define ARP_MARK 0
|
||||
#define ARP_FOUND 1 /* Confirmed */
|
||||
#define ARP_NEW 2 /* Newly created */
|
||||
#define ARP_EMPTY 3 /* No MAC addr */
|
||||
|
||||
struct arp_record {
|
||||
unsigned short hwlen, status;
|
||||
int family;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
struct all_addr addr;
|
||||
struct arp_record *next;
|
||||
};
|
||||
|
||||
static struct arp_record *arps = NULL, *old = NULL, *freelist = NULL;
|
||||
static time_t last = 0;
|
||||
|
||||
static int filter_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
|
||||
{
|
||||
struct arp_record *arp;
|
||||
|
||||
(void)parmv;
|
||||
|
||||
if (maclen > DHCP_CHADDR_MAX)
|
||||
return 1;
|
||||
|
||||
#ifndef HAVE_IPV6
|
||||
if (family != AF_INET)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
/* Look for existing entry */
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
{
|
||||
if (family != arp->family || arp->status == ARP_NEW)
|
||||
continue;
|
||||
|
||||
if (family == AF_INET)
|
||||
{
|
||||
if (arp->addr.addr.addr4.s_addr != ((struct in_addr *)addrp)->s_addr)
|
||||
continue;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
{
|
||||
if (!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, (struct in6_addr *)addrp))
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (arp->status == ARP_EMPTY)
|
||||
{
|
||||
/* existing address, was negative. */
|
||||
arp->status = ARP_NEW;
|
||||
arp->hwlen = maclen;
|
||||
memcpy(arp->hwaddr, mac, maclen);
|
||||
}
|
||||
else if (arp->hwlen == maclen && memcmp(arp->hwaddr, mac, maclen) == 0)
|
||||
/* Existing entry matches - confirm. */
|
||||
arp->status = ARP_FOUND;
|
||||
else
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!arp)
|
||||
{
|
||||
/* New entry */
|
||||
if (freelist)
|
||||
{
|
||||
arp = freelist;
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else if (!(arp = whine_malloc(sizeof(struct arp_record))))
|
||||
return 1;
|
||||
|
||||
arp->next = arps;
|
||||
arps = arp;
|
||||
arp->status = ARP_NEW;
|
||||
arp->hwlen = maclen;
|
||||
arp->family = family;
|
||||
memcpy(arp->hwaddr, mac, maclen);
|
||||
if (family == AF_INET)
|
||||
arp->addr.addr.addr4.s_addr = ((struct in_addr *)addrp)->s_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy(&arp->addr.addr.addr6, addrp, IN6ADDRSZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* If in lazy mode, we cache absence of ARP entries. */
|
||||
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now)
|
||||
{
|
||||
struct arp_record *arp, *tmp, **up;
|
||||
int updated = 0;
|
||||
|
||||
again:
|
||||
|
||||
/* If the database is less then INTERVAL old, look in there */
|
||||
if (difftime(now, last) < INTERVAL)
|
||||
{
|
||||
/* addr == NULL -> just make cache up-to-date */
|
||||
if (!addr)
|
||||
return 0;
|
||||
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
{
|
||||
if (addr->sa.sa_family != arp->family)
|
||||
continue;
|
||||
|
||||
if (arp->family == AF_INET &&
|
||||
arp->addr.addr.addr4.s_addr != addr->in.sin_addr.s_addr)
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (arp->family == AF_INET6 &&
|
||||
!IN6_ARE_ADDR_EQUAL(&arp->addr.addr.addr6, &addr->in6.sin6_addr))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
/* Only accept positive entries unless in lazy mode. */
|
||||
if (arp->status != ARP_EMPTY || lazy || updated)
|
||||
{
|
||||
if (mac && arp->hwlen != 0)
|
||||
memcpy(mac, arp->hwaddr, arp->hwlen);
|
||||
return arp->hwlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found, try the kernel */
|
||||
if (!updated)
|
||||
{
|
||||
updated = 1;
|
||||
last = now;
|
||||
|
||||
/* Mark all non-negative entries */
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
if (arp->status != ARP_EMPTY)
|
||||
arp->status = ARP_MARK;
|
||||
|
||||
iface_enumerate(AF_UNSPEC, NULL, filter_mac);
|
||||
|
||||
/* Remove all unconfirmed entries to old list. */
|
||||
for (arp = arps, up = &arps; arp; arp = tmp)
|
||||
{
|
||||
tmp = arp->next;
|
||||
|
||||
if (arp->status == ARP_MARK)
|
||||
{
|
||||
*up = arp->next;
|
||||
arp->next = old;
|
||||
old = arp;
|
||||
}
|
||||
else
|
||||
up = &arp->next;
|
||||
}
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* record failure, so we don't consult the kernel each time
|
||||
we're asked for this address */
|
||||
if (freelist)
|
||||
{
|
||||
arp = freelist;
|
||||
freelist = freelist->next;
|
||||
}
|
||||
else
|
||||
arp = whine_malloc(sizeof(struct arp_record));
|
||||
|
||||
if (arp)
|
||||
{
|
||||
arp->next = arps;
|
||||
arps = arp;
|
||||
arp->status = ARP_EMPTY;
|
||||
arp->family = addr->sa.sa_family;
|
||||
arp->hwlen = 0;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
arp->addr.addr.addr4.s_addr = addr->in.sin_addr.s_addr;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
memcpy(&arp->addr.addr.addr6, &addr->in6.sin6_addr, IN6ADDRSZ);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_arp_script_run(void)
|
||||
{
|
||||
struct arp_record *arp;
|
||||
|
||||
/* Notify any which went, then move to free list */
|
||||
if (old)
|
||||
{
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (option_bool(OPT_SCRIPT_ARP))
|
||||
queue_arp(ACTION_ARP_DEL, old->hwaddr, old->hwlen, old->family, &old->addr);
|
||||
#endif
|
||||
arp = old;
|
||||
old = arp->next;
|
||||
arp->next = freelist;
|
||||
freelist = arp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (arp = arps; arp; arp = arp->next)
|
||||
if (arp->status == ARP_NEW)
|
||||
{
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (option_bool(OPT_SCRIPT_ARP))
|
||||
queue_arp(ACTION_ARP, arp->hwaddr, arp->hwlen, arp->family, &arp->addr);
|
||||
#endif
|
||||
arp->status = ARP_FOUND;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
162
src/auth.c
162
src/auth.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,36 +18,53 @@
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
|
||||
static struct addrlist *find_addrlist(struct addrlist *list, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
do {
|
||||
if (!(list->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
struct in_addr netmask, addr = addr_u->addr.addr4;
|
||||
|
||||
if (!(flag & F_IPV4))
|
||||
continue;
|
||||
|
||||
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - list->prefixlen));
|
||||
|
||||
if (is_same_net(addr, list->addr.addr.addr4, netmask))
|
||||
return list;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (is_same_net6(&(addr_u->addr.addr6), &list->addr.addr.addr6, list->prefixlen))
|
||||
return list;
|
||||
#endif
|
||||
|
||||
} while ((list = list->next));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct addrlist *find_subnet(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
struct addrlist *subnet;
|
||||
if (!zone->subnet)
|
||||
return NULL;
|
||||
|
||||
return find_addrlist(zone->subnet, flag, addr_u);
|
||||
}
|
||||
|
||||
for (subnet = zone->subnet; subnet; subnet = subnet->next)
|
||||
{
|
||||
if (!(subnet->flags & ADDRLIST_IPV6))
|
||||
{
|
||||
struct in_addr netmask, addr = addr_u->addr.addr4;
|
||||
|
||||
if (!(flag & F_IPV4))
|
||||
continue;
|
||||
|
||||
netmask.s_addr = htonl(~(in_addr_t)0 << (32 - subnet->prefixlen));
|
||||
|
||||
if (is_same_net(addr, subnet->addr.addr.addr4, netmask))
|
||||
return subnet;
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (is_same_net6(&(addr_u->addr.addr6), &subnet->addr.addr.addr6, subnet->prefixlen))
|
||||
return subnet;
|
||||
#endif
|
||||
|
||||
}
|
||||
return NULL;
|
||||
static struct addrlist *find_exclude(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
if (!zone->exclude)
|
||||
return NULL;
|
||||
|
||||
return find_addrlist(zone->exclude, flag, addr_u);
|
||||
}
|
||||
|
||||
static int filter_zone(struct auth_zone *zone, int flag, struct all_addr *addr_u)
|
||||
{
|
||||
/* No zones specified, no filter */
|
||||
if (find_exclude(zone, flag, addr_u))
|
||||
return 0;
|
||||
|
||||
/* No subnets specified, no filter */
|
||||
if (!zone->subnet)
|
||||
return 1;
|
||||
|
||||
@@ -81,7 +98,8 @@ int in_zone(struct auth_zone *zone, char *name, char **cut)
|
||||
}
|
||||
|
||||
|
||||
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr, int local_query)
|
||||
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t now, union mysockaddr *peer_addr,
|
||||
int local_query, int do_bit, int have_pseudoheader)
|
||||
{
|
||||
char *name = daemon->namebuff;
|
||||
unsigned char *p, *ansp;
|
||||
@@ -98,7 +116,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
struct interface_name *intr;
|
||||
struct naptr *na;
|
||||
struct all_addr addr;
|
||||
struct cname *a;
|
||||
struct cname *a, *candidate;
|
||||
unsigned int wclen;
|
||||
|
||||
if (ntohs(header->qdcount) == 0 || OPCODE(header) != QUERY )
|
||||
return 0;
|
||||
@@ -114,6 +133,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
unsigned short flag = 0;
|
||||
int found = 0;
|
||||
int cname_wildcard = 0;
|
||||
|
||||
/* save pointer to name for copying into answers */
|
||||
nameoffset = p - (unsigned char *)header;
|
||||
@@ -388,25 +408,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
}
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(name, a->alias) )
|
||||
{
|
||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||
strcpy(name, a->target);
|
||||
if (!strchr(name, '.'))
|
||||
{
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, &nameoffset,
|
||||
T_CNAME, C_IN, "d", name))
|
||||
anscount++;
|
||||
|
||||
goto cname_restart;
|
||||
}
|
||||
|
||||
if (!cut)
|
||||
{
|
||||
nxdomain = 0;
|
||||
@@ -512,8 +513,62 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
} while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4 | F_IPV6)));
|
||||
}
|
||||
|
||||
if (!found)
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||
/* Only supply CNAME if no record for any type is known. */
|
||||
if (nxdomain)
|
||||
{
|
||||
/* Check for possible wildcard match against *.domain
|
||||
return length of match, to get longest.
|
||||
Note that if return length of wildcard section, so
|
||||
we match b.simon to _both_ *.simon and b.simon
|
||||
but return a longer (better) match to b.simon.
|
||||
*/
|
||||
for (wclen = 0, candidate = NULL, a = daemon->cnames; a; a = a->next)
|
||||
if (a->alias[0] == '*')
|
||||
{
|
||||
char *test = name;
|
||||
|
||||
while ((test = strchr(test+1, '.')))
|
||||
{
|
||||
if (hostname_isequal(test, &(a->alias[1])))
|
||||
{
|
||||
if (strlen(test) > wclen && !cname_wildcard)
|
||||
{
|
||||
wclen = strlen(test);
|
||||
candidate = a;
|
||||
cname_wildcard = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (hostname_isequal(a->alias, name) && strlen(a->alias) > wclen)
|
||||
{
|
||||
/* Simple case, no wildcard */
|
||||
wclen = strlen(a->alias);
|
||||
candidate = a;
|
||||
}
|
||||
|
||||
if (candidate)
|
||||
{
|
||||
log_query(F_CONFIG | F_CNAME, name, NULL, NULL);
|
||||
strcpy(name, candidate->target);
|
||||
if (!strchr(name, '.'))
|
||||
{
|
||||
strcat(name, ".");
|
||||
strcat(name, zone->domain);
|
||||
}
|
||||
found = 1;
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->auth_ttl, &nameoffset,
|
||||
T_CNAME, C_IN, "d", name))
|
||||
anscount++;
|
||||
|
||||
goto cname_restart;
|
||||
}
|
||||
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -537,12 +592,12 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
char *p = name;
|
||||
|
||||
if (subnet->prefixlen >= 24)
|
||||
p += sprintf(p, "%d.", a & 0xff);
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
a = a >> 8;
|
||||
if (subnet->prefixlen >= 16 )
|
||||
p += sprintf(p, "%d.", a & 0xff);
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
a = a >> 8;
|
||||
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
||||
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
@@ -805,7 +860,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
header->hb4 &= ~HB4_RA;
|
||||
}
|
||||
|
||||
/* authoritive */
|
||||
/* authoritative */
|
||||
if (auth)
|
||||
header->hb3 |= HB3_AA;
|
||||
|
||||
@@ -820,6 +875,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
header->ancount = htons(anscount);
|
||||
header->nscount = htons(authcount);
|
||||
header->arcount = htons(0);
|
||||
|
||||
/* Advertise our packet size limit in our reply */
|
||||
if (have_pseudoheader)
|
||||
return add_pseudoheader(header, ansp - (unsigned char *)header, (unsigned char *)limit, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||
|
||||
return ansp - (unsigned char *)header;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
|
||||
10
src/bpf.c
10
src/bpf.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,9 @@
|
||||
#include <ifaddrs.h>
|
||||
|
||||
#include <sys/param.h>
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <net/if_dl.h>
|
||||
@@ -103,7 +105,7 @@ int arp_enumerate(void *parm, int (*callback)())
|
||||
int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
{
|
||||
struct ifaddrs *head, *addrs;
|
||||
int errsav, fd = -1, ret = 0;
|
||||
int errsave, fd = -1, ret = 0;
|
||||
|
||||
if (family == AF_UNSPEC)
|
||||
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||||
@@ -235,11 +237,11 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
errsav = errno;
|
||||
errsave = errno;
|
||||
freeifaddrs(head);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
errno = errsav;
|
||||
errno = errsave;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
66
src/cache.c
66
src/cache.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -189,12 +189,7 @@ static void cache_hash(struct crec *crecp)
|
||||
static void cache_blockdata_free(struct crec *crecp)
|
||||
{
|
||||
if (crecp->flags & F_DNSKEY)
|
||||
{
|
||||
if (crecp->flags & F_DS)
|
||||
blockdata_free(crecp->addr.sig.keydata);
|
||||
else
|
||||
blockdata_free(crecp->addr.key.keydata);
|
||||
}
|
||||
blockdata_free(crecp->addr.key.keydata);
|
||||
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
|
||||
blockdata_free(crecp->addr.ds.keydata);
|
||||
}
|
||||
@@ -369,13 +364,8 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* Deletion has to be class-sensitive for DS, DNSKEY, RRSIG, also
|
||||
type-covered sensitive for RRSIG */
|
||||
if ((flags & (F_DNSKEY | F_DS)) &&
|
||||
(flags & (F_DNSKEY | F_DS)) == (crecp->flags & (F_DNSKEY | F_DS)) &&
|
||||
crecp->uid == addr->addr.dnssec.class &&
|
||||
(!((flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY)) ||
|
||||
crecp->addr.sig.type_covered == addr->addr.dnssec.type))
|
||||
/* Deletion has to be class-sensitive for DS and DNSKEY */
|
||||
if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
|
||||
{
|
||||
if (crecp->flags & F_CONFIG)
|
||||
return crecp;
|
||||
@@ -481,7 +471,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
existing record is for an A or AAAA and
|
||||
the record we're trying to insert is the same,
|
||||
just drop the insert, but don't error the whole process. */
|
||||
if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD))
|
||||
if ((flags & (F_IPV4 | F_IPV6)) && (flags & F_FORWARD) && addr)
|
||||
{
|
||||
if ((flags & F_IPV4) && (new->flags & F_IPV4) &&
|
||||
new->addr.addr.addr.addr4.s_addr == addr->addr.addr4.s_addr)
|
||||
@@ -532,13 +522,9 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
struct all_addr free_addr = new->addr.addr;;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* For DNSSEC records, addr holds class and type_covered for RRSIG */
|
||||
/* For DNSSEC records, addr holds class. */
|
||||
if (new->flags & (F_DS | F_DNSKEY))
|
||||
{
|
||||
free_addr.addr.dnssec.class = new->uid;
|
||||
if ((new->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
|
||||
free_addr.addr.dnssec.type = new->addr.sig.type_covered;
|
||||
}
|
||||
free_addr.addr.dnssec.class = new->uid;
|
||||
#endif
|
||||
|
||||
free_avail = 1; /* Must be free space now. */
|
||||
@@ -653,9 +639,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
||||
if (!is_expired(now, crecp) && !is_outdated_cname_pointer(crecp))
|
||||
{
|
||||
if ((crecp->flags & F_FORWARD) &&
|
||||
#ifdef HAVE_DNSSEC
|
||||
(((crecp->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
|
||||
#endif
|
||||
(crecp->flags & prot) &&
|
||||
hostname_isequal(cache_get_name(crecp), name))
|
||||
{
|
||||
@@ -713,9 +696,6 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
||||
|
||||
if (ans &&
|
||||
(ans->flags & F_FORWARD) &&
|
||||
#ifdef HAVE_DNSSEC
|
||||
(((ans->flags & (F_DNSKEY | F_DS)) == (prot & (F_DNSKEY | F_DS))) || (prot & F_NSIGMATCH)) &&
|
||||
#endif
|
||||
(ans->flags & prot) &&
|
||||
hostname_isequal(cache_get_name(ans), name))
|
||||
return ans;
|
||||
@@ -794,10 +774,12 @@ static void add_hosts_cname(struct crec *target)
|
||||
struct cname *a;
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(cache_get_name(target), a->target) &&
|
||||
if (a->alias[1] != '*' &&
|
||||
hostname_isequal(cache_get_name(target), a->target) &&
|
||||
(crec = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
||||
crec->ttd = a->ttl;
|
||||
crec->name.namep = a->alias;
|
||||
crec->addr.cname.target.cache = target;
|
||||
crec->addr.cname.uid = target->uid;
|
||||
@@ -939,7 +921,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
||||
if (!f)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to load names from %s: %s"), filename, strerror(errno));
|
||||
return 0;
|
||||
return cache_size;
|
||||
}
|
||||
|
||||
eatspace(f);
|
||||
@@ -1001,6 +983,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
||||
strcat(cache->name.sname, ".");
|
||||
strcat(cache->name.sname, domain_suffix);
|
||||
cache->flags = flags;
|
||||
cache->ttd = daemon->local_ttl;
|
||||
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
|
||||
name_count++;
|
||||
}
|
||||
@@ -1008,6 +991,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
||||
{
|
||||
strcpy(cache->name.sname, canon);
|
||||
cache->flags = flags;
|
||||
cache->ttd = daemon->local_ttl;
|
||||
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
|
||||
name_count++;
|
||||
}
|
||||
@@ -1073,10 +1057,12 @@ void cache_reload(void)
|
||||
/* Add CNAMEs to interface_names to the cache */
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(a->target, intr->name) &&
|
||||
if (a->alias[1] != '*' &&
|
||||
hostname_isequal(a->target, intr->name) &&
|
||||
((cache = whine_malloc(sizeof(struct crec)))))
|
||||
{
|
||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||
cache->ttd = a->ttl;
|
||||
cache->name.namep = a->alias;
|
||||
cache->addr.cname.target.int_name = intr;
|
||||
cache->addr.cname.uid = SRC_INTERFACE;
|
||||
@@ -1091,6 +1077,7 @@ void cache_reload(void)
|
||||
(cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
|
||||
{
|
||||
cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
|
||||
cache->ttd = daemon->local_ttl;
|
||||
cache->name.namep = ds->name;
|
||||
cache->addr.ds.keylen = ds->digestlen;
|
||||
cache->addr.ds.algo = ds->algo;
|
||||
@@ -1115,6 +1102,7 @@ void cache_reload(void)
|
||||
(cache = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
cache->name.namep = nl->name;
|
||||
cache->ttd = hr->ttl;
|
||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV4 | F_NAMEP | F_CONFIG;
|
||||
add_hosts_entry(cache, (struct all_addr *)&hr->addr, INADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
|
||||
}
|
||||
@@ -1123,6 +1111,7 @@ void cache_reload(void)
|
||||
(cache = whine_malloc(sizeof(struct crec))))
|
||||
{
|
||||
cache->name.namep = nl->name;
|
||||
cache->ttd = hr->ttl;
|
||||
cache->flags = F_HOSTS | F_IMMORTAL | F_FORWARD | F_REVERSE | F_IPV6 | F_NAMEP | F_CONFIG;
|
||||
add_hosts_entry(cache, (struct all_addr *)&hr->addr6, IN6ADDRSZ, SRC_CONFIG, (struct crec **)daemon->packet, revhashsz);
|
||||
}
|
||||
@@ -1190,7 +1179,8 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
struct cname *a;
|
||||
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (hostname_isequal(cache_get_name(target), a->target))
|
||||
if (a->alias[1] != '*' &&
|
||||
hostname_isequal(cache_get_name(target), a->target))
|
||||
{
|
||||
if ((aliasc = dhcp_spare))
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
@@ -1303,6 +1293,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NO_ID
|
||||
int cache_make_stat(struct txt_record *t)
|
||||
{
|
||||
static char *buff = NULL;
|
||||
@@ -1398,6 +1389,7 @@ int cache_make_stat(struct txt_record *t)
|
||||
*buff = len;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* There can be names in the cache containing control chars, don't
|
||||
mess up logging or open security holes. */
|
||||
@@ -1472,11 +1464,7 @@ void dump_cache(time_t now)
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if (cache->flags & F_DS)
|
||||
{
|
||||
if (cache->flags & F_DNSKEY)
|
||||
/* RRSIG */
|
||||
sprintf(a, "%5u %3u %s", cache->addr.sig.keytag,
|
||||
cache->addr.sig.algo, querystr("", cache->addr.sig.type_covered));
|
||||
else if (!(cache->flags & F_NEG))
|
||||
if (!(cache->flags & F_NEG))
|
||||
sprintf(a, "%5u %3u %3u", cache->addr.ds.keytag,
|
||||
cache->addr.ds.algo, cache->addr.ds.digest);
|
||||
}
|
||||
@@ -1502,8 +1490,6 @@ void dump_cache(time_t now)
|
||||
else if (cache->flags & F_CNAME)
|
||||
t = "C";
|
||||
#ifdef HAVE_DNSSEC
|
||||
else if ((cache->flags & (F_DS | F_DNSKEY)) == (F_DS | F_DNSKEY))
|
||||
t = "G"; /* DNSKEY and DS set -> RRISG */
|
||||
else if (cache->flags & F_DS)
|
||||
t = "S";
|
||||
else if (cache->flags & F_DNSKEY)
|
||||
@@ -1525,7 +1511,7 @@ void dump_cache(time_t now)
|
||||
/* ctime includes trailing \n - eat it */
|
||||
*(p-1) = 0;
|
||||
#endif
|
||||
my_syslog(LOG_INFO, daemon->namebuff);
|
||||
my_syslog(LOG_INFO, "%s", daemon->namebuff);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1606,7 +1592,7 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
|
||||
if (addr)
|
||||
{
|
||||
if (flags & F_KEYTAG)
|
||||
sprintf(daemon->addrbuff, arg, addr->addr.keytag);
|
||||
sprintf(daemon->addrbuff, arg, addr->addr.log.keytag, addr->addr.log.algo, addr->addr.log.digest);
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
|
||||
55
src/config.h
55
src/config.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,13 +18,16 @@
|
||||
#define MAX_PROCS 20 /* max no children for TCP requests */
|
||||
#define CHILD_LIFETIME 150 /* secs 'till terminated (RFC1035 suggests > 120s) */
|
||||
#define TCP_MAX_QUERIES 100 /* Maximum number of queries per incoming TCP connection */
|
||||
#define TCP_BACKLOG 32 /* kernel backlog limit for TCP connections */
|
||||
#define EDNS_PKTSZ 4096 /* default max EDNS.0 UDP packet from RFC5625 */
|
||||
#define SAFE_PKTSZ 1280 /* "go anywhere" UDP packet size */
|
||||
#define KEYBLOCK_LEN 40 /* choose to mininise fragmentation when storing DNSSEC keys */
|
||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||
#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 RANDOM_SOCKS 64 /* max simultaneous random ports */
|
||||
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
|
||||
#define CACHESIZ 150 /* default cache size */
|
||||
@@ -91,13 +94,13 @@ HAVE_DBUS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_IDN
|
||||
define this if you want international domain name support.
|
||||
NOTE: for backwards compatibility, IDN support is automatically
|
||||
included when internationalisation support is built, using the
|
||||
*-i18n makefile targets, even if HAVE_IDN is not explicitly set.
|
||||
define this if you want international domain name 2003 support.
|
||||
|
||||
HAVE_LIBIDN2
|
||||
define this if you want international domain name 2008 support.
|
||||
|
||||
HAVE_CONNTRACK
|
||||
define this to include code which propogates conntrack marks from
|
||||
define this to include code which propagates conntrack marks from
|
||||
incoming DNS queries to the corresponding upstream queries. This adds
|
||||
a build-dependency on libnetfilter_conntrack, but the resulting binary will
|
||||
still run happily on a kernel without conntrack support.
|
||||
@@ -119,6 +122,8 @@ HAVE_LOOP
|
||||
HAVE_INOTIFY
|
||||
use the Linux inotify facility to efficiently re-read configuration files.
|
||||
|
||||
NO_ID
|
||||
Don't report *.bind CHAOS info to clients, forward such requests upstream instead.
|
||||
NO_IPV6
|
||||
NO_TFTP
|
||||
NO_DHCP
|
||||
@@ -127,7 +132,7 @@ NO_SCRIPT
|
||||
NO_LARGEFILE
|
||||
NO_AUTH
|
||||
NO_INOTIFY
|
||||
these are avilable to explictly 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
|
||||
which are enabled by default in the distributed source tree. Building dnsmasq
|
||||
with something like "make COPTS=-DNO_SCRIPT" will do the trick.
|
||||
@@ -172,6 +177,7 @@ RESOLVFILE
|
||||
/* #define HAVE_LUASCRIPT */
|
||||
/* #define HAVE_DBUS */
|
||||
/* #define HAVE_IDN */
|
||||
/* #define HAVE_LIBIDN2 */
|
||||
/* #define HAVE_CONNTRACK */
|
||||
/* #define HAVE_DNSSEC */
|
||||
|
||||
@@ -228,7 +234,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
defined if struct sockaddr has sa_len field (*BSD)
|
||||
*/
|
||||
|
||||
/* Must preceed __linux__ since uClinux defines __linux__ too. */
|
||||
/* Must precede __linux__ since uClinux defines __linux__ too. */
|
||||
#if defined(__uClinux__)
|
||||
#define HAVE_LINUX_NETWORK
|
||||
#define HAVE_GETOPT_LONG
|
||||
@@ -266,7 +272,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
defined(__DragonFly__) || \
|
||||
defined(__FreeBSD_kernel__)
|
||||
#define HAVE_BSD_NETWORK
|
||||
/* Later verions of FreeBSD have getopt_long() */
|
||||
/* Later versions of FreeBSD have getopt_long() */
|
||||
#if defined(optional_argument) && defined(required_argument)
|
||||
# define HAVE_GETOPT_LONG
|
||||
#endif
|
||||
@@ -337,7 +343,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#define HAVE_DHCP
|
||||
#endif
|
||||
|
||||
#if defined(NO_SCRIPT) || !defined(HAVE_DHCP) || defined(NO_FORK)
|
||||
#if defined(NO_SCRIPT) || defined(NO_FORK)
|
||||
#undef HAVE_SCRIPT
|
||||
#undef HAVE_LUASCRIPT
|
||||
#endif
|
||||
@@ -364,7 +370,7 @@ HAVE_SOCKADDR_SA_LEN
|
||||
#endif
|
||||
|
||||
/* Define a string indicating which options are in use.
|
||||
DNSMASQP_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||
DNSMASQ_COMPILE_OPTS is only defined in dnsmasq.c */
|
||||
|
||||
#ifdef DNSMASQ_COMPILE_OPTS
|
||||
|
||||
@@ -391,10 +397,14 @@ static char *compile_opts =
|
||||
"no-"
|
||||
#endif
|
||||
"i18n "
|
||||
#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
"IDN2 "
|
||||
#else
|
||||
#if !defined(HAVE_IDN)
|
||||
"no-"
|
||||
#endif
|
||||
"IDN "
|
||||
#endif
|
||||
"IDN "
|
||||
#endif
|
||||
#ifndef HAVE_DHCP
|
||||
"no-"
|
||||
#endif
|
||||
@@ -404,14 +414,14 @@ static char *compile_opts =
|
||||
"no-"
|
||||
# endif
|
||||
"DHCPv6 "
|
||||
# if !defined(HAVE_SCRIPT)
|
||||
#endif
|
||||
#if !defined(HAVE_SCRIPT)
|
||||
"no-scripts "
|
||||
# else
|
||||
# if !defined(HAVE_LUASCRIPT)
|
||||
"no-"
|
||||
# endif
|
||||
"Lua "
|
||||
#else
|
||||
# if !defined(HAVE_LUASCRIPT)
|
||||
"no-"
|
||||
# endif
|
||||
"Lua "
|
||||
#endif
|
||||
#ifndef HAVE_TFTP
|
||||
"no-"
|
||||
@@ -433,6 +443,9 @@ static char *compile_opts =
|
||||
"no-"
|
||||
#endif
|
||||
"DNSSEC "
|
||||
#ifdef NO_ID
|
||||
"no-ID "
|
||||
#endif
|
||||
#ifndef HAVE_LOOP
|
||||
"no-"
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
|
||||
30
src/dbus.c
30
src/dbus.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -549,17 +549,16 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
|
||||
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid IP address '%s'", ipaddr);
|
||||
|
||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL,
|
||||
&hw_type);
|
||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
|
||||
|
||||
lease_set_hwaddr(lease, dhcp_chaddr, clid, hw_len, hw_type,
|
||||
clid_len, now, 0);
|
||||
lease_set_expires(lease, expires, now);
|
||||
if (hostname_len != 0)
|
||||
lease_set_hostname(lease, hostname, 0, get_domain(lease->addr), NULL);
|
||||
|
||||
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
|
||||
@@ -749,8 +748,7 @@ char *dbus_init(void)
|
||||
}
|
||||
|
||||
|
||||
void set_dbus_listeners(int *maxfdp,
|
||||
fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
void set_dbus_listeners(void)
|
||||
{
|
||||
struct watch *w;
|
||||
|
||||
@@ -760,19 +758,17 @@ void set_dbus_listeners(int *maxfdp,
|
||||
unsigned int flags = dbus_watch_get_flags(w->watch);
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
bump_maxfd(fd, maxfdp);
|
||||
|
||||
if (flags & DBUS_WATCH_READABLE)
|
||||
FD_SET(fd, rset);
|
||||
poll_listen(fd, POLLIN);
|
||||
|
||||
if (flags & DBUS_WATCH_WRITABLE)
|
||||
FD_SET(fd, wset);
|
||||
poll_listen(fd, POLLOUT);
|
||||
|
||||
FD_SET(fd, eset);
|
||||
poll_listen(fd, POLLERR);
|
||||
}
|
||||
}
|
||||
|
||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
void check_dbus_listeners()
|
||||
{
|
||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||
struct watch *w;
|
||||
@@ -783,13 +779,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
|
||||
unsigned int flags = 0;
|
||||
int fd = dbus_watch_get_unix_fd(w->watch);
|
||||
|
||||
if (FD_ISSET(fd, rset))
|
||||
if (poll_check(fd, POLLIN))
|
||||
flags |= DBUS_WATCH_READABLE;
|
||||
|
||||
if (FD_ISSET(fd, wset))
|
||||
if (poll_check(fd, POLLOUT))
|
||||
flags |= DBUS_WATCH_WRITABLE;
|
||||
|
||||
if (FD_ISSET(fd, eset))
|
||||
if (poll_check(fd, POLLERR))
|
||||
flags |= DBUS_WATCH_ERROR;
|
||||
|
||||
if (flags != 0)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
void dhcp_common_init(void)
|
||||
{
|
||||
/* These each hold a DHCP option max size 255
|
||||
and get a terminating zero added */
|
||||
daemon->dhcp_buff = safe_malloc(256);
|
||||
daemon->dhcp_buff2 = safe_malloc(256);
|
||||
daemon->dhcp_buff3 = safe_malloc(256);
|
||||
/* These each hold a DHCP option max size 255
|
||||
and get a terminating zero added */
|
||||
daemon->dhcp_buff = safe_malloc(DHCP_BUFF_SZ);
|
||||
daemon->dhcp_buff2 = safe_malloc(DHCP_BUFF_SZ);
|
||||
daemon->dhcp_buff3 = safe_malloc(DHCP_BUFF_SZ);
|
||||
|
||||
/* dhcp_packet is used by v4 and v6, outpacket only by v6
|
||||
sizeof(struct dhcp_packet) is as good an initial size as any,
|
||||
@@ -599,7 +599,7 @@ static const struct opttab_t opttab6[] = {
|
||||
{ "sntp-server", 31, OT_ADDR_LIST },
|
||||
{ "information-refresh-time", 32, OT_TIME },
|
||||
{ "FQDN", 39, OT_INTERNAL | OT_RFC1035_NAME },
|
||||
{ "ntp-server", 56, OT_ADDR_LIST },
|
||||
{ "ntp-server", 56, 0 },
|
||||
{ "bootfile-url", 59, OT_NAME },
|
||||
{ "bootfile-param", 60, OT_CSTRING },
|
||||
{ NULL, 0, 0 }
|
||||
@@ -855,14 +855,14 @@ void log_context(int family, struct dhcp_context *context)
|
||||
if (context->flags & CONTEXT_RA_STATELESS)
|
||||
{
|
||||
if (context->flags & CONTEXT_TEMPLATE)
|
||||
strncpy(daemon->dhcp_buff, context->template_interface, 256);
|
||||
strncpy(daemon->dhcp_buff, context->template_interface, DHCP_BUFF_SZ);
|
||||
else
|
||||
strcpy(daemon->dhcp_buff, daemon->addrbuff);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
inet_ntop(family, start, daemon->dhcp_buff, 256);
|
||||
inet_ntop(family, end, daemon->dhcp_buff3, 256);
|
||||
inet_ntop(family, start, daemon->dhcp_buff, DHCP_BUFF_SZ);
|
||||
inet_ntop(family, end, daemon->dhcp_buff3, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO,
|
||||
(context->flags & CONTEXT_RA_STATELESS) ?
|
||||
_("%s stateless on %s%.0s%.0s%s") :
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,10 @@
|
||||
#define DHCP_CLIENT_ALTPORT 1068
|
||||
#define PXE_PORT 4011
|
||||
|
||||
/* These each hold a DHCP option max size 255
|
||||
and get a terminating zero added */
|
||||
#define DHCP_BUFF_SZ 256
|
||||
|
||||
#define BOOTREQUEST 1
|
||||
#define BOOTREPLY 2
|
||||
#define DHCP_COOKIE 0x63825363
|
||||
|
||||
189
src/dhcp.c
189
src/dhcp.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -67,9 +67,9 @@ static int make_fd(int port)
|
||||
setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)
|
||||
die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
|
||||
/* When bind-interfaces is set, there might be more than one dnmsasq
|
||||
/* When bind-interfaces is set, there might be more than one dnsmasq
|
||||
instance binding port 67. That's OK if they serve different networks.
|
||||
Need to set REUSEADDR|REUSEPORT to make this posible.
|
||||
Need to set REUSEADDR|REUSEPORT to make this possible.
|
||||
Handle the case that REUSEPORT is defined, but the kernel doesn't
|
||||
support it. This handles the introduction of REUSEPORT on Linux. */
|
||||
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||
@@ -145,11 +145,14 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
struct cmsghdr *cmptr;
|
||||
struct iovec iov;
|
||||
ssize_t sz;
|
||||
int iface_index = 0, unicast_dest = 0, is_inform = 0;
|
||||
int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
|
||||
int rcvd_iface_index;
|
||||
struct in_addr iface_addr;
|
||||
struct iface_param parm;
|
||||
time_t recvtime = now;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
struct arpreq arp_req;
|
||||
struct timeval tv;
|
||||
#endif
|
||||
|
||||
union {
|
||||
@@ -176,6 +179,9 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
return;
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
|
||||
recvtime = tv.tv_sec;
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
@@ -217,9 +223,13 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
|
||||
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
|
||||
ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != 0)
|
||||
return;
|
||||
|
||||
|
||||
mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
|
||||
loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* ARP fiddling uses original interface even if we pretend to use a different one. */
|
||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
||||
@@ -230,6 +240,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
--bridge-interface option), change ifr.ifr_name so that we look
|
||||
for DHCP contexts associated with the aliased interface instead
|
||||
of with the aliasing one. */
|
||||
rcvd_iface_index = iface_index;
|
||||
for (bridge = daemon->bridges; bridge; bridge = bridge->next)
|
||||
{
|
||||
for (alias = bridge->alias; alias; alias = alias->next)
|
||||
@@ -262,8 +273,8 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
if ((relay = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, ifr.ifr_name)))
|
||||
{
|
||||
/* Reply from server, using us as relay. */
|
||||
iface_index = relay->iface_index;
|
||||
if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name))
|
||||
rcvd_iface_index = relay->iface_index;
|
||||
if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
|
||||
return;
|
||||
is_relay_reply = 1;
|
||||
iov.iov_len = sz;
|
||||
@@ -278,7 +289,8 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||
else
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
|
||||
if (iface_check(AF_INET, NULL, ifr.ifr_name, NULL))
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -323,7 +335,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
|
||||
/* We're relaying this request */
|
||||
if (parm.relay_local.s_addr != 0 &&
|
||||
relay_upstream4(parm.relay, (struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, iface_index))
|
||||
relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
|
||||
return;
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
@@ -332,14 +344,14 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz,
|
||||
now, unicast_dest, &is_inform, pxe_fd, iface_addr);
|
||||
now, unicast_dest, loopback, &is_inform, pxe_fd, iface_addr, recvtime);
|
||||
lease_update_file(now);
|
||||
lease_update_dns(0);
|
||||
|
||||
if (iov.iov_len == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
msg.msg_name = &dest;
|
||||
msg.msg_namelen = sizeof(dest);
|
||||
msg.msg_control = NULL;
|
||||
@@ -387,7 +399,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
msg.msg_controllen = sizeof(control_u);
|
||||
cmptr = CMSG_FIRSTHDR(&msg);
|
||||
pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
|
||||
pkt->ipi_ifindex = iface_index;
|
||||
pkt->ipi_ifindex = rcvd_iface_index;
|
||||
pkt->ipi_spec_dst.s_addr = 0;
|
||||
msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
|
||||
cmptr->cmsg_level = IPPROTO_IP;
|
||||
@@ -452,8 +464,13 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#endif
|
||||
|
||||
while(retry_send(sendmsg(fd, &msg, 0)));
|
||||
|
||||
/* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
|
||||
if (errno != 0)
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
|
||||
inet_ntoa(dest.sin_addr), strerror(errno));
|
||||
}
|
||||
|
||||
|
||||
/* check against secondary interface addresses */
|
||||
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||
@@ -488,7 +505,7 @@ static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
||||
3) Fills in local (this host) and router (this host or relay) addresses.
|
||||
4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
|
||||
|
||||
Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
|
||||
Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
|
||||
|
||||
static int complete_context(struct in_addr local, int if_index, char *label,
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam)
|
||||
@@ -588,7 +605,7 @@ struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||
{
|
||||
/* We start of with a set of possible contexts, all on the current physical interface.
|
||||
These are chained on ->current.
|
||||
Here we have an address, and return the actual context correponding to that
|
||||
Here we have an address, and return the actual context corresponding to that
|
||||
address. Note that none may fit, if the address came a dhcp-host and is outside
|
||||
any dhcp-range. In that case we return a static range if possible, or failing that,
|
||||
any context on the correct subnet. (If there's more than one, this is a dodgy
|
||||
@@ -630,9 +647,69 @@ struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct i
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check if and address is in use by sending ICMP ping.
|
||||
This wrapper handles a cache and load-limiting.
|
||||
Return is NULL is address in use, or a pointer to a cache entry
|
||||
recording that it isn't. */
|
||||
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
|
||||
{
|
||||
static struct ping_result dummy;
|
||||
struct ping_result *r, *victim = NULL;
|
||||
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
|
||||
((float)PING_WAIT)));
|
||||
|
||||
/* check if we failed to ping addr sometime in the last
|
||||
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
|
||||
This avoids problems when a stupid client bangs
|
||||
on us repeatedly. As a final check, if we did more
|
||||
than 60% of the possible ping checks in the last
|
||||
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
|
||||
for (count = 0, r = daemon->ping_results; r; r = r->next)
|
||||
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
|
||||
victim = r; /* old record */
|
||||
else
|
||||
{
|
||||
count++;
|
||||
if (r->addr.s_addr == addr.s_addr)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* didn't find cached entry */
|
||||
if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
|
||||
{
|
||||
/* overloaded, or configured not to check, loopback interface, return "not in use" */
|
||||
dummy.hash = 0;
|
||||
return &dummy;
|
||||
}
|
||||
else if (icmp_ping(addr))
|
||||
return NULL; /* address in use. */
|
||||
else
|
||||
{
|
||||
/* at this point victim may hold an expired record */
|
||||
if (!victim)
|
||||
{
|
||||
if ((victim = whine_malloc(sizeof(struct ping_result))))
|
||||
{
|
||||
victim->next = daemon->ping_results;
|
||||
daemon->ping_results = victim;
|
||||
}
|
||||
}
|
||||
|
||||
/* record that this address is OK for 30s
|
||||
without more ping checks */
|
||||
if (victim)
|
||||
{
|
||||
victim->addr = addr;
|
||||
victim->time = now;
|
||||
victim->hash = hash;
|
||||
}
|
||||
return victim;
|
||||
}
|
||||
}
|
||||
|
||||
int address_allocate(struct dhcp_context *context,
|
||||
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
|
||||
struct dhcp_netid *netids, time_t now)
|
||||
struct dhcp_netid *netids, time_t now, int loopback)
|
||||
{
|
||||
/* Find a free address: exclude anything in use and anything allocated to
|
||||
a particular hwaddr/clientid/hostname in our configuration.
|
||||
@@ -646,7 +723,11 @@ int address_allocate(struct dhcp_context *context,
|
||||
/* hash hwaddr: use the SDBM hashing algorithm. Seems to give good
|
||||
dispersal even with similarly-valued "strings". */
|
||||
for (j = 0, i = 0; i < hw_len; i++)
|
||||
j += hwaddr[i] + (j << 6) + (j << 16) - j;
|
||||
j = hwaddr[i] + (j << 6) + (j << 16) - j;
|
||||
|
||||
/* j == 0 is marker */
|
||||
if (j == 0)
|
||||
j = 1;
|
||||
|
||||
for (pass = 0; pass <= 1; pass++)
|
||||
for (c = context; c; c = c->current)
|
||||
@@ -684,69 +765,27 @@ int address_allocate(struct dhcp_context *context,
|
||||
(!IN_CLASSC(ntohl(addr.s_addr)) ||
|
||||
((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
|
||||
{
|
||||
struct ping_result *r, *victim = NULL;
|
||||
int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
|
||||
((float)PING_WAIT)));
|
||||
struct ping_result *r;
|
||||
|
||||
*addrp = addr;
|
||||
|
||||
/* check if we failed to ping addr sometime in the last
|
||||
PING_CACHE_TIME seconds. If so, assume the same situation still exists.
|
||||
This avoids problems when a stupid client bangs
|
||||
on us repeatedly. As a final check, if we did more
|
||||
than 60% of the possible ping checks in the last
|
||||
PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
|
||||
for (count = 0, r = daemon->ping_results; r; r = r->next)
|
||||
if (difftime(now, r->time) > (float)PING_CACHE_TIME)
|
||||
victim = r; /* old record */
|
||||
else
|
||||
{
|
||||
count++;
|
||||
if (r->addr.s_addr == addr.s_addr)
|
||||
{
|
||||
/* consec-ip mode: we offered this address for another client
|
||||
(different hash) recently, don't offer it to this one. */
|
||||
if (option_bool(OPT_CONSEC_ADDR) && r->hash != j)
|
||||
break;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!r)
|
||||
{
|
||||
if ((count < max) && !option_bool(OPT_NO_PING) && icmp_ping(addr))
|
||||
if ((r = do_icmp_ping(now, addr, j, loopback)))
|
||||
{
|
||||
/* consec-ip mode: we offered this address for another client
|
||||
(different hash) recently, don't offer it to this one. */
|
||||
if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
|
||||
{
|
||||
/* address in use: perturb address selection so that we are
|
||||
less likely to try this address again. */
|
||||
if (!option_bool(OPT_CONSEC_ADDR))
|
||||
c->addr_epoch++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* at this point victim may hold an expired record */
|
||||
if (!victim)
|
||||
{
|
||||
if ((victim = whine_malloc(sizeof(struct ping_result))))
|
||||
{
|
||||
victim->next = daemon->ping_results;
|
||||
daemon->ping_results = victim;
|
||||
}
|
||||
}
|
||||
|
||||
/* record that this address is OK for 30s
|
||||
without more ping checks */
|
||||
if (victim)
|
||||
{
|
||||
victim->addr = addr;
|
||||
victim->time = now;
|
||||
victim->hash = j;
|
||||
}
|
||||
*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++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
|
||||
|
||||
if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
|
||||
87
src/dhcp6.c
87
src/dhcp6.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -27,17 +27,10 @@ struct iface_param {
|
||||
int ind, addr_match;
|
||||
};
|
||||
|
||||
struct mac_param {
|
||||
struct in6_addr *target;
|
||||
unsigned char *mac;
|
||||
unsigned int maclen;
|
||||
};
|
||||
|
||||
|
||||
static int complete_context6(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags,
|
||||
unsigned int preferred, unsigned int valid, void *vparam);
|
||||
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv);
|
||||
static int make_duid1(int index, unsigned int type, char *mac, size_t maclen, void *parm);
|
||||
|
||||
void dhcp6_init(void)
|
||||
@@ -58,9 +51,9 @@ void dhcp6_init(void)
|
||||
!set_ipv6pktinfo(fd))
|
||||
die (_("cannot create DHCPv6 socket: %s"), NULL, EC_BADNET);
|
||||
|
||||
/* When bind-interfaces is set, there might be more than one dnmsasq
|
||||
/* When bind-interfaces is set, there might be more than one dnsmasq
|
||||
instance binding port 547. That's OK if they serve different networks.
|
||||
Need to set REUSEADDR|REUSEPORT to make this posible.
|
||||
Need to set REUSEADDR|REUSEPORT to make this possible.
|
||||
Handle the case that REUSEPORT is defined, but the kernel doesn't
|
||||
support it. This handles the introduction of REUSEPORT on Linux. */
|
||||
if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
|
||||
@@ -227,7 +220,7 @@ void dhcp6_packet(time_t now)
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id);
|
||||
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -257,16 +250,15 @@ void dhcp6_packet(time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep)
|
||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsigned int *maclenp, unsigned int *mactypep, time_t now)
|
||||
{
|
||||
/* Recieving a packet from a host does not populate the neighbour
|
||||
/* Receiving a packet from a host does not populate the neighbour
|
||||
cache, so we send a neighbour discovery request if we can't
|
||||
find the sender. Repeat a few times in case of packet loss. */
|
||||
|
||||
struct neigh_packet neigh;
|
||||
struct sockaddr_in6 addr;
|
||||
struct mac_param mac_param;
|
||||
int i;
|
||||
union mysockaddr addr;
|
||||
int i, maclen;
|
||||
|
||||
neigh.type = ND_NEIGHBOR_SOLICIT;
|
||||
neigh.code = 0;
|
||||
@@ -277,55 +269,31 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.sin6_len = sizeof(struct sockaddr_in6);
|
||||
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
addr.sin6_family = AF_INET6;
|
||||
addr.sin6_port = htons(IPPROTO_ICMPV6);
|
||||
addr.sin6_addr = *client;
|
||||
addr.sin6_scope_id = iface;
|
||||
|
||||
mac_param.target = client;
|
||||
mac_param.maclen = 0;
|
||||
mac_param.mac = mac;
|
||||
addr.in6.sin6_family = AF_INET6;
|
||||
addr.in6.sin6_port = htons(IPPROTO_ICMPV6);
|
||||
addr.in6.sin6_addr = *client;
|
||||
addr.in6.sin6_scope_id = iface;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
iface_enumerate(AF_UNSPEC, &mac_param, find_mac);
|
||||
|
||||
if (mac_param.maclen != 0)
|
||||
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
|
||||
break;
|
||||
|
||||
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
||||
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
|
||||
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 100000000; /* 100ms */
|
||||
nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
*maclenp = mac_param.maclen;
|
||||
*maclenp = maclen;
|
||||
*mactypep = ARPHRD_ETHER;
|
||||
}
|
||||
|
||||
static int find_mac(int family, char *addrp, char *mac, size_t maclen, void *parmv)
|
||||
{
|
||||
struct mac_param *parm = parmv;
|
||||
|
||||
if (family == AF_INET6 && IN6_ARE_ADDR_EQUAL(parm->target, (struct in6_addr *)addrp))
|
||||
{
|
||||
if (maclen <= DHCP_CHADDR_MAX)
|
||||
{
|
||||
parm->maclen = maclen;
|
||||
memcpy(parm->mac, mac, maclen);
|
||||
}
|
||||
|
||||
return 0; /* found, abort */
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int complete_context6(struct in6_addr *local, int prefix,
|
||||
int scope, int if_index, int flags, unsigned int preferred,
|
||||
unsigned int valid, void *vparam)
|
||||
@@ -376,7 +344,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
{
|
||||
struct dhcp_context *tmp, **up;
|
||||
|
||||
/* use interface values only for contructed contexts */
|
||||
/* use interface values only for constructed contexts */
|
||||
if (!(context->flags & CONTEXT_CONSTRUCTED))
|
||||
preferred = valid = 0xffffffff;
|
||||
else if (flags & IFACE_DEPRECATED)
|
||||
@@ -452,7 +420,7 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
||||
j = rand64();
|
||||
else
|
||||
for (j = iaid, i = 0; i < clid_len; i++)
|
||||
j += clid[i] + (j << 6) + (j << 16) - j;
|
||||
j = clid[i] + (j << 6) + (j << 16) - j;
|
||||
|
||||
for (pass = 0; pass <= plain_range ? 1 : 0; pass++)
|
||||
for (c = context; c; c = c->current)
|
||||
@@ -466,7 +434,16 @@ struct dhcp_context *address6_allocate(struct dhcp_context *context, unsigned c
|
||||
/* seed is largest extant lease addr in this context */
|
||||
start = lease_find_max_addr6(c) + serial;
|
||||
else
|
||||
start = addr6part(&c->start6) + ((j + c->addr_epoch) % (1 + addr6part(&c->end6) - addr6part(&c->start6)));
|
||||
{
|
||||
u64 range = 1 + addr6part(&c->end6) - addr6part(&c->start6);
|
||||
u64 offset = j + c->addr_epoch;
|
||||
|
||||
/* don't divide by zero if range is whole 2^64 */
|
||||
if (range != 0)
|
||||
offset = offset % range;
|
||||
|
||||
start = addr6part(&c->start6) + offset;
|
||||
}
|
||||
|
||||
/* iterate until we find a free address. */
|
||||
addr = start;
|
||||
@@ -695,7 +672,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
||||
/* address went, now it's back */
|
||||
log_context(AF_INET6, context);
|
||||
/* fast RAs for a while */
|
||||
ra_start_unsolicted(param->now, context);
|
||||
ra_start_unsolicited(param->now, context);
|
||||
param->newone = 1;
|
||||
/* Add address to name again */
|
||||
if (context->flags & CONTEXT_RA_NAME)
|
||||
@@ -718,7 +695,7 @@ static int construct_worker(struct in6_addr *local, int prefix,
|
||||
context->next = daemon->dhcp6;
|
||||
daemon->dhcp6 = context;
|
||||
|
||||
ra_start_unsolicted(param->now, context);
|
||||
ra_start_unsolicited(param->now, context);
|
||||
/* we created a new one, need to call
|
||||
lease_update_file to get periodic functions called */
|
||||
param->newone = 1;
|
||||
@@ -766,7 +743,7 @@ void dhcp_construct_contexts(time_t now)
|
||||
/* maximum time is 2 hours, from RFC */
|
||||
if (context->saved_valid > 7200) /* 2 hours */
|
||||
context->saved_valid = 7200;
|
||||
ra_start_unsolicted(now, context);
|
||||
ra_start_unsolicited(now, context);
|
||||
param.newone = 1; /* include deletion */
|
||||
|
||||
if (context->flags & CONTEXT_RA_NAME)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#define NAMESERVER_PORT 53
|
||||
#define TFTP_PORT 69
|
||||
#define MAX_PORT 65535u
|
||||
|
||||
#define IN6ADDRSZ 16
|
||||
#define INADDRSZ 4
|
||||
@@ -77,6 +78,8 @@
|
||||
|
||||
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
||||
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
||||
#define EDNS0_OPTION_NOMDEVICEID 65073 /* Nominum temporary assignment */
|
||||
#define EDNS0_OPTION_NOMCPEID 65074 /* Nominum temporary assignment */
|
||||
|
||||
struct dns_header {
|
||||
u16 id;
|
||||
|
||||
453
src/dnsmasq.c
453
src/dnsmasq.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -24,8 +24,8 @@ struct daemon *daemon;
|
||||
static volatile pid_t pid = 0;
|
||||
static volatile int pipewrite;
|
||||
|
||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
|
||||
static void check_dns_listeners(fd_set *set, time_t now);
|
||||
static int set_dns_listeners(time_t now);
|
||||
static void check_dns_listeners(time_t now);
|
||||
static void sig_handler(int sig);
|
||||
static void async_event(int pipe, time_t now);
|
||||
static void fatal_event(struct event_desc *ev, char *msg);
|
||||
@@ -91,8 +91,11 @@ int main (int argc, char **argv)
|
||||
if (daemon->edns_pktsz < PACKETSZ)
|
||||
daemon->edns_pktsz = PACKETSZ;
|
||||
|
||||
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
|
||||
daemon->edns_pktsz : DNSMASQ_PACKETSZ;
|
||||
/* Min buffer size: we check after adding each record, so there must be
|
||||
memory for the largest packet, and the largest record so the
|
||||
min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
|
||||
This might be increased is EDNS packet size if greater than the minimum. */
|
||||
daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
|
||||
daemon->packet = safe_malloc(daemon->packet_buff_sz);
|
||||
|
||||
daemon->addrbuff = safe_malloc(ADDRSTRLEN);
|
||||
@@ -166,8 +169,16 @@ int main (int argc, char **argv)
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
{
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (!daemon->ds)
|
||||
die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
|
||||
struct ds_config *ds;
|
||||
|
||||
/* Must have at least a root trust anchor, or the DNSSEC code
|
||||
can loop forever. */
|
||||
for (ds = daemon->ds; ds; ds = ds->next)
|
||||
if (ds->name[0] == 0)
|
||||
break;
|
||||
|
||||
if (!ds)
|
||||
die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
|
||||
|
||||
if (daemon->cachesize < CACHESIZ)
|
||||
die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
|
||||
@@ -191,12 +202,12 @@ int main (int argc, char **argv)
|
||||
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
if (daemon->max_logs != 0)
|
||||
die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
|
||||
die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (daemon->max_logs != 0)
|
||||
die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
|
||||
die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AUTH
|
||||
@@ -208,7 +219,13 @@ int main (int argc, char **argv)
|
||||
if (option_bool(OPT_LOOP_DETECT))
|
||||
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
|
||||
if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
|
||||
daemon->min_port = 1024u;
|
||||
|
||||
if (daemon->max_port < daemon->min_port)
|
||||
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
/* Create a serial at startup if not configured. */
|
||||
@@ -242,8 +259,11 @@ int main (int argc, char **argv)
|
||||
/* Note that order matters here, we must call lease_init before
|
||||
creating any file descriptors which shouldn't be leaked
|
||||
to the lease-script init process. We need to call common_init
|
||||
before lease_init to allocate buffers it uses.*/
|
||||
if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || daemon->relay6)
|
||||
before lease_init to allocate buffers it uses.
|
||||
The script subsystem relies on DHCP buffers, hence the last two
|
||||
conditions below. */
|
||||
if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
|
||||
daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
|
||||
{
|
||||
dhcp_common_init();
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
@@ -494,7 +514,7 @@ int main (int argc, char **argv)
|
||||
extent that an attacker running as the unprivileged user could replace the pidfile with a
|
||||
symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
|
||||
|
||||
The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
|
||||
The following code first deletes any existing file, and then opens it with the O_EXCL flag,
|
||||
ensuring that the open() fails should there be any existing file (because the unlink() failed,
|
||||
or an attacker exploited the race between unlink() and open()). This ensures that no symlink
|
||||
attack can succeed.
|
||||
@@ -541,17 +561,21 @@ int main (int argc, char **argv)
|
||||
{
|
||||
/* open stdout etc to /dev/null */
|
||||
int nullfd = open("/dev/null", O_RDWR);
|
||||
dup2(nullfd, STDOUT_FILENO);
|
||||
dup2(nullfd, STDERR_FILENO);
|
||||
dup2(nullfd, STDIN_FILENO);
|
||||
close(nullfd);
|
||||
if (nullfd != -1)
|
||||
{
|
||||
dup2(nullfd, STDOUT_FILENO);
|
||||
dup2(nullfd, STDERR_FILENO);
|
||||
dup2(nullfd, STDIN_FILENO);
|
||||
close(nullfd);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||
daemon->helperfd = -1;
|
||||
#ifdef HAVE_SCRIPT
|
||||
if ((daemon->dhcp || daemon->dhcp6) && (daemon->lease_change_command || daemon->luascript))
|
||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||
if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
|
||||
(daemon->lease_change_command || daemon->luascript))
|
||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||
#endif
|
||||
|
||||
if (!option_bool(OPT_DEBUG) && getuid() == 0)
|
||||
@@ -559,7 +583,7 @@ int main (int argc, char **argv)
|
||||
int bad_capabilities = 0;
|
||||
gid_t dummy;
|
||||
|
||||
/* remove all supplimentary groups */
|
||||
/* remove all supplementary groups */
|
||||
if (gp &&
|
||||
(setgroups(0, &dummy) == -1 ||
|
||||
setgid(gp->gr_gid) == -1))
|
||||
@@ -631,7 +655,7 @@ int main (int argc, char **argv)
|
||||
(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
|
||||
data->inheritable = 0;
|
||||
|
||||
/* lose the setuid and setgid capbilities */
|
||||
/* lose the setuid and setgid capabilities */
|
||||
if (capset(hdr, data) == -1)
|
||||
{
|
||||
send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
|
||||
@@ -690,10 +714,16 @@ int main (int argc, char **argv)
|
||||
|
||||
if (daemon->port == 0)
|
||||
my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
|
||||
else if (daemon->cachesize != 0)
|
||||
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
|
||||
else
|
||||
{
|
||||
if (daemon->cachesize != 0)
|
||||
my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
|
||||
|
||||
if (option_bool(OPT_LOCAL_SERVICE))
|
||||
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
|
||||
}
|
||||
|
||||
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
|
||||
|
||||
@@ -707,9 +737,6 @@ int main (int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (option_bool(OPT_LOCAL_SERVICE))
|
||||
my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
{
|
||||
@@ -726,7 +753,8 @@ int main (int argc, char **argv)
|
||||
|
||||
my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
|
||||
|
||||
if (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)
|
||||
my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
|
||||
|
||||
if (rc == 1)
|
||||
@@ -743,6 +771,8 @@ int main (int argc, char **argv)
|
||||
|
||||
if (option_bool(OPT_NOWILD))
|
||||
warn_bound_listeners();
|
||||
else if (!option_bool(OPT_CLEVERBIND))
|
||||
warn_wild_labels();
|
||||
|
||||
warn_int_names();
|
||||
|
||||
@@ -790,7 +820,7 @@ int main (int argc, char **argv)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
|
||||
# endif
|
||||
|
||||
/* after dhcp_contruct_contexts */
|
||||
/* after dhcp_construct_contexts */
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
lease_find_interfaces(now);
|
||||
#endif
|
||||
@@ -799,10 +829,6 @@ int main (int argc, char **argv)
|
||||
if (option_bool(OPT_TFTP))
|
||||
{
|
||||
struct tftp_prefix *p;
|
||||
#ifdef FD_SETSIZE
|
||||
if (FD_SETSIZE < (unsigned)max_fd)
|
||||
max_fd = FD_SETSIZE;
|
||||
#endif
|
||||
|
||||
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
|
||||
daemon->tftp_prefix ? _("root is ") : _("enabled"),
|
||||
@@ -862,126 +888,100 @@ int main (int argc, char **argv)
|
||||
|
||||
while (1)
|
||||
{
|
||||
int maxfd = -1;
|
||||
struct timeval t, *tp = NULL;
|
||||
fd_set rset, wset, eset;
|
||||
int t, timeout = -1;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
FD_ZERO(&eset);
|
||||
poll_reset();
|
||||
|
||||
/* if we are out of resources, find how long we have to wait
|
||||
for some to come free, we'll loop around then and restart
|
||||
listening for queries */
|
||||
if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
|
||||
{
|
||||
t.tv_usec = 0;
|
||||
tp = &t;
|
||||
}
|
||||
if ((t = set_dns_listeners(now)) != 0)
|
||||
timeout = t * 1000;
|
||||
|
||||
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
|
||||
if (daemon->tftp_trans ||
|
||||
(option_bool(OPT_DBUS) && !daemon->dbus))
|
||||
{
|
||||
t.tv_sec = 0;
|
||||
t.tv_usec = 250000;
|
||||
tp = &t;
|
||||
}
|
||||
timeout = 250;
|
||||
|
||||
/* Wake every second whilst waiting for DAD to complete */
|
||||
else if (is_dad_listeners())
|
||||
{
|
||||
t.tv_sec = 1;
|
||||
t.tv_usec = 0;
|
||||
tp = &t;
|
||||
}
|
||||
timeout = 1000;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
set_dbus_listeners(&maxfd, &rset, &wset, &eset);
|
||||
set_dbus_listeners();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->relay4)
|
||||
{
|
||||
FD_SET(daemon->dhcpfd, &rset);
|
||||
bump_maxfd(daemon->dhcpfd, &maxfd);
|
||||
poll_listen(daemon->dhcpfd, POLLIN);
|
||||
if (daemon->pxefd != -1)
|
||||
{
|
||||
FD_SET(daemon->pxefd, &rset);
|
||||
bump_maxfd(daemon->pxefd, &maxfd);
|
||||
}
|
||||
poll_listen(daemon->pxefd, POLLIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_dhcp6 || daemon->relay6)
|
||||
{
|
||||
FD_SET(daemon->dhcp6fd, &rset);
|
||||
bump_maxfd(daemon->dhcp6fd, &maxfd);
|
||||
}
|
||||
|
||||
poll_listen(daemon->dhcp6fd, POLLIN);
|
||||
|
||||
if (daemon->doing_ra)
|
||||
{
|
||||
FD_SET(daemon->icmp6fd, &rset);
|
||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||
}
|
||||
poll_listen(daemon->icmp6fd, POLLIN);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
if (daemon->inotifyfd != -1)
|
||||
{
|
||||
FD_SET(daemon->inotifyfd, &rset);
|
||||
bump_maxfd(daemon->inotifyfd, &maxfd);
|
||||
}
|
||||
poll_listen(daemon->inotifyfd, POLLIN);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
FD_SET(daemon->netlinkfd, &rset);
|
||||
bump_maxfd(daemon->netlinkfd, &maxfd);
|
||||
poll_listen(daemon->netlinkfd, POLLIN);
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
FD_SET(daemon->routefd, &rset);
|
||||
bump_maxfd(daemon->routefd, &maxfd);
|
||||
poll_listen(daemon->routefd, POLLIN);
|
||||
#endif
|
||||
|
||||
FD_SET(piperead, &rset);
|
||||
bump_maxfd(piperead, &maxfd);
|
||||
poll_listen(piperead, POLLIN);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
# ifdef HAVE_SCRIPT
|
||||
while (helper_buf_empty() && do_script_run(now));
|
||||
#ifdef HAVE_SCRIPT
|
||||
# ifdef HAVE_DHCP
|
||||
while (helper_buf_empty() && do_script_run(now));
|
||||
# endif
|
||||
|
||||
/* Refresh cache */
|
||||
if (option_bool(OPT_SCRIPT_ARP))
|
||||
find_mac(NULL, NULL, 0, now);
|
||||
while (helper_buf_empty() && do_arp_script_run());
|
||||
|
||||
# ifdef HAVE_TFTP
|
||||
while (helper_buf_empty() && do_tftp_script_run());
|
||||
# endif
|
||||
|
||||
if (!helper_buf_empty())
|
||||
{
|
||||
FD_SET(daemon->helperfd, &wset);
|
||||
bump_maxfd(daemon->helperfd, &maxfd);
|
||||
}
|
||||
# else
|
||||
poll_listen(daemon->helperfd, POLLOUT);
|
||||
#else
|
||||
/* need this for other side-effects */
|
||||
# ifdef HAVE_DHCP
|
||||
while (do_script_run(now));
|
||||
# endif
|
||||
|
||||
while (do_arp_script_run());
|
||||
|
||||
# ifdef HAVE_TFTP
|
||||
while (do_tftp_script_run());
|
||||
# endif
|
||||
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* must do this just before select(), when we know no
|
||||
more calls to my_syslog() can occur */
|
||||
set_log_writer(&wset, &maxfd);
|
||||
set_log_writer();
|
||||
|
||||
if (do_poll(timeout) < 0)
|
||||
continue;
|
||||
|
||||
if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
|
||||
{
|
||||
/* otherwise undefined after error */
|
||||
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
|
||||
}
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
check_log_writer(&wset);
|
||||
check_log_writer(0);
|
||||
|
||||
/* prime. */
|
||||
enumerate_interfaces(1);
|
||||
@@ -997,15 +997,15 @@ int main (int argc, char **argv)
|
||||
}
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
if (FD_ISSET(daemon->netlinkfd, &rset))
|
||||
if (poll_check(daemon->netlinkfd, POLLIN))
|
||||
netlink_multicast();
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
if (FD_ISSET(daemon->routefd, &rset))
|
||||
if (poll_check(daemon->routefd, POLLIN))
|
||||
route_sock();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_INOTIFY
|
||||
if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
|
||||
if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
|
||||
{
|
||||
if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
|
||||
poll_resolv(1, 1, now);
|
||||
@@ -1025,7 +1025,7 @@ int main (int argc, char **argv)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (FD_ISSET(piperead, &rset))
|
||||
if (poll_check(piperead, POLLIN))
|
||||
async_event(piperead, now);
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
@@ -1038,34 +1038,34 @@ int main (int argc, char **argv)
|
||||
if (daemon->dbus)
|
||||
my_syslog(LOG_INFO, _("connected to system DBus"));
|
||||
}
|
||||
check_dbus_listeners(&rset, &wset, &eset);
|
||||
check_dbus_listeners();
|
||||
#endif
|
||||
|
||||
check_dns_listeners(&rset, now);
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
check_tftp_listeners(&rset, now);
|
||||
check_tftp_listeners(now);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->relay4)
|
||||
{
|
||||
if (FD_ISSET(daemon->dhcpfd, &rset))
|
||||
if (poll_check(daemon->dhcpfd, POLLIN))
|
||||
dhcp_packet(now, 0);
|
||||
if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
|
||||
if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
|
||||
dhcp_packet(now, 1);
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset))
|
||||
if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
|
||||
dhcp6_packet(now);
|
||||
|
||||
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||
icmp6_packet(now);
|
||||
#endif
|
||||
|
||||
# ifdef HAVE_SCRIPT
|
||||
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
|
||||
if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
|
||||
helper_write();
|
||||
# endif
|
||||
#endif
|
||||
@@ -1231,11 +1231,13 @@ static void async_event(int pipe, time_t now)
|
||||
switch (ev.event)
|
||||
{
|
||||
case EVENT_RELOAD:
|
||||
daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
|
||||
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"));
|
||||
reset_option_bool(OPT_DNSSEC_TIME);
|
||||
daemon->dnssec_no_time_check = 0;
|
||||
}
|
||||
#endif
|
||||
/* fall through */
|
||||
@@ -1300,6 +1302,7 @@ static void async_event(int pipe, time_t now)
|
||||
daemon->tcp_pids[i] = 0;
|
||||
break;
|
||||
|
||||
#if defined(HAVE_SCRIPT)
|
||||
case EVENT_KILLED:
|
||||
my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
|
||||
break;
|
||||
@@ -1313,12 +1316,19 @@ static void async_event(int pipe, time_t now)
|
||||
daemon->lease_change_command, strerror(ev.data));
|
||||
break;
|
||||
|
||||
case EVENT_SCRIPT_LOG:
|
||||
my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
|
||||
free(msg);
|
||||
msg = NULL;
|
||||
break;
|
||||
|
||||
/* necessary for fatal errors in helper */
|
||||
case EVENT_USER_ERR:
|
||||
case EVENT_DIE:
|
||||
case EVENT_LUA_ERR:
|
||||
fatal_event(&ev, msg);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case EVENT_REOPEN:
|
||||
/* Note: this may leave TCP-handling processes with the old file still open.
|
||||
@@ -1344,7 +1354,7 @@ static void async_event(int pipe, time_t now)
|
||||
if (daemon->tcp_pids[i] != 0)
|
||||
kill(daemon->tcp_pids[i], SIGALRM);
|
||||
|
||||
#if defined(HAVE_SCRIPT)
|
||||
#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
|
||||
/* handle pending lease transitions */
|
||||
if (daemon->helperfd != -1)
|
||||
{
|
||||
@@ -1361,6 +1371,15 @@ static void async_event(int pipe, time_t now)
|
||||
if (daemon->lease_stream)
|
||||
fclose(daemon->lease_stream);
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* update timestamp file on TERM if time is considered valid */
|
||||
if (daemon->back_to_the_future)
|
||||
{
|
||||
if (utimes(daemon->timestamp_file, NULL) == -1)
|
||||
my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (daemon->runfile)
|
||||
unlink(daemon->runfile);
|
||||
|
||||
@@ -1470,7 +1489,7 @@ void clear_cache_and_reload(time_t now)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
static int set_dns_listeners(time_t now)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
@@ -1482,8 +1501,7 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
|
||||
{
|
||||
tftp++;
|
||||
FD_SET(transfer->sockfd, set);
|
||||
bump_maxfd(transfer->sockfd, maxfdp);
|
||||
poll_listen(transfer->sockfd, POLLIN);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1492,45 +1510,32 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
get_new_frec(now, &wait, 0);
|
||||
|
||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||
{
|
||||
FD_SET(serverfdp->fd, set);
|
||||
bump_maxfd(serverfdp->fd, maxfdp);
|
||||
}
|
||||
|
||||
poll_listen(serverfdp->fd, POLLIN);
|
||||
|
||||
if (daemon->port != 0 && !daemon->osport)
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount != 0)
|
||||
{
|
||||
FD_SET(daemon->randomsocks[i].fd, set);
|
||||
bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
|
||||
}
|
||||
|
||||
poll_listen(daemon->randomsocks[i].fd, POLLIN);
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
{
|
||||
/* only listen for queries if we have resources */
|
||||
if (listener->fd != -1 && wait == 0)
|
||||
{
|
||||
FD_SET(listener->fd, set);
|
||||
bump_maxfd(listener->fd, maxfdp);
|
||||
}
|
||||
|
||||
poll_listen(listener->fd, POLLIN);
|
||||
|
||||
/* death of a child goes through the select loop, so
|
||||
we don't need to explicitly arrange to wake up here */
|
||||
if (listener->tcpfd != -1)
|
||||
for (i = 0; i < MAX_PROCS; i++)
|
||||
if (daemon->tcp_pids[i] == 0)
|
||||
{
|
||||
FD_SET(listener->tcpfd, set);
|
||||
bump_maxfd(listener->tcpfd, maxfdp);
|
||||
poll_listen(listener->tcpfd, POLLIN);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
|
||||
{
|
||||
FD_SET(listener->tftpfd, set);
|
||||
bump_maxfd(listener->tftpfd, maxfdp);
|
||||
}
|
||||
poll_listen(listener->tftpfd, POLLIN);
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1538,33 +1543,33 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
|
||||
return wait;
|
||||
}
|
||||
|
||||
static void check_dns_listeners(fd_set *set, time_t now)
|
||||
static void check_dns_listeners(time_t now)
|
||||
{
|
||||
struct serverfd *serverfdp;
|
||||
struct listener *listener;
|
||||
int i;
|
||||
|
||||
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
|
||||
if (FD_ISSET(serverfdp->fd, set))
|
||||
if (poll_check(serverfdp->fd, POLLIN))
|
||||
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
|
||||
|
||||
if (daemon->port != 0 && !daemon->osport)
|
||||
for (i = 0; i < RANDOM_SOCKS; i++)
|
||||
if (daemon->randomsocks[i].refcount != 0 &&
|
||||
FD_ISSET(daemon->randomsocks[i].fd, set))
|
||||
poll_check(daemon->randomsocks[i].fd, POLLIN))
|
||||
reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
|
||||
|
||||
for (listener = daemon->listeners; listener; listener = listener->next)
|
||||
{
|
||||
if (listener->fd != -1 && FD_ISSET(listener->fd, set))
|
||||
if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
|
||||
receive_query(listener, now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
|
||||
if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
|
||||
tftp_request(listener, now);
|
||||
#endif
|
||||
|
||||
if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
|
||||
if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
|
||||
{
|
||||
int confd, client_ok = 1;
|
||||
struct irec *iface = NULL;
|
||||
@@ -1685,7 +1690,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
|
||||
}
|
||||
|
||||
#ifndef NO_FORK
|
||||
/* Arrange for SIGALARM after CHILD_LIFETIME seconds to
|
||||
/* Arrange for SIGALRM after CHILD_LIFETIME seconds to
|
||||
terminate the process. */
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
alarm(CHILD_LIFETIME);
|
||||
@@ -1750,29 +1755,15 @@ int icmp_ping(struct in_addr addr)
|
||||
{
|
||||
/* Try and get an ICMP echo from a machine. */
|
||||
|
||||
/* Note that whilst in the three second wait, we check for
|
||||
(and service) events on the DNS and TFTP sockets, (so doing that
|
||||
better not use any resources our caller has in use...)
|
||||
but we remain deaf to signals or further DHCP packets. */
|
||||
|
||||
/* There can be a problem using dnsmasq_time() to end the loop, since
|
||||
it's not monotonic, and can go backwards if the system clock is
|
||||
tweaked, leading to the code getting stuck in this loop and
|
||||
ignoring DHCP requests. To fix this, we check to see if select returned
|
||||
as a result of a timeout rather than a socket becoming available. We
|
||||
only allow this to happen as many times as it takes to get to the wait time
|
||||
in quarter-second chunks. This provides a fallback way to end loop. */
|
||||
|
||||
int fd, rc;
|
||||
int fd;
|
||||
struct sockaddr_in saddr;
|
||||
struct {
|
||||
struct ip ip;
|
||||
struct icmp icmp;
|
||||
} packet;
|
||||
unsigned short id = rand16();
|
||||
unsigned int i, j, timeout_count;
|
||||
unsigned int i, j;
|
||||
int gotreply = 0;
|
||||
time_t start, now;
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
|
||||
if ((fd = make_icmp_sock()) == -1)
|
||||
@@ -1802,69 +1793,8 @@ int icmp_ping(struct in_addr addr)
|
||||
while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
|
||||
(struct sockaddr *)&saddr, sizeof(saddr))));
|
||||
|
||||
for (now = start = dnsmasq_time(), timeout_count = 0;
|
||||
(difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set rset, wset;
|
||||
struct sockaddr_in faddr;
|
||||
int maxfd = fd;
|
||||
socklen_t len = sizeof(faddr);
|
||||
|
||||
tv.tv_usec = 250000;
|
||||
tv.tv_sec = 0;
|
||||
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
FD_SET(fd, &rset);
|
||||
set_dns_listeners(now, &rset, &maxfd);
|
||||
set_log_writer(&wset, &maxfd);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra)
|
||||
{
|
||||
FD_SET(daemon->icmp6fd, &rset);
|
||||
bump_maxfd(daemon->icmp6fd, &maxfd);
|
||||
}
|
||||
#endif
|
||||
|
||||
rc = select(maxfd+1, &rset, &wset, NULL, &tv);
|
||||
|
||||
if (rc < 0)
|
||||
{
|
||||
FD_ZERO(&rset);
|
||||
FD_ZERO(&wset);
|
||||
}
|
||||
else if (rc == 0)
|
||||
timeout_count++;
|
||||
gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
check_log_writer(&wset);
|
||||
check_dns_listeners(&rset, now);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
|
||||
icmp6_packet(now);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
check_tftp_listeners(&rset, now);
|
||||
#endif
|
||||
|
||||
if (FD_ISSET(fd, &rset) &&
|
||||
recvfrom(fd, &packet, sizeof(packet), 0,
|
||||
(struct sockaddr *)&faddr, &len) == sizeof(packet) &&
|
||||
saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
|
||||
packet.icmp.icmp_type == ICMP_ECHOREPLY &&
|
||||
packet.icmp.icmp_seq == 0 &&
|
||||
packet.icmp.icmp_id == id)
|
||||
{
|
||||
gotreply = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
|
||||
while (retry_send(close(fd)));
|
||||
#else
|
||||
@@ -1874,6 +1804,85 @@ int icmp_ping(struct in_addr addr)
|
||||
|
||||
return gotreply;
|
||||
}
|
||||
|
||||
int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
|
||||
{
|
||||
/* Delay processing DHCP packets for "sec" seconds counting from "start".
|
||||
If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
|
||||
from "addr" with ICMP ID "id" and return 1 */
|
||||
|
||||
/* Note that whilst waiting, we check for
|
||||
(and service) events on the DNS and TFTP sockets, (so doing that
|
||||
better not use any resources our caller has in use...)
|
||||
but we remain deaf to signals or further DHCP packets. */
|
||||
|
||||
/* There can be a problem using dnsmasq_time() to end the loop, since
|
||||
it's not monotonic, and can go backwards if the system clock is
|
||||
tweaked, leading to the code getting stuck in this loop and
|
||||
ignoring DHCP requests. To fix this, we check to see if select returned
|
||||
as a result of a timeout rather than a socket becoming available. We
|
||||
only allow this to happen as many times as it takes to get to the wait time
|
||||
in quarter-second chunks. This provides a fallback way to end loop. */
|
||||
|
||||
int rc, timeout_count;
|
||||
time_t now;
|
||||
|
||||
for (now = dnsmasq_time(), timeout_count = 0;
|
||||
(difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
|
||||
{
|
||||
poll_reset();
|
||||
if (fd != -1)
|
||||
poll_listen(fd, POLLIN);
|
||||
set_dns_listeners(now);
|
||||
set_log_writer();
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra)
|
||||
poll_listen(daemon->icmp6fd, POLLIN);
|
||||
#endif
|
||||
|
||||
rc = do_poll(250);
|
||||
|
||||
if (rc < 0)
|
||||
continue;
|
||||
else if (rc == 0)
|
||||
timeout_count++;
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
check_log_writer(0);
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
|
||||
icmp6_packet(now);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
check_tftp_listeners(now);
|
||||
#endif
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
struct {
|
||||
struct ip ip;
|
||||
struct icmp icmp;
|
||||
} packet;
|
||||
struct sockaddr_in faddr;
|
||||
socklen_t len = sizeof(faddr);
|
||||
|
||||
if (poll_check(fd, POLLIN) &&
|
||||
recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
|
||||
addr == faddr.sin_addr.s_addr &&
|
||||
packet.icmp.icmp_type == ICMP_ECHOREPLY &&
|
||||
packet.icmp.icmp_seq == 0 &&
|
||||
packet.icmp.icmp_id == id)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
279
src/dnsmasq.h
279
src/dnsmasq.h
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,7 +14,13 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define COPYRIGHT "Copyright (c) 2000-2015 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (c) 2000-2017 Simon Kelley"
|
||||
|
||||
/* We do defines that influence behavior of stdio.h, so complain
|
||||
if included too early. */
|
||||
#ifdef _STDIO_H
|
||||
# error "Header file stdio.h included too early!"
|
||||
#endif
|
||||
|
||||
#ifndef NO_LARGEFILE
|
||||
/* Ensure we can use files >2GB (log files may grow this big) */
|
||||
@@ -82,7 +88,7 @@ typedef unsigned long long u64;
|
||||
#if defined(HAVE_SOLARIS_NETWORK)
|
||||
# include <sys/sockio.h>
|
||||
#endif
|
||||
#include <sys/select.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/un.h>
|
||||
@@ -124,7 +130,7 @@ typedef unsigned long long u64;
|
||||
#if defined(HAVE_LINUX_NETWORK)
|
||||
#include <linux/capability.h>
|
||||
/* There doesn't seem to be a universally-available
|
||||
userpace header for these. */
|
||||
userspace header for these. */
|
||||
extern int capset(cap_user_header_t header, cap_user_data_t data);
|
||||
extern int capget(cap_user_header_t header, cap_user_data_t data);
|
||||
#define LINUX_CAPABILITY_VERSION_1 0x19980330
|
||||
@@ -144,30 +150,31 @@ struct event_desc {
|
||||
int event, data, msg_sz;
|
||||
};
|
||||
|
||||
#define EVENT_RELOAD 1
|
||||
#define EVENT_DUMP 2
|
||||
#define EVENT_ALARM 3
|
||||
#define EVENT_TERM 4
|
||||
#define EVENT_CHILD 5
|
||||
#define EVENT_REOPEN 6
|
||||
#define EVENT_EXITED 7
|
||||
#define EVENT_KILLED 8
|
||||
#define EVENT_EXEC_ERR 9
|
||||
#define EVENT_PIPE_ERR 10
|
||||
#define EVENT_USER_ERR 11
|
||||
#define EVENT_CAP_ERR 12
|
||||
#define EVENT_PIDFILE 13
|
||||
#define EVENT_HUSER_ERR 14
|
||||
#define EVENT_GROUP_ERR 15
|
||||
#define EVENT_DIE 16
|
||||
#define EVENT_LOG_ERR 17
|
||||
#define EVENT_FORK_ERR 18
|
||||
#define EVENT_LUA_ERR 19
|
||||
#define EVENT_TFTP_ERR 20
|
||||
#define EVENT_INIT 21
|
||||
#define EVENT_NEWADDR 22
|
||||
#define EVENT_NEWROUTE 23
|
||||
#define EVENT_TIME_ERR 24
|
||||
#define EVENT_RELOAD 1
|
||||
#define EVENT_DUMP 2
|
||||
#define EVENT_ALARM 3
|
||||
#define EVENT_TERM 4
|
||||
#define EVENT_CHILD 5
|
||||
#define EVENT_REOPEN 6
|
||||
#define EVENT_EXITED 7
|
||||
#define EVENT_KILLED 8
|
||||
#define EVENT_EXEC_ERR 9
|
||||
#define EVENT_PIPE_ERR 10
|
||||
#define EVENT_USER_ERR 11
|
||||
#define EVENT_CAP_ERR 12
|
||||
#define EVENT_PIDFILE 13
|
||||
#define EVENT_HUSER_ERR 14
|
||||
#define EVENT_GROUP_ERR 15
|
||||
#define EVENT_DIE 16
|
||||
#define EVENT_LOG_ERR 17
|
||||
#define EVENT_FORK_ERR 18
|
||||
#define EVENT_LUA_ERR 19
|
||||
#define EVENT_TFTP_ERR 20
|
||||
#define EVENT_INIT 21
|
||||
#define EVENT_NEWADDR 22
|
||||
#define EVENT_NEWROUTE 23
|
||||
#define EVENT_TIME_ERR 24
|
||||
#define EVENT_SCRIPT_LOG 25
|
||||
|
||||
/* Exit codes. */
|
||||
#define EC_GOOD 0
|
||||
@@ -178,13 +185,6 @@ struct event_desc {
|
||||
#define EC_MISC 5
|
||||
#define EC_INIT_OFFSET 10
|
||||
|
||||
/* Min buffer size: we check after adding each record, so there must be
|
||||
memory for the largest packet, and the largest record so the
|
||||
min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
|
||||
This might be increased is EDNS packet size if greater than the minimum.
|
||||
*/
|
||||
#define DNSMASQ_PACKETSZ PACKETSZ+MAXDNAME+RRFIXEDSZ
|
||||
|
||||
/* Trust the compiler dead-code eliminator.... */
|
||||
#define option_bool(x) (((x) < 32) ? daemon->options & (1u << (x)) : daemon->options2 & (1u << ((x) - 32)))
|
||||
|
||||
@@ -217,7 +217,7 @@ struct event_desc {
|
||||
#define OPT_TFTP_SECURE 26
|
||||
#define OPT_TFTP_NOBLOCK 27
|
||||
#define OPT_LOG_OPTS 28
|
||||
#define OPT_TFTP_APREF 29
|
||||
#define OPT_TFTP_APREF_IP 29
|
||||
#define OPT_NO_OVERRIDE 30
|
||||
#define OPT_NO_REBIND 31
|
||||
#define OPT_ADD_MAC 32
|
||||
@@ -241,12 +241,17 @@ struct event_desc {
|
||||
#define OPT_LOOP_DETECT 50
|
||||
#define OPT_EXTRALOG 51
|
||||
#define OPT_TFTP_NO_FAIL 52
|
||||
#define OPT_LAST 53
|
||||
#define OPT_SCRIPT_ARP 53
|
||||
#define OPT_MAC_B64 54
|
||||
#define OPT_MAC_HEX 55
|
||||
#define OPT_TFTP_APREF_MAC 56
|
||||
#define OPT_LAST 57
|
||||
|
||||
/* 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. */
|
||||
#define MS_TFTP LOG_USER
|
||||
#define MS_DHCP LOG_DAEMON
|
||||
#define MS_TFTP LOG_USER
|
||||
#define MS_DHCP LOG_DAEMON
|
||||
#define MS_SCRIPT LOG_MAIL
|
||||
|
||||
struct all_addr {
|
||||
union {
|
||||
@@ -255,8 +260,10 @@ struct all_addr {
|
||||
struct in6_addr addr6;
|
||||
#endif
|
||||
/* for log_query */
|
||||
unsigned int keytag;
|
||||
/* for cache_insert if RRSIG, DNSKEY, DS */
|
||||
struct {
|
||||
unsigned short keytag, algo, digest;
|
||||
} log;
|
||||
/* for cache_insert of DNSKEY, DS */
|
||||
struct {
|
||||
unsigned short class, type;
|
||||
} dnssec;
|
||||
@@ -287,6 +294,7 @@ struct naptr {
|
||||
struct naptr *next;
|
||||
};
|
||||
|
||||
#ifndef NO_ID
|
||||
#define TXT_STAT_CACHESIZE 1
|
||||
#define TXT_STAT_INSERTS 2
|
||||
#define TXT_STAT_EVICTIONS 3
|
||||
@@ -294,6 +302,7 @@ struct naptr {
|
||||
#define TXT_STAT_HITS 5
|
||||
#define TXT_STAT_AUTH 6
|
||||
#define TXT_STAT_SERVERS 7
|
||||
#endif
|
||||
|
||||
struct txt_record {
|
||||
char *name;
|
||||
@@ -309,8 +318,9 @@ struct ptr_record {
|
||||
};
|
||||
|
||||
struct cname {
|
||||
int ttl, flag;
|
||||
char *alias, *target;
|
||||
struct cname *next;
|
||||
struct cname *next, *targetp;
|
||||
};
|
||||
|
||||
struct ds_config {
|
||||
@@ -340,11 +350,13 @@ struct auth_zone {
|
||||
struct auth_name_list *next;
|
||||
} *interface_names;
|
||||
struct addrlist *subnet;
|
||||
struct addrlist *exclude;
|
||||
struct auth_zone *next;
|
||||
};
|
||||
|
||||
|
||||
struct host_record {
|
||||
int ttl;
|
||||
struct name_list {
|
||||
char *name;
|
||||
struct name_list *next;
|
||||
@@ -397,14 +409,9 @@ struct crec {
|
||||
unsigned char algo;
|
||||
unsigned char digest;
|
||||
} ds;
|
||||
struct {
|
||||
struct blockdata *keydata;
|
||||
unsigned short keylen, type_covered, keytag;
|
||||
char algo;
|
||||
} sig;
|
||||
} addr;
|
||||
time_t ttd; /* time to die */
|
||||
/* used as class if DNSKEY/DS/RRSIG, index to source for F_HOSTS */
|
||||
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
|
||||
unsigned int uid;
|
||||
unsigned short flags;
|
||||
union {
|
||||
@@ -444,8 +451,7 @@ struct crec {
|
||||
#define F_SECSTAT (1u<<24)
|
||||
#define F_NO_RR (1u<<25)
|
||||
#define F_IPSET (1u<<26)
|
||||
#define F_NSIGMATCH (1u<<27)
|
||||
#define F_NOEXTRA (1u<<28)
|
||||
#define F_NOEXTRA (1u<<27)
|
||||
|
||||
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||
#define SRC_INTERFACE 0
|
||||
@@ -486,11 +492,14 @@ union mysockaddr {
|
||||
#define SERV_NO_REBIND 2048 /* inhibit dns-rebind protection */
|
||||
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
||||
#define SERV_DO_DNSSEC 16384 /* Validate DNSSEC when using this server */
|
||||
#define SERV_GOT_TCP 32768 /* Got some data from the TCP connection */
|
||||
|
||||
struct serverfd {
|
||||
int fd;
|
||||
union mysockaddr source_addr;
|
||||
char interface[IF_NAMESIZE+1];
|
||||
unsigned int ifindex, used;
|
||||
struct serverfd *next;
|
||||
};
|
||||
|
||||
@@ -521,7 +530,7 @@ struct ipsets {
|
||||
struct irec {
|
||||
union mysockaddr addr;
|
||||
struct in_addr netmask; /* only valid for IPv4 */
|
||||
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found;
|
||||
int tftp_ok, dhcp_ok, mtu, done, warned, dad, dns_auth, index, multicast_done, found, label;
|
||||
char *name;
|
||||
struct irec *next;
|
||||
};
|
||||
@@ -540,6 +549,13 @@ struct iname {
|
||||
struct iname *next;
|
||||
};
|
||||
|
||||
/* subnet parameters from command line */
|
||||
struct mysubnet {
|
||||
union mysockaddr addr;
|
||||
int addr_used;
|
||||
int mask;
|
||||
};
|
||||
|
||||
/* resolv-file parms from command-line */
|
||||
struct resolvc {
|
||||
struct resolvc *next;
|
||||
@@ -578,12 +594,8 @@ struct hostsfile {
|
||||
#define STAT_NEED_KEY 5
|
||||
#define STAT_TRUNCATED 6
|
||||
#define STAT_SECURE_WILDCARD 7
|
||||
#define STAT_NO_SIG 8
|
||||
#define STAT_NO_DS 9
|
||||
#define STAT_NO_NS 10
|
||||
#define STAT_NEED_DS_NEG 11
|
||||
#define STAT_CHASE_CNAME 12
|
||||
#define STAT_INSECURE_DS 13
|
||||
#define STAT_OK 8
|
||||
#define STAT_ABANDONED 9
|
||||
|
||||
#define FREC_NOREBIND 1
|
||||
#define FREC_CHECKING_DISABLED 2
|
||||
@@ -593,8 +605,8 @@ struct hostsfile {
|
||||
#define FREC_AD_QUESTION 32
|
||||
#define FREC_DO_QUESTION 64
|
||||
#define FREC_ADDED_PHEADER 128
|
||||
#define FREC_CHECK_NOSIGN 256
|
||||
#define FREC_TEST_PKTSZ 512
|
||||
#define FREC_TEST_PKTSZ 256
|
||||
#define FREC_HAS_EXTRADATA 512
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
#define HASH_SIZE 20 /* SHA-1 digest size */
|
||||
@@ -618,9 +630,7 @@ struct frec {
|
||||
#ifdef HAVE_DNSSEC
|
||||
int class, work_counter;
|
||||
struct blockdata *stash; /* Saved reply, whilst we validate */
|
||||
struct blockdata *orig_domain; /* domain of original query, whilst
|
||||
we're seeing is if in unsigned domain */
|
||||
size_t stash_len, name_start, name_len;
|
||||
size_t stash_len;
|
||||
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
|
||||
struct frec *blocking_query; /* Query which is blocking us. */
|
||||
#endif
|
||||
@@ -642,6 +652,8 @@ struct frec {
|
||||
#define ACTION_OLD 3
|
||||
#define ACTION_ADD 4
|
||||
#define ACTION_TFTP 5
|
||||
#define ACTION_ARP 6
|
||||
#define ACTION_ARP_DEL 7
|
||||
|
||||
#define LEASE_NEW 1 /* newly created */
|
||||
#define LEASE_CHANGED 2 /* modified */
|
||||
@@ -700,6 +712,12 @@ struct tag_if {
|
||||
struct tag_if *next;
|
||||
};
|
||||
|
||||
struct delay_config {
|
||||
int delay;
|
||||
struct dhcp_netid *netid;
|
||||
struct delay_config *next;
|
||||
};
|
||||
|
||||
struct hwaddr_config {
|
||||
int hwaddr_len, hwaddr_type;
|
||||
unsigned char hwaddr[DHCP_CHADDR_MAX];
|
||||
@@ -786,7 +804,7 @@ struct pxe_service {
|
||||
#define MATCH_REMOTE 4
|
||||
#define MATCH_SUBSCRIBER 5
|
||||
|
||||
/* vendorclass, userclass, remote-id or cicuit-id */
|
||||
/* vendorclass, userclass, remote-id or circuit-id */
|
||||
struct dhcp_vendor {
|
||||
int len, match_type;
|
||||
unsigned int enterprise;
|
||||
@@ -828,7 +846,8 @@ struct prefix_class {
|
||||
|
||||
struct ra_interface {
|
||||
char *name;
|
||||
int interval, lifetime, prio;
|
||||
char *mtu_name;
|
||||
int interval, lifetime, prio, mtu;
|
||||
struct ra_interface *next;
|
||||
};
|
||||
|
||||
@@ -934,9 +953,9 @@ extern struct daemon {
|
||||
struct auth_zone *auth_zones;
|
||||
struct interface_name *int_names;
|
||||
char *mxtarget;
|
||||
int addr4_netmask;
|
||||
int addr6_netmask;
|
||||
char *lease_file;
|
||||
struct mysubnet *add_subnet4;
|
||||
struct mysubnet *add_subnet6;
|
||||
char *lease_file;
|
||||
char *username, *groupname, *scriptuser;
|
||||
char *luascript;
|
||||
char *authserver, *hostmaster;
|
||||
@@ -955,8 +974,9 @@ extern struct daemon {
|
||||
char *log_file; /* optional log file */
|
||||
int max_logs; /* queue limit */
|
||||
int cachesize, ftabsize;
|
||||
int port, query_port, min_port;
|
||||
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl;
|
||||
int port, query_port, min_port, max_port;
|
||||
unsigned long local_ttl, neg_ttl, max_ttl, min_cache_ttl, max_cache_ttl, auth_ttl, dhcp_ttl, use_dhcp_ttl;
|
||||
char *dns_client_id;
|
||||
struct hostsfile *addn_hosts;
|
||||
struct dhcp_context *dhcp, *dhcp6;
|
||||
struct ra_interface *ra_interfaces;
|
||||
@@ -969,13 +989,14 @@ extern struct daemon {
|
||||
struct tag_if *tag_if;
|
||||
struct addr_list *override_relays;
|
||||
struct dhcp_relay *relay4, *relay6;
|
||||
struct delay_config *delay_conf;
|
||||
int override;
|
||||
int enable_pxe;
|
||||
int doing_ra, doing_dhcp6;
|
||||
struct dhcp_netid_list *dhcp_ignore, *dhcp_ignore_names, *dhcp_gen_names;
|
||||
struct dhcp_netid_list *force_broadcast, *bootp_dynamic;
|
||||
struct hostsfile *dhcp_hosts_file, *dhcp_opts_file, *dynamic_dirs;
|
||||
int dhcp_max, tftp_max;
|
||||
int dhcp_max, tftp_max, tftp_mtu;
|
||||
int dhcp_server_port, dhcp_client_port;
|
||||
int start_tftp_port, end_tftp_port;
|
||||
unsigned int min_leasetime;
|
||||
@@ -992,6 +1013,8 @@ extern struct daemon {
|
||||
#endif
|
||||
#ifdef HAVE_DNSSEC
|
||||
struct ds_config *ds;
|
||||
int dnssec_no_time_check;
|
||||
int back_to_the_future;
|
||||
char *timestamp_file;
|
||||
#endif
|
||||
|
||||
@@ -1077,7 +1100,9 @@ void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_addre
|
||||
struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||
void cache_unhash_dhcp(void);
|
||||
void dump_cache(time_t now);
|
||||
#ifndef NO_ID
|
||||
int cache_make_stat(struct txt_record *t);
|
||||
#endif
|
||||
char *cache_get_name(struct crec *crecp);
|
||||
char *cache_get_cname_target(struct crec *crecp);
|
||||
struct crec *cache_enumerate(int init);
|
||||
@@ -1111,28 +1136,20 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
||||
char *name, unsigned short *typep);
|
||||
size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||
struct all_addr *addrp, unsigned int flags,
|
||||
unsigned long local_ttl);
|
||||
int extract_addresses(struct dns_header *header, size_t qlen, char *namebuff,
|
||||
time_t now, char **ipsets, int is_sign, int checkrebind,
|
||||
int no_cache, int secure, int *doctored);
|
||||
unsigned long ttl);
|
||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||
time_t now, char **ipsets, int is_sign, int check_rebind,
|
||||
int no_cache_dnssec, int secure, int *doctored);
|
||||
size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
struct in_addr local_addr, struct in_addr local_netmask,
|
||||
time_t now, int *ad_reqd, int *do_bit);
|
||||
time_t now, int ad_reqd, int do_bit, int have_pseudoheader);
|
||||
int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
|
||||
struct bogus_addr *addr, time_t now);
|
||||
struct bogus_addr *baddr, time_t now);
|
||||
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
|
||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
||||
size_t *len, unsigned char **p, int *is_sign);
|
||||
int check_for_local_domain(char *name, time_t now);
|
||||
unsigned int questions_crc(struct dns_header *header, size_t plen, char *buff);
|
||||
unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
|
||||
size_t resize_packet(struct dns_header *header, size_t plen,
|
||||
unsigned char *pheader, size_t hlen);
|
||||
size_t add_mac(struct dns_header *header, size_t plen, char *limit, union mysockaddr *l3);
|
||||
size_t add_source_addr(struct dns_header *header, size_t plen, char *limit, union mysockaddr *source);
|
||||
#ifdef HAVE_DNSSEC
|
||||
size_t add_do_bit(struct dns_header *header, size_t plen, char *limit);
|
||||
#endif
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
|
||||
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
|
||||
int nameoffset, unsigned char **pp, unsigned long ttl,
|
||||
int *offset, unsigned short type, unsigned short class, char *format, ...);
|
||||
@@ -1145,17 +1162,18 @@ int private_net(struct in_addr addr, int ban_localhost);
|
||||
/* auth.c */
|
||||
#ifdef HAVE_AUTH
|
||||
size_t answer_auth(struct dns_header *header, char *limit, size_t qlen,
|
||||
time_t now, union mysockaddr *peer_addr, int local_query);
|
||||
time_t now, union mysockaddr *peer_addr, int local_query,
|
||||
int do_bit, int have_pseudoheader);
|
||||
int in_zone(struct auth_zone *zone, char *name, char **cut);
|
||||
#endif
|
||||
|
||||
/* dnssec.c */
|
||||
size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, char *name, char *keyname, int class);
|
||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t 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 *neganswer, int *nons);
|
||||
int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname);
|
||||
int dnskey_keytag(int alg, int flags, unsigned char *rdata, int rdlen);
|
||||
int 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 dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
|
||||
size_t filter_rrsigs(struct dns_header *header, size_t plen);
|
||||
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
|
||||
int setup_timestamp(void);
|
||||
@@ -1165,9 +1183,9 @@ void rand_init(void);
|
||||
unsigned short rand16(void);
|
||||
u32 rand32(void);
|
||||
u64 rand64(void);
|
||||
int legal_hostname(char *c);
|
||||
char *canonicalise(char *s, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval);
|
||||
int legal_hostname(char *name);
|
||||
char *canonicalise(char *in, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||
void *safe_malloc(size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
@@ -1191,7 +1209,6 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
|
||||
unsigned int mask);
|
||||
int expand_buf(struct iovec *iov, size_t size);
|
||||
char *print_mac(char *buff, unsigned char *mac, int len);
|
||||
void bump_maxfd(int fd, int *max);
|
||||
int read_write(int fd, unsigned char *packet, int size, int rw);
|
||||
|
||||
int wildcard_match(const char* wildcard, const char* match);
|
||||
@@ -1201,9 +1218,11 @@ int wildcard_matchn(const char* wildcard, const char* match, int num);
|
||||
void die(char *message, char *arg1, int exit_code);
|
||||
int log_start(struct passwd *ent_pw, int errfd);
|
||||
int log_reopen(char *log_file);
|
||||
|
||||
void my_syslog(int priority, const char *format, ...);
|
||||
void set_log_writer(fd_set *set, int *maxfdp);
|
||||
void check_log_writer(fd_set *set);
|
||||
|
||||
void set_log_writer(void);
|
||||
void check_log_writer(int force);
|
||||
void flush_log(void);
|
||||
|
||||
/* option.c */
|
||||
@@ -1229,7 +1248,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force);
|
||||
int send_from(int fd, int nowild, char *packet, size_t len,
|
||||
union mysockaddr *to, struct all_addr *source,
|
||||
unsigned int iface);
|
||||
void resend_query();
|
||||
void resend_query(void);
|
||||
struct randfd *allocate_rfd(int family);
|
||||
void free_rfd(struct randfd *rfd);
|
||||
|
||||
@@ -1249,11 +1268,12 @@ void add_update_server(int flags,
|
||||
void check_servers(void);
|
||||
int enumerate_interfaces(int reset);
|
||||
void create_wildcard_listeners(void);
|
||||
void create_bound_listeners(int die);
|
||||
void create_bound_listeners(int dienow);
|
||||
void warn_bound_listeners(void);
|
||||
void warn_wild_labels(void);
|
||||
void warn_int_names(void);
|
||||
int is_dad_listeners(void);
|
||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth_dns);
|
||||
int iface_check(int family, struct all_addr *addr, char *name, int *auth);
|
||||
int loopback_exception(int fd, int family, struct all_addr *addr, char *name);
|
||||
int label_exception(int index, int family, struct all_addr *addr);
|
||||
int fix_fd(int fd);
|
||||
@@ -1274,14 +1294,16 @@ void newaddress(time_t now);
|
||||
void dhcp_init(void);
|
||||
void dhcp_packet(time_t now, int pxe_fd);
|
||||
struct dhcp_context *address_available(struct dhcp_context *context,
|
||||
struct in_addr addr,
|
||||
struct in_addr taddr,
|
||||
struct dhcp_netid *netids);
|
||||
struct dhcp_context *narrow_context(struct dhcp_context *context,
|
||||
struct in_addr taddr,
|
||||
struct dhcp_netid *netids);
|
||||
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr,
|
||||
unsigned int hash, int loopback);
|
||||
int address_allocate(struct dhcp_context *context,
|
||||
struct in_addr *addrp, unsigned char *hwaddr, int hw_len,
|
||||
struct dhcp_netid *netids, time_t now);
|
||||
struct dhcp_netid *netids, time_t now, int loopback);
|
||||
void dhcp_read_ethers(void);
|
||||
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr);
|
||||
char *host_from_dns(struct in_addr addr);
|
||||
@@ -1330,7 +1352,8 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data,
|
||||
/* rfc2131.c */
|
||||
#ifdef HAVE_DHCP
|
||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe_fd, struct in_addr fallback);
|
||||
size_t sz, time_t now, int unicast_dest, int loopback,
|
||||
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime);
|
||||
unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
int clid_len, unsigned char *clid, int *len_out);
|
||||
#endif
|
||||
@@ -1339,6 +1362,7 @@ unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
|
||||
#ifdef HAVE_DHCP
|
||||
int make_icmp_sock(void);
|
||||
int icmp_ping(struct in_addr addr);
|
||||
int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id);
|
||||
#endif
|
||||
void queue_event(int event);
|
||||
void send_alarm(time_t event, time_t now);
|
||||
@@ -1366,8 +1390,8 @@ int iface_enumerate(int family, void *parm, int (callback)());
|
||||
/* dbus.c */
|
||||
#ifdef HAVE_DBUS
|
||||
char *dbus_init(void);
|
||||
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset);
|
||||
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset);
|
||||
void check_dbus_listeners(void);
|
||||
void set_dbus_listeners(void);
|
||||
# ifdef HAVE_DHCP
|
||||
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
||||
# endif
|
||||
@@ -1388,13 +1412,15 @@ void queue_script(int action, struct dhcp_lease *lease,
|
||||
#ifdef HAVE_TFTP
|
||||
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
||||
#endif
|
||||
void queue_arp(int action, unsigned char *mac, int maclen,
|
||||
int family, struct all_addr *addr);
|
||||
int helper_buf_empty(void);
|
||||
#endif
|
||||
|
||||
/* tftp.c */
|
||||
#ifdef HAVE_TFTP
|
||||
void tftp_request(struct listener *listen, time_t now);
|
||||
void check_tftp_listeners(fd_set *rset, time_t now);
|
||||
void check_tftp_listeners(time_t now);
|
||||
int do_tftp_script_run(void);
|
||||
#endif
|
||||
|
||||
@@ -1424,7 +1450,7 @@ struct dhcp_config *config_find_by_address6(struct dhcp_config *configs, struct
|
||||
void make_duid(time_t now);
|
||||
void dhcp_construct_contexts(time_t now);
|
||||
void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||
unsigned int *maclenp, unsigned int *mactypep);
|
||||
unsigned int *maclenp, unsigned int *mactypep, time_t now);
|
||||
#endif
|
||||
|
||||
/* rfc3315.c */
|
||||
@@ -1432,7 +1458,8 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
|
||||
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
|
||||
size_t sz, struct in6_addr *client_addr, time_t now);
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id);
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
|
||||
u32 scope_id, time_t now);
|
||||
|
||||
unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
|
||||
#endif
|
||||
@@ -1441,10 +1468,10 @@ unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arriva
|
||||
#ifdef HAVE_DHCP
|
||||
void dhcp_common_init(void);
|
||||
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg);
|
||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *input);
|
||||
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags);
|
||||
struct dhcp_netid *option_filter(struct dhcp_netid *tags, struct dhcp_netid *context_tags,
|
||||
struct dhcp_opt *opts);
|
||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int negonly);
|
||||
int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded);
|
||||
char *strip_hostname(char *hostname);
|
||||
void log_tags(struct dhcp_netid *netid, u32 xid);
|
||||
int match_bytes(struct dhcp_opt *o, unsigned char *p, int len);
|
||||
@@ -1474,6 +1501,7 @@ void log_relay(int family, struct dhcp_relay *relay);
|
||||
/* outpacket.c */
|
||||
#ifdef HAVE_DHCP6
|
||||
void end_opt6(int container);
|
||||
void reset_counter(void);
|
||||
int save_counter(int newval);
|
||||
void *expand(size_t headroom);
|
||||
int new_opt6(int opt);
|
||||
@@ -1489,7 +1517,7 @@ void put_opt6_string(char *s);
|
||||
void ra_init(time_t now);
|
||||
void icmp6_packet(time_t now);
|
||||
time_t periodic_ra(time_t now);
|
||||
void ra_start_unsolicted(time_t now, struct dhcp_context *context);
|
||||
void ra_start_unsolicited(time_t now, struct dhcp_context *context);
|
||||
#endif
|
||||
|
||||
/* slaac.c */
|
||||
@@ -1501,13 +1529,38 @@ void slaac_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
||||
|
||||
/* loop.c */
|
||||
#ifdef HAVE_LOOP
|
||||
void loop_send_probes();
|
||||
void loop_send_probes(void);
|
||||
int detect_loop(char *query, int type);
|
||||
#endif
|
||||
|
||||
/* inotify.c */
|
||||
#ifdef HAVE_INOTIFY
|
||||
void inotify_dnsmasq_init();
|
||||
void inotify_dnsmasq_init(void);
|
||||
int inotify_check(time_t now);
|
||||
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
|
||||
#endif
|
||||
|
||||
/* poll.c */
|
||||
void poll_reset(void);
|
||||
int poll_check(int fd, short event);
|
||||
void poll_listen(int fd, short event);
|
||||
int do_poll(int timeout);
|
||||
|
||||
/* rrfilter.c */
|
||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
|
||||
u16 *rrfilter_desc(int type);
|
||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
||||
|
||||
/* edns0.c */
|
||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
||||
size_t *len, unsigned char **p, int *is_sign, int *is_last);
|
||||
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
|
||||
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
|
||||
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, time_t now, int *check_subnet);
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
|
||||
|
||||
/* arp.c */
|
||||
int find_mac(union mysockaddr *addr, unsigned char *mac, int lazy, time_t now);
|
||||
int do_arp_script_run(void);
|
||||
|
||||
1538
src/dnssec.c
1538
src/dnssec.c
File diff suppressed because it is too large
Load Diff
38
src/domain.c
38
src/domain.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -77,18 +77,31 @@ int is_name_synthetic(int flags, char *name, struct all_addr *addr)
|
||||
|
||||
*p = 0;
|
||||
|
||||
/* swap . or : for - */
|
||||
for (p = tail; *p; p++)
|
||||
if (*p == '-')
|
||||
{
|
||||
if (prot == AF_INET)
|
||||
#ifdef HAVE_IPV6
|
||||
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
|
||||
*p = ':';
|
||||
}
|
||||
else
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
/* swap . or : for - */
|
||||
for (p = tail; *p; p++)
|
||||
if (*p == '-')
|
||||
{
|
||||
if (prot == AF_INET)
|
||||
*p = '.';
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
*p = ':';
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (hostname_isequal(c->domain, p+1) && inet_pton(prot, tail, addr))
|
||||
{
|
||||
if (prot == AF_INET)
|
||||
@@ -169,8 +182,9 @@ int is_rev_synth(int flag, struct all_addr *addr, char *name)
|
||||
inet_ntop(AF_INET6, &addr->addr.addr6, name+1, ADDRSTRLEN);
|
||||
}
|
||||
|
||||
/* V4-mapped have periods.... */
|
||||
for (p = name; *p; p++)
|
||||
if (*p == ':')
|
||||
if (*p == ':' || *p == '.')
|
||||
*p = '-';
|
||||
|
||||
strncat(name, ".", MAXDNAME);
|
||||
|
||||
449
src/edns0.c
Normal file
449
src/edns0.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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"
|
||||
|
||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen, size_t *len, unsigned char **p, int *is_sign, int *is_last)
|
||||
{
|
||||
/* See if packet has an RFC2671 pseudoheader, and if so return a pointer to it.
|
||||
also return length of pseudoheader in *len and pointer to the UDP size in *p
|
||||
Finally, check to see if a packet is signed. If it is we cannot change a single bit before
|
||||
forwarding. We look for TSIG in the addition section, and TKEY queries (for GSS-TSIG) */
|
||||
|
||||
int i, arcount = ntohs(header->arcount);
|
||||
unsigned char *ansp = (unsigned char *)(header+1);
|
||||
unsigned short rdlen, type, class;
|
||||
unsigned char *ret = NULL;
|
||||
|
||||
if (is_sign)
|
||||
{
|
||||
*is_sign = 0;
|
||||
|
||||
if (OPCODE(header) == QUERY)
|
||||
{
|
||||
for (i = ntohs(header->qdcount); i != 0; i--)
|
||||
{
|
||||
if (!(ansp = skip_name(ansp, header, plen, 4)))
|
||||
return NULL;
|
||||
|
||||
GETSHORT(type, ansp);
|
||||
GETSHORT(class, ansp);
|
||||
|
||||
if (class == C_IN && type == T_TKEY)
|
||||
*is_sign = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(ansp = skip_questions(header, plen)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (arcount == 0)
|
||||
return NULL;
|
||||
|
||||
if (!(ansp = skip_section(ansp, ntohs(header->ancount) + ntohs(header->nscount), header, plen)))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < arcount; i++)
|
||||
{
|
||||
unsigned char *save, *start = ansp;
|
||||
if (!(ansp = skip_name(ansp, header, plen, 10)))
|
||||
return NULL;
|
||||
|
||||
GETSHORT(type, ansp);
|
||||
save = ansp;
|
||||
GETSHORT(class, ansp);
|
||||
ansp += 4; /* TTL */
|
||||
GETSHORT(rdlen, ansp);
|
||||
if (!ADD_RDLEN(header, ansp, plen, rdlen))
|
||||
return NULL;
|
||||
if (type == T_OPT)
|
||||
{
|
||||
if (len)
|
||||
*len = ansp - start;
|
||||
|
||||
if (p)
|
||||
*p = save;
|
||||
|
||||
if (is_last)
|
||||
*is_last = (i == arcount-1);
|
||||
|
||||
ret = start;
|
||||
}
|
||||
else if (is_sign &&
|
||||
i == arcount - 1 &&
|
||||
class == C_ANY &&
|
||||
type == T_TSIG)
|
||||
*is_sign = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* replace == 2 ->delete existing option only. */
|
||||
size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace)
|
||||
{
|
||||
unsigned char *lenp, *datap, *p, *udp_len, *buff = NULL;
|
||||
int rdlen = 0, is_sign, is_last;
|
||||
unsigned short flags = set_do ? 0x8000 : 0, rcode = 0;
|
||||
|
||||
p = find_pseudoheader(header, plen, NULL, &udp_len, &is_sign, &is_last);
|
||||
|
||||
if (is_sign)
|
||||
return plen;
|
||||
|
||||
if (p)
|
||||
{
|
||||
/* Existing header */
|
||||
int i;
|
||||
unsigned short code, len;
|
||||
|
||||
p = udp_len;
|
||||
GETSHORT(udp_sz, p);
|
||||
GETSHORT(rcode, p);
|
||||
GETSHORT(flags, p);
|
||||
|
||||
if (set_do)
|
||||
{
|
||||
p -= 2;
|
||||
flags |= 0x8000;
|
||||
PUTSHORT(flags, p);
|
||||
}
|
||||
|
||||
lenp = p;
|
||||
GETSHORT(rdlen, p);
|
||||
if (!CHECK_LEN(header, p, plen, rdlen))
|
||||
return plen; /* bad packet */
|
||||
datap = p;
|
||||
|
||||
/* no option to add */
|
||||
if (optno == 0)
|
||||
return plen;
|
||||
|
||||
/* check if option already there */
|
||||
for (i = 0; i + 4 < rdlen;)
|
||||
{
|
||||
GETSHORT(code, p);
|
||||
GETSHORT(len, p);
|
||||
|
||||
/* malformed option, delete the whole OPT RR and start again. */
|
||||
if (i + 4 + len > rdlen)
|
||||
{
|
||||
rdlen = 0;
|
||||
is_last = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (code == optno)
|
||||
{
|
||||
if (replace == 0)
|
||||
return plen;
|
||||
|
||||
/* delete option if we're to replace it. */
|
||||
p -= 4;
|
||||
rdlen -= len + 4;
|
||||
memmove(p, p+len+4, rdlen - i);
|
||||
PUTSHORT(rdlen, lenp);
|
||||
lenp -= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
p += len;
|
||||
i += len + 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're going to extend the RR, it has to be the last RR in the packet */
|
||||
if (!is_last)
|
||||
{
|
||||
/* First, take a copy of the options. */
|
||||
if (rdlen != 0 && (buff = whine_malloc(rdlen)))
|
||||
memcpy(buff, datap, rdlen);
|
||||
|
||||
/* now, delete OPT RR */
|
||||
plen = rrfilter(header, plen, 0);
|
||||
|
||||
/* Now, force addition of a new one */
|
||||
p = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p)
|
||||
{
|
||||
/* We are (re)adding the pseudoheader */
|
||||
if (!(p = skip_questions(header, plen)) ||
|
||||
!(p = skip_section(p,
|
||||
ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount),
|
||||
header, plen)))
|
||||
{
|
||||
free(buff);
|
||||
return plen;
|
||||
}
|
||||
if (p + 11 > limit)
|
||||
{
|
||||
free(buff);
|
||||
return plen; /* Too big */
|
||||
}
|
||||
*p++ = 0; /* empty name */
|
||||
PUTSHORT(T_OPT, p);
|
||||
PUTSHORT(udp_sz, p); /* max packet length, 512 if not given in EDNS0 header */
|
||||
PUTSHORT(rcode, p); /* extended RCODE and version */
|
||||
PUTSHORT(flags, p); /* DO flag */
|
||||
lenp = p;
|
||||
PUTSHORT(rdlen, p); /* RDLEN */
|
||||
datap = p;
|
||||
/* Copy back any options */
|
||||
if (buff)
|
||||
{
|
||||
if (p + rdlen > limit)
|
||||
{
|
||||
free(buff);
|
||||
return plen; /* Too big */
|
||||
}
|
||||
memcpy(p, buff, rdlen);
|
||||
free(buff);
|
||||
p += rdlen;
|
||||
}
|
||||
|
||||
/* Only bump arcount if RR is going to fit */
|
||||
if (((ssize_t)optlen) <= (limit - (p + 4)))
|
||||
header->arcount = htons(ntohs(header->arcount) + 1);
|
||||
}
|
||||
|
||||
if (((ssize_t)optlen) > (limit - (p + 4)))
|
||||
return plen; /* Too big */
|
||||
|
||||
/* Add new option */
|
||||
if (optno != 0 && replace != 2)
|
||||
{
|
||||
if (p + 4 > limit)
|
||||
return plen; /* Too big */
|
||||
PUTSHORT(optno, p);
|
||||
PUTSHORT(optlen, p);
|
||||
if (p + optlen > limit)
|
||||
return plen; /* Too big */
|
||||
memcpy(p, opt, optlen);
|
||||
p += optlen;
|
||||
PUTSHORT(p - datap, lenp);
|
||||
}
|
||||
return p - (unsigned char *)header;
|
||||
}
|
||||
|
||||
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit)
|
||||
{
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, 0, NULL, 0, 1, 0);
|
||||
}
|
||||
|
||||
static unsigned char char64(unsigned char c)
|
||||
{
|
||||
return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[c & 0x3f];
|
||||
}
|
||||
|
||||
static void encoder(unsigned char *in, char *out)
|
||||
{
|
||||
out[0] = char64(in[0]>>2);
|
||||
out[1] = char64((in[0]<<4) | (in[1]>>4));
|
||||
out[2] = char64((in[1]<<2) | (in[2]>>6));
|
||||
out[3] = char64(in[2]);
|
||||
}
|
||||
|
||||
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
|
||||
{
|
||||
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
char encode[18]; /* handle 6 byte MACs */
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
|
||||
{
|
||||
replace = 1;
|
||||
|
||||
if (option_bool(OPT_MAC_HEX))
|
||||
print_mac(encode, mac, maclen);
|
||||
else
|
||||
{
|
||||
encoder(mac, encode);
|
||||
encoder(mac+3, encode+4);
|
||||
encode[8] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
|
||||
}
|
||||
|
||||
|
||||
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
|
||||
{
|
||||
int maclen;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) != 0)
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
struct subnet_opt {
|
||||
u16 family;
|
||||
u8 source_netmask, scope_netmask;
|
||||
#ifdef HAVE_IPV6
|
||||
u8 addr[IN6ADDRSZ];
|
||||
#else
|
||||
u8 addr[INADDRSZ];
|
||||
#endif
|
||||
};
|
||||
|
||||
static void *get_addrp(union mysockaddr *addr, const short family)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
if (family == AF_INET6)
|
||||
return &addr->in6.sin6_addr;
|
||||
#endif
|
||||
|
||||
return &addr->in.sin_addr;
|
||||
}
|
||||
|
||||
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
|
||||
{
|
||||
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
|
||||
|
||||
int len;
|
||||
void *addrp = NULL;
|
||||
int sa_family = source->sa.sa_family;
|
||||
|
||||
opt->source_netmask = 0;
|
||||
opt->scope_netmask = 0;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
|
||||
{
|
||||
opt->source_netmask = daemon->add_subnet6->mask;
|
||||
if (daemon->add_subnet6->addr_used)
|
||||
{
|
||||
sa_family = daemon->add_subnet6->addr.sa.sa_family;
|
||||
addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
|
||||
}
|
||||
else
|
||||
addrp = &source->in6.sin6_addr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (source->sa.sa_family == AF_INET && daemon->add_subnet4)
|
||||
{
|
||||
opt->source_netmask = daemon->add_subnet4->mask;
|
||||
if (daemon->add_subnet4->addr_used)
|
||||
{
|
||||
sa_family = daemon->add_subnet4->addr.sa.sa_family;
|
||||
addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
|
||||
}
|
||||
else
|
||||
addrp = &source->in.sin_addr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
|
||||
#else
|
||||
opt->family = htons(1);
|
||||
#endif
|
||||
|
||||
len = 0;
|
||||
|
||||
if (addrp && opt->source_netmask != 0)
|
||||
{
|
||||
len = ((opt->source_netmask - 1) >> 3) + 1;
|
||||
memcpy(opt->addr, addrp, len);
|
||||
if (opt->source_netmask & 7)
|
||||
opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
|
||||
}
|
||||
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source)
|
||||
{
|
||||
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
|
||||
|
||||
int len;
|
||||
struct subnet_opt opt;
|
||||
|
||||
len = calc_subnet_opt(&opt, source);
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
|
||||
}
|
||||
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
|
||||
{
|
||||
/* Section 9.2, Check that subnet option in reply matches. */
|
||||
|
||||
int len, calc_len;
|
||||
struct subnet_opt opt;
|
||||
unsigned char *p;
|
||||
int code, i, rdlen;
|
||||
|
||||
calc_len = calc_subnet_opt(&opt, peer);
|
||||
|
||||
if (!(p = skip_name(pseudoheader, header, plen, 10)))
|
||||
return 1;
|
||||
|
||||
p += 8; /* skip UDP length and RCODE */
|
||||
|
||||
GETSHORT(rdlen, p);
|
||||
if (!CHECK_LEN(header, p, plen, rdlen))
|
||||
return 1; /* bad packet */
|
||||
|
||||
/* check if option there */
|
||||
for (i = 0; i + 4 < rdlen; i += len + 4)
|
||||
{
|
||||
GETSHORT(code, p);
|
||||
GETSHORT(len, p);
|
||||
if (code == EDNS0_OPTION_CLIENT_SUBNET)
|
||||
{
|
||||
/* make sure this doesn't mismatch. */
|
||||
opt.scope_netmask = p[3];
|
||||
if (len != calc_len || memcmp(p, &opt, len) != 0)
|
||||
return 0;
|
||||
}
|
||||
p += len;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, time_t now, int *check_subnet)
|
||||
{
|
||||
*check_subnet = 0;
|
||||
|
||||
if (option_bool(OPT_ADD_MAC))
|
||||
plen = add_mac(header, plen, limit, source, now);
|
||||
|
||||
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
|
||||
plen = add_dns_client(header, plen, limit, source, now);
|
||||
|
||||
if (daemon->dns_client_id)
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
|
||||
(unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
|
||||
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
plen = add_source_addr(header, plen, limit, source);
|
||||
*check_subnet = 1;
|
||||
}
|
||||
|
||||
return plen;
|
||||
}
|
||||
1282
src/forward.c
1282
src/forward.c
File diff suppressed because it is too large
Load Diff
122
src/helper.c
122
src/helper.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
|
||||
/* This file has code to fork a helper process which recieves data via a pipe
|
||||
/* This file has code to fork a helper process which receives data via a pipe
|
||||
shared with the main process and which is responsible for calling a script when
|
||||
DHCP leases change.
|
||||
|
||||
@@ -135,7 +135,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
max_fd != STDIN_FILENO && max_fd != pipefd[0] &&
|
||||
max_fd != event_fd && max_fd != err_fd)
|
||||
close(max_fd);
|
||||
|
||||
|
||||
#ifdef HAVE_LUASCRIPT
|
||||
if (daemon->luascript)
|
||||
{
|
||||
@@ -189,6 +189,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
unsigned char *buf = (unsigned char *)daemon->namebuff;
|
||||
unsigned char *end, *extradata, *alloc_buff = NULL;
|
||||
int is6, err = 0;
|
||||
int pipeout[2];
|
||||
|
||||
free(alloc_buff);
|
||||
|
||||
@@ -219,7 +220,18 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
action_str = "tftp";
|
||||
is6 = (data.flags != AF_INET);
|
||||
}
|
||||
else
|
||||
else if (data.action == ACTION_ARP)
|
||||
{
|
||||
action_str = "arp-add";
|
||||
is6 = (data.flags != AF_INET);
|
||||
}
|
||||
else if (data.action == ACTION_ARP_DEL)
|
||||
{
|
||||
action_str = "arp-del";
|
||||
is6 = (data.flags != AF_INET);
|
||||
data.action = ACTION_ARP;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
|
||||
@@ -289,7 +301,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
if (!is6)
|
||||
inet_ntop(AF_INET, &data.addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
#ifdef HAVE_DHCP6
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
inet_ntop(AF_INET6, &data.addr6, daemon->addrbuff, ADDRSTRLEN);
|
||||
#endif
|
||||
@@ -321,6 +333,22 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else if (data.action == ACTION_ARP)
|
||||
{
|
||||
lua_getglobal(lua, "arp");
|
||||
if (lua_type(lua, -1) != LUA_TFUNCTION)
|
||||
lua_pop(lua, 1); /* arp function optional */
|
||||
else
|
||||
{
|
||||
lua_pushstring(lua, action_str); /* arg1 - action */
|
||||
lua_newtable(lua); /* arg2 - data table */
|
||||
lua_pushstring(lua, daemon->addrbuff);
|
||||
lua_setfield(lua, -2, "client_address");
|
||||
lua_pushstring(lua, daemon->dhcp_buff);
|
||||
lua_setfield(lua, -2, "mac_address");
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_getglobal(lua, "lease"); /* function to call */
|
||||
@@ -445,16 +473,54 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
if (!daemon->lease_change_command)
|
||||
continue;
|
||||
|
||||
/* Pipe to capture stdout and stderr from script */
|
||||
if (!option_bool(OPT_DEBUG) && pipe(pipeout) == -1)
|
||||
continue;
|
||||
|
||||
/* possible fork errors are all temporary resource problems */
|
||||
while ((pid = fork()) == -1 && (errno == EAGAIN || errno == ENOMEM))
|
||||
sleep(2);
|
||||
|
||||
if (pid == -1)
|
||||
continue;
|
||||
{
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
{
|
||||
close(pipeout[0]);
|
||||
close(pipeout[1]);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* wait for child to complete */
|
||||
if (pid != 0)
|
||||
{
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
close(pipeout[1]);
|
||||
|
||||
/* Read lines sent to stdout/err by the script and pass them back to be logged */
|
||||
if (!(fp = fdopen(pipeout[0], "r")))
|
||||
close(pipeout[0]);
|
||||
else
|
||||
{
|
||||
while (fgets(daemon->packet, daemon->packet_buff_sz, fp))
|
||||
{
|
||||
/* do not include new lines, log will append them */
|
||||
size_t len = strlen(daemon->packet);
|
||||
if (len > 0)
|
||||
{
|
||||
--len;
|
||||
if (daemon->packet[len] == '\n')
|
||||
daemon->packet[len] = 0;
|
||||
}
|
||||
send_event(event_fd, EVENT_SCRIPT_LOG, 0, daemon->packet);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* reap our children's children, if necessary */
|
||||
while (1)
|
||||
{
|
||||
@@ -477,8 +543,17 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!option_bool(OPT_DEBUG))
|
||||
{
|
||||
/* map stdout/stderr of script to pipeout */
|
||||
close(pipeout[0]);
|
||||
dup2(pipeout[1], STDOUT_FILENO);
|
||||
dup2(pipeout[1], STDERR_FILENO);
|
||||
close(pipeout[1]);
|
||||
}
|
||||
|
||||
if (data.action != ACTION_TFTP)
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
|
||||
@@ -529,6 +604,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
|
||||
}
|
||||
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
|
||||
@@ -550,9 +626,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
my_setenv("DNSMASQ_OLD_HOSTNAME", data.action == ACTION_OLD_HOSTNAME ? hostname : NULL, &err);
|
||||
if (data.action == ACTION_OLD_HOSTNAME)
|
||||
hostname = NULL;
|
||||
|
||||
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
|
||||
}
|
||||
|
||||
my_setenv("DNSMASQ_LOG_DHCP", option_bool(OPT_LOG_OPTS) ? "1" : NULL, &err);
|
||||
|
||||
/* we need to have the event_fd around if exec fails */
|
||||
if ((i = fcntl(event_fd, F_GETFD)) != -1)
|
||||
@@ -563,8 +639,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
if (err == 0)
|
||||
{
|
||||
execl(daemon->lease_change_command,
|
||||
p ? p+1 : daemon->lease_change_command,
|
||||
action_str, is6 ? daemon->packet : daemon->dhcp_buff,
|
||||
p ? p+1 : daemon->lease_change_command, action_str,
|
||||
(is6 && data.action != ACTION_ARP) ? daemon->packet : daemon->dhcp_buff,
|
||||
daemon->addrbuff, hostname, (char*)NULL);
|
||||
err = errno;
|
||||
}
|
||||
@@ -760,6 +836,30 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
||||
}
|
||||
#endif
|
||||
|
||||
void queue_arp(int action, unsigned char *mac, int maclen, int family, struct all_addr *addr)
|
||||
{
|
||||
/* no script */
|
||||
if (daemon->helperfd == -1)
|
||||
return;
|
||||
|
||||
buff_alloc(sizeof(struct script_data));
|
||||
memset(buf, 0, sizeof(struct script_data));
|
||||
|
||||
buf->action = action;
|
||||
buf->hwaddr_len = maclen;
|
||||
buf->hwaddr_type = ARPHRD_ETHER;
|
||||
if ((buf->flags = family) == AF_INET)
|
||||
buf->addr = addr->addr.addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
buf->addr6 = addr->addr.addr6;
|
||||
#endif
|
||||
|
||||
memcpy(buf->hwaddr, mac, maclen);
|
||||
|
||||
bytes_in_buf = sizeof(struct script_data);
|
||||
}
|
||||
|
||||
int helper_buf_empty(void)
|
||||
{
|
||||
return bytes_in_buf == 0;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -42,20 +42,22 @@ static char *inotify_buffer;
|
||||
Return value is malloc'ed */
|
||||
static char *my_readlink(char *path)
|
||||
{
|
||||
ssize_t rc;
|
||||
size_t size = 64;
|
||||
ssize_t rc, size = 64;
|
||||
char *buf;
|
||||
|
||||
while (1)
|
||||
{
|
||||
buf = safe_malloc(size);
|
||||
rc = readlink(path, buf, size);
|
||||
rc = readlink(path, buf, (size_t)size);
|
||||
|
||||
if (rc == -1)
|
||||
{
|
||||
/* Not link or doesn't exist. */
|
||||
if (errno == EINVAL || errno == ENOENT)
|
||||
return NULL;
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
die(_("cannot access path %s: %s"), path, EC_MISC);
|
||||
}
|
||||
@@ -91,6 +93,9 @@ void inotify_dnsmasq_init()
|
||||
|
||||
if (daemon->inotifyfd == -1)
|
||||
die(_("failed to create inotify: %s"), NULL, EC_MISC);
|
||||
|
||||
if (option_bool(OPT_NO_RESOLV))
|
||||
return;
|
||||
|
||||
for (res = daemon->resolv_files; res; res = res->next)
|
||||
{
|
||||
@@ -99,7 +104,7 @@ void inotify_dnsmasq_init()
|
||||
|
||||
strcpy(path, res->name);
|
||||
|
||||
/* Follow symlinks until we reach a non-symlink, or a non-existant file. */
|
||||
/* Follow symlinks until we reach a non-symlink, or a non-existent file. */
|
||||
while ((new_path = my_readlink(path)))
|
||||
{
|
||||
if (links-- == 0)
|
||||
@@ -198,6 +203,8 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
|
||||
free(path);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir_stream);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +260,7 @@ int inotify_check(time_t now)
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->doing_dhcp6)
|
||||
{
|
||||
/* Propogate the consequences of loading a new dhcp-host */
|
||||
/* Propagate the consequences of loading a new dhcp-host */
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
@@ -266,7 +273,7 @@ int inotify_check(time_t now)
|
||||
{
|
||||
if (option_read_dynfile(path, AH_DHCP_HST))
|
||||
{
|
||||
/* Propogate the consequences of loading a new dhcp-host */
|
||||
/* Propagate the consequences of loading a new dhcp-host */
|
||||
dhcp_update_configs(daemon->dhcp_conf);
|
||||
lease_update_from_configs();
|
||||
lease_update_file(now);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
15
src/ipset.c
15
src/ipset.c
@@ -211,7 +211,7 @@ 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 af = AF_INET;
|
||||
int ret = 0, af = AF_INET;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
@@ -219,11 +219,20 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr, int flags,
|
||||
af = AF_INET6;
|
||||
/* old method only supports IPv4 */
|
||||
if (old_kernel)
|
||||
return -1;
|
||||
{
|
||||
errno = EAFNOSUPPORT ;
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
|
||||
if (ret != -1)
|
||||
ret = old_kernel ? old_add_to_ipset(setname, ipaddr, remove) : new_add_to_ipset(setname, ipaddr, af, remove);
|
||||
|
||||
if (ret == -1)
|
||||
my_syslog(LOG_ERR, _("failed to update ipset %s: %s"), setname, strerror(errno));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
239
src/lease.c
239
src/lease.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -21,21 +21,126 @@
|
||||
static struct dhcp_lease *leases = NULL, *old_leases = NULL;
|
||||
static int dns_dirty, file_dirty, leases_left;
|
||||
|
||||
void lease_init(time_t now)
|
||||
static int read_leases(time_t now, FILE *leasestream)
|
||||
{
|
||||
unsigned long ei;
|
||||
struct all_addr addr;
|
||||
struct dhcp_lease *lease;
|
||||
int clid_len, hw_len, hw_type;
|
||||
int items;
|
||||
char *domain = NULL;
|
||||
|
||||
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
|
||||
|
||||
/* client-id max length is 255 which is 255*2 digits + 254 colons
|
||||
borrow DNS packet buffer which is always larger than 1000 bytes
|
||||
|
||||
Check various buffers are big enough for the code below */
|
||||
|
||||
#if (DHCP_BUFF_SZ < 255) || (MAXDNAME < 64) || (PACKETSZ+MAXDNAME+RRFIXEDSZ < 764)
|
||||
# error Buffer size breakage in leasefile parsing.
|
||||
#endif
|
||||
|
||||
while ((items=fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2)) == 2)
|
||||
{
|
||||
*daemon->namebuff = *daemon->dhcp_buff = *daemon->packet = '\0';
|
||||
hw_len = hw_type = clid_len = 0;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (strcmp(daemon->dhcp_buff3, "duid") == 0)
|
||||
{
|
||||
daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
|
||||
if (daemon->duid_len < 0)
|
||||
return 0;
|
||||
daemon->duid = safe_malloc(daemon->duid_len);
|
||||
memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (fscanf(leasestream, " %64s %255s %764s",
|
||||
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)))
|
||||
domain = get_domain(lease->addr);
|
||||
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explicit MAC address type means ether. */
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
|
||||
{
|
||||
char *s = daemon->dhcp_buff2;
|
||||
int lease_type = LEASE_NA;
|
||||
|
||||
if (s[0] == 'T')
|
||||
{
|
||||
lease_type = LEASE_TA;
|
||||
s++;
|
||||
}
|
||||
|
||||
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
|
||||
{
|
||||
lease_set_iaid(lease, strtoul(s, NULL, 10));
|
||||
domain = get_domain6((struct in6_addr *)lease->hwaddr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return 0;
|
||||
|
||||
if (!lease)
|
||||
die (_("too many stored leases"), NULL, EC_MISC);
|
||||
|
||||
if (strcmp(daemon->packet, "*") != 0)
|
||||
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
||||
|
||||
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
|
||||
hw_len, hw_type, clid_len, now, 0);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, domain, NULL);
|
||||
|
||||
ei = atol(daemon->dhcp_buff3);
|
||||
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
if (ei != 0)
|
||||
lease->expires = (time_t)ei + now;
|
||||
else
|
||||
lease->expires = (time_t)0;
|
||||
lease->length = ei;
|
||||
#else
|
||||
/* strictly time_t is opaque, but this hack should work on all sane systems,
|
||||
even when sizeof(time_t) == 8 */
|
||||
lease->expires = (time_t)ei;
|
||||
#endif
|
||||
|
||||
/* set these correctly: the "old" events are generated later from
|
||||
the startup synthesised SIGHUP. */
|
||||
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
|
||||
|
||||
*daemon->dhcp_buff3 = *daemon->dhcp_buff2 = '\0';
|
||||
}
|
||||
|
||||
return (items == 0 || items == EOF);
|
||||
}
|
||||
|
||||
void lease_init(time_t now)
|
||||
{
|
||||
FILE *leasestream;
|
||||
|
||||
|
||||
leases_left = daemon->dhcp_max;
|
||||
|
||||
|
||||
if (option_bool(OPT_LEASE_RO))
|
||||
{
|
||||
/* run "<lease_change_script> init" once to get the
|
||||
initial state of the database. If leasefile-ro is
|
||||
set without a script, we just do without any
|
||||
set without a script, we just do without any
|
||||
lease database. */
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command)
|
||||
@@ -56,99 +161,24 @@ void lease_init(time_t now)
|
||||
{
|
||||
/* NOTE: need a+ mode to create file if it doesn't exist */
|
||||
leasestream = daemon->lease_stream = fopen(daemon->lease_file, "a+");
|
||||
|
||||
|
||||
if (!leasestream)
|
||||
die(_("cannot open or create lease file %s: %s"), daemon->lease_file, EC_FILE);
|
||||
|
||||
|
||||
/* a+ mode leaves pointer at end. */
|
||||
rewind(leasestream);
|
||||
}
|
||||
|
||||
/* client-id max length is 255 which is 255*2 digits + 254 colons
|
||||
borrow DNS packet buffer which is always larger than 1000 bytes */
|
||||
|
||||
if (leasestream)
|
||||
while (fscanf(leasestream, "%255s %255s", daemon->dhcp_buff3, daemon->dhcp_buff2) == 2)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
if (strcmp(daemon->dhcp_buff3, "duid") == 0)
|
||||
{
|
||||
daemon->duid_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, 130, NULL, NULL);
|
||||
daemon->duid = safe_malloc(daemon->duid_len);
|
||||
memcpy(daemon->duid, daemon->dhcp_buff2, daemon->duid_len);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
{
|
||||
if (!read_leases(now, leasestream))
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("failed to parse lease database, invalid line: %s %s %s %s ..."),
|
||||
daemon->dhcp_buff3, daemon->dhcp_buff2,
|
||||
daemon->namebuff, daemon->dhcp_buff);
|
||||
|
||||
ei = atol(daemon->dhcp_buff3);
|
||||
|
||||
if (fscanf(leasestream, " %64s %255s %764s",
|
||||
daemon->namebuff, daemon->dhcp_buff, daemon->packet) != 3)
|
||||
break;
|
||||
|
||||
clid_len = 0;
|
||||
if (strcmp(daemon->packet, "*") != 0)
|
||||
clid_len = parse_hex(daemon->packet, (unsigned char *)daemon->packet, 255, NULL, NULL);
|
||||
|
||||
if (inet_pton(AF_INET, daemon->namebuff, &addr.addr.addr4) &&
|
||||
(lease = lease4_allocate(addr.addr.addr4)))
|
||||
{
|
||||
hw_len = parse_hex(daemon->dhcp_buff2, (unsigned char *)daemon->dhcp_buff2, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||
/* For backwards compatibility, no explict MAC address type means ether. */
|
||||
if (hw_type == 0 && hw_len != 0)
|
||||
hw_type = ARPHRD_ETHER;
|
||||
|
||||
lease_set_hwaddr(lease, (unsigned char *)daemon->dhcp_buff2, (unsigned char *)daemon->packet,
|
||||
hw_len, hw_type, clid_len, now, 0);
|
||||
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain(lease->addr), NULL);
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (inet_pton(AF_INET6, daemon->namebuff, &addr.addr.addr6))
|
||||
{
|
||||
char *s = daemon->dhcp_buff2;
|
||||
int lease_type = LEASE_NA;
|
||||
int iaid;
|
||||
|
||||
if (s[0] == 'T')
|
||||
{
|
||||
lease_type = LEASE_TA;
|
||||
s++;
|
||||
}
|
||||
|
||||
iaid = strtoul(s, NULL, 10);
|
||||
|
||||
if ((lease = lease6_allocate(&addr.addr.addr6, lease_type)))
|
||||
{
|
||||
lease_set_hwaddr(lease, NULL, (unsigned char *)daemon->packet, 0, 0, clid_len, now, 0);
|
||||
lease_set_iaid(lease, iaid);
|
||||
if (strcmp(daemon->dhcp_buff, "*") != 0)
|
||||
lease_set_hostname(lease, daemon->dhcp_buff, 0, get_domain6((struct in6_addr *)lease->hwaddr), NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
break;
|
||||
|
||||
if (!lease)
|
||||
die (_("too many stored leases"), NULL, EC_MISC);
|
||||
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
if (ei != 0)
|
||||
lease->expires = (time_t)ei + now;
|
||||
else
|
||||
lease->expires = (time_t)0;
|
||||
lease->length = ei;
|
||||
#else
|
||||
/* strictly time_t is opaque, but this hack should work on all sane systems,
|
||||
even when sizeof(time_t) == 8 */
|
||||
lease->expires = (time_t)ei;
|
||||
#endif
|
||||
|
||||
/* set these correctly: the "old" events are generated later from
|
||||
the startup synthesised SIGHUP. */
|
||||
lease->flags &= ~(LEASE_NEW | LEASE_CHANGED);
|
||||
}
|
||||
if (ferror(leasestream))
|
||||
die(_("failed to read lease file %s: %s"), daemon->lease_file, EC_FILE);
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (!daemon->lease_stream)
|
||||
@@ -162,6 +192,7 @@ void lease_init(time_t now)
|
||||
errno = ENOENT;
|
||||
else if (WEXITSTATUS(rc) == 126)
|
||||
errno = EACCES;
|
||||
|
||||
die(_("cannot run lease-init script %s: %s"), daemon->lease_change_command, EC_FILE);
|
||||
}
|
||||
|
||||
@@ -198,7 +229,7 @@ void lease_update_from_configs(void)
|
||||
else if ((name = host_from_dns(lease->addr)))
|
||||
lease_set_hostname(lease, name, 1, get_domain(lease->addr), NULL); /* updates auth flag only */
|
||||
}
|
||||
|
||||
|
||||
static void ourprintf(int *errp, char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@@ -406,7 +437,7 @@ void lease_ping_reply(struct in6_addr *sender, unsigned char *packet, char *inte
|
||||
|
||||
void lease_update_slaac(time_t now)
|
||||
{
|
||||
/* Called when we contruct a new RA-names context, to add putative
|
||||
/* Called when we construct a new RA-names context, to add putative
|
||||
new SLAAC addresses to existing leases. */
|
||||
|
||||
struct dhcp_lease *lease;
|
||||
@@ -776,7 +807,7 @@ void lease_set_expires(struct dhcp_lease *lease, unsigned int len, time_t now)
|
||||
{
|
||||
exp = now + (time_t)len;
|
||||
/* Check for 2038 overflow. Make the lease
|
||||
inifinite in that case, as the least disruptive
|
||||
infinite in that case, as the least disruptive
|
||||
thing we can do. */
|
||||
if (difftime(exp, now) <= 0.0)
|
||||
exp = 0;
|
||||
@@ -1110,18 +1141,22 @@ int do_script_run(time_t now)
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
/* delim == -1 -> delim = 0, but embedded 0s, creating extra records, are OK. */
|
||||
void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned int len, int delim)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* check for embeded NULLs */
|
||||
for (i = 0; i < len; i++)
|
||||
if (data[i] == 0)
|
||||
{
|
||||
len = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (delim == -1)
|
||||
delim = 0;
|
||||
else
|
||||
/* check for embedded NULLs */
|
||||
for (i = 0; i < len; i++)
|
||||
if (data[i] == 0)
|
||||
{
|
||||
len = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((lease->extradata_size - lease->extradata_len) < (len + 1))
|
||||
{
|
||||
size_t newsz = lease->extradata_len + len + 100;
|
||||
|
||||
21
src/log.c
21
src/log.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -154,7 +154,7 @@ static void log_write(void)
|
||||
|
||||
while (entries)
|
||||
{
|
||||
/* The data in the payoad is written with a terminating zero character
|
||||
/* The data in the payload is written with a terminating zero character
|
||||
and the length reflects this. For a stream connection we need to
|
||||
send the zero as a record terminator, but this isn't done for a
|
||||
datagram connection, so treat the length as one less than reality
|
||||
@@ -288,7 +288,9 @@ void my_syslog(int priority, const char *format, ...)
|
||||
func = "-tftp";
|
||||
else if ((LOG_FACMASK & priority) == MS_DHCP)
|
||||
func = "-dhcp";
|
||||
|
||||
else if ((LOG_FACMASK & priority) == MS_SCRIPT)
|
||||
func = "-script";
|
||||
|
||||
#ifdef LOG_PRI
|
||||
priority = LOG_PRI(priority);
|
||||
#else
|
||||
@@ -421,25 +423,22 @@ void my_syslog(int priority, const char *format, ...)
|
||||
}
|
||||
}
|
||||
|
||||
void set_log_writer(fd_set *set, int *maxfdp)
|
||||
void set_log_writer(void)
|
||||
{
|
||||
if (entries && log_fd != -1 && connection_good)
|
||||
{
|
||||
FD_SET(log_fd, set);
|
||||
bump_maxfd(log_fd, maxfdp);
|
||||
}
|
||||
poll_listen(log_fd, POLLOUT);
|
||||
}
|
||||
|
||||
void check_log_writer(fd_set *set)
|
||||
void check_log_writer(int force)
|
||||
{
|
||||
if (log_fd != -1 && (!set || FD_ISSET(log_fd, set)))
|
||||
if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
|
||||
log_write();
|
||||
}
|
||||
|
||||
void flush_log(void)
|
||||
{
|
||||
/* write until queue empty, but don't loop forever if there's
|
||||
no connection to the syslog in existance */
|
||||
no connection to the syslog in existence */
|
||||
while (log_fd != -1)
|
||||
{
|
||||
struct timespec waiter;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -73,7 +73,7 @@ void netlink_init(void)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* save pid assigned by bind() and retrieved by getsockname() */
|
||||
@@ -188,11 +188,17 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
}
|
||||
|
||||
for (h = (struct nlmsghdr *)iov.iov_base; NLMSG_OK(h, (size_t)len); h = NLMSG_NEXT(h, len))
|
||||
if (h->nlmsg_seq != seq || h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||
if (h->nlmsg_pid != netlink_pid || h->nlmsg_type == NLMSG_ERROR)
|
||||
{
|
||||
/* May be multicast arriving async */
|
||||
nl_async(h);
|
||||
}
|
||||
else if (h->nlmsg_seq != seq)
|
||||
{
|
||||
/* May be part of incomplete response to previous request after
|
||||
ENOBUFS. Drop it. */
|
||||
continue;
|
||||
}
|
||||
else if (h->nlmsg_type == NLMSG_DONE)
|
||||
return callback_ok;
|
||||
else if (h->nlmsg_type == RTM_NEWADDR && family != AF_UNSPEC && family != AF_LOCAL)
|
||||
@@ -288,7 +294,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
rta = RTA_NEXT(rta, len1);
|
||||
}
|
||||
|
||||
if (inaddr && mac && callback_ok)
|
||||
if (!(neigh->ndm_state & (NUD_NOARP | NUD_INCOMPLETE | NUD_FAILED)) &&
|
||||
inaddr && mac && callback_ok)
|
||||
if (!((*callback)(neigh->ndm_family, inaddr, mac, maclen, parm)))
|
||||
callback_ok = 0;
|
||||
}
|
||||
|
||||
189
src/network.c
189
src/network.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -178,7 +178,7 @@ int iface_check(int family, struct all_addr *addr, char *name, int *auth)
|
||||
}
|
||||
|
||||
|
||||
/* Fix for problem that the kernel sometimes reports the loopback inerface as the
|
||||
/* Fix for problem that the kernel sometimes reports the loopback interface as the
|
||||
arrival interface when a packet originates locally, even when sent to address of
|
||||
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
|
||||
@@ -244,6 +244,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||
int dhcp_ok = 1;
|
||||
int auth_dns = 0;
|
||||
int is_label = 0;
|
||||
#if defined(HAVE_DHCP) || defined(HAVE_TFTP)
|
||||
struct iname *tmp;
|
||||
#endif
|
||||
@@ -264,6 +265,8 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
|
||||
if (!label)
|
||||
label = ifr.ifr_name;
|
||||
else
|
||||
is_label = strcmp(label, ifr.ifr_name);
|
||||
|
||||
/* maintain a list of all addresses on all interfaces for --local-service option */
|
||||
if (option_bool(OPT_LOCAL_SERVICE))
|
||||
@@ -482,6 +485,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
iface->found = 1;
|
||||
iface->done = iface->multicast_done = iface->warned = 0;
|
||||
iface->index = if_index;
|
||||
iface->label = is_label;
|
||||
if ((iface->name = whine_malloc(strlen(ifr.ifr_name)+1)))
|
||||
{
|
||||
strcpy(iface->name, ifr.ifr_name);
|
||||
@@ -532,13 +536,14 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
|
||||
{
|
||||
union mysockaddr addr;
|
||||
int prefix, bit;
|
||||
|
||||
(void)broadcast; /* warning */
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||
addr.in.sin_len = sizeof(addr.in);
|
||||
#endif
|
||||
addr.in.sin_family = AF_INET;
|
||||
addr.in.sin_addr = broadcast; /* warning */
|
||||
addr.in.sin_addr = local;
|
||||
addr.in.sin_port = htons(daemon->port);
|
||||
|
||||
@@ -643,7 +648,7 @@ int enumerate_interfaces(int reset)
|
||||
/* Garbage-collect listeners listening on addresses that no longer exist.
|
||||
Does nothing when not binding interfaces or for listeners on localhost,
|
||||
since the ->iface field is NULL. Note that this needs the protections
|
||||
against re-entrancy, hence it's here. It also means there's a possibility,
|
||||
against reentrancy, hence it's here. It also means there's a possibility,
|
||||
in OPT_CLEVERBIND mode, that at listener will just disappear after
|
||||
a call to enumerate_interfaces, this is checked OK on all calls. */
|
||||
struct listener *l, *tmp, **up;
|
||||
@@ -698,7 +703,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
||||
|
||||
if ((fd = socket(family, type, 0)) == -1)
|
||||
{
|
||||
int port, errsav;
|
||||
int port, errsave;
|
||||
char *s;
|
||||
|
||||
/* No error if the kernel just doesn't support this IP flavour */
|
||||
@@ -708,7 +713,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
||||
return -1;
|
||||
|
||||
err:
|
||||
errsav = errno;
|
||||
errsave = errno;
|
||||
port = prettyprint_addr(addr, daemon->addrbuff);
|
||||
if (!option_bool(OPT_NOWILD) && !option_bool(OPT_CLEVERBIND))
|
||||
sprintf(daemon->addrbuff, "port %d", port);
|
||||
@@ -717,7 +722,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
||||
if (fd != -1)
|
||||
close (fd);
|
||||
|
||||
errno = errsav;
|
||||
errno = errsave;
|
||||
|
||||
if (dienow)
|
||||
{
|
||||
@@ -745,7 +750,7 @@ static int make_sock(union mysockaddr *addr, int type, int dienow)
|
||||
|
||||
if (type == SOCK_STREAM)
|
||||
{
|
||||
if (listen(fd, 5) == -1)
|
||||
if (listen(fd, TCP_BACKLOG) == -1)
|
||||
goto err;
|
||||
}
|
||||
else if (family == AF_INET)
|
||||
@@ -809,10 +814,11 @@ int tcp_interface(int fd, int af)
|
||||
int opt = 1;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
socklen_t len;
|
||||
|
||||
/* use mshdr do that the CMSDG_* macros are available */
|
||||
/* use mshdr so that the CMSDG_* macros are available */
|
||||
msg.msg_control = daemon->packet;
|
||||
msg.msg_controllen = daemon->packet_buff_sz;
|
||||
msg.msg_controllen = len = daemon->packet_buff_sz;
|
||||
|
||||
/* we overwrote the buffer... */
|
||||
daemon->srv_save = NULL;
|
||||
@@ -820,18 +826,21 @@ int tcp_interface(int fd, int af)
|
||||
if (af == AF_INET)
|
||||
{
|
||||
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) != -1 &&
|
||||
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
union {
|
||||
unsigned char *c;
|
||||
struct in_pktinfo *p;
|
||||
} p;
|
||||
|
||||
p.c = CMSG_DATA(cmptr);
|
||||
if_index = p.p->ipi_ifindex;
|
||||
}
|
||||
getsockopt(fd, IPPROTO_IP, IP_PKTOPTIONS, msg.msg_control, &len) != -1)
|
||||
{
|
||||
msg.msg_controllen = len;
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
{
|
||||
union {
|
||||
unsigned char *c;
|
||||
struct in_pktinfo *p;
|
||||
} p;
|
||||
|
||||
p.c = CMSG_DATA(cmptr);
|
||||
if_index = p.p->ipi_ifindex;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
@@ -849,9 +858,10 @@ int tcp_interface(int fd, int af)
|
||||
#endif
|
||||
|
||||
if (set_ipv6pktinfo(fd) &&
|
||||
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, (socklen_t *)&msg.msg_controllen) != -1)
|
||||
getsockopt(fd, IPPROTO_IPV6, PKTOPTIONS, msg.msg_control, &len) != -1)
|
||||
{
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
msg.msg_controllen = len;
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
union {
|
||||
@@ -1028,6 +1038,15 @@ void warn_bound_listeners(void)
|
||||
my_syslog(LOG_WARNING, _("LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid DNS amplification attacks via these interface(s)"));
|
||||
}
|
||||
|
||||
void warn_wild_labels(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
if (iface->found && iface->name && iface->label)
|
||||
my_syslog(LOG_WARNING, _("warning: using interface %s instead"), iface->name);
|
||||
}
|
||||
|
||||
void warn_int_names(void)
|
||||
{
|
||||
struct interface_name *intname;
|
||||
@@ -1076,23 +1095,30 @@ void join_multicast(int dienow)
|
||||
|
||||
if ((daemon->doing_dhcp6 || daemon->relay6) &&
|
||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||
err = 1;
|
||||
err = errno;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &mreq.ipv6mr_multiaddr);
|
||||
|
||||
if (daemon->doing_dhcp6 &&
|
||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||
err = 1;
|
||||
err = errno;
|
||||
|
||||
inet_pton(AF_INET6, ALL_ROUTERS, &mreq.ipv6mr_multiaddr);
|
||||
|
||||
if (daemon->doing_ra &&
|
||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1)
|
||||
err = 1;
|
||||
err = errno;
|
||||
|
||||
if (err)
|
||||
{
|
||||
char *s = _("interface %s failed to join DHCPv6 multicast group: %s");
|
||||
errno = err;
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
if (errno == ENOMEM)
|
||||
my_syslog(LOG_ERR, _("try increasing /proc/sys/net/core/optmem_max"));
|
||||
#endif
|
||||
|
||||
if (dienow)
|
||||
die(s, iface->name, EC_BADNET);
|
||||
else
|
||||
@@ -1112,7 +1138,7 @@ int random_sock(int family)
|
||||
if ((fd = socket(family, SOCK_DGRAM, 0)) != -1)
|
||||
{
|
||||
union mysockaddr addr;
|
||||
unsigned int ports_avail = 65536u - (unsigned short)daemon->min_port;
|
||||
unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
|
||||
int tries = ports_avail < 30 ? 3 * ports_avail : 100;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
@@ -1125,8 +1151,8 @@ int random_sock(int family)
|
||||
{
|
||||
unsigned short port = rand16();
|
||||
|
||||
if (daemon->min_port != 0)
|
||||
port = htons(daemon->min_port + (port % ((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)
|
||||
{
|
||||
@@ -1191,6 +1217,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
||||
static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
{
|
||||
struct serverfd *sfd;
|
||||
unsigned int ifindex = 0;
|
||||
int errsave;
|
||||
|
||||
/* when using random ports, servers which would otherwise use
|
||||
@@ -1211,11 +1238,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (intname && strlen(intname) != 0)
|
||||
ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
|
||||
|
||||
/* may have a suitable one already */
|
||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next )
|
||||
if (sockaddr_isequal(&sfd->source_addr, addr) &&
|
||||
strcmp(intname, sfd->interface) == 0)
|
||||
strcmp(intname, sfd->interface) == 0 &&
|
||||
ifindex == sfd->ifindex)
|
||||
return sfd;
|
||||
|
||||
/* need to make a new one. */
|
||||
@@ -1237,11 +1268,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
errno = errsave;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
strcpy(sfd->interface, intname);
|
||||
sfd->source_addr = *addr;
|
||||
sfd->next = daemon->sfds;
|
||||
sfd->ifindex = ifindex;
|
||||
daemon->sfds = sfd;
|
||||
|
||||
return sfd;
|
||||
}
|
||||
|
||||
@@ -1396,7 +1429,6 @@ void add_update_server(int flags,
|
||||
serv->domain = domain_str;
|
||||
serv->next = next;
|
||||
serv->queries = serv->failed_queries = 0;
|
||||
serv->edns_pktsz = daemon->edns_pktsz;
|
||||
#ifdef HAVE_LOOP
|
||||
serv->uid = rand32();
|
||||
#endif
|
||||
@@ -1417,18 +1449,58 @@ void check_servers(void)
|
||||
{
|
||||
struct irec *iface;
|
||||
struct server *serv;
|
||||
int port = 0;
|
||||
struct serverfd *sfd, *tmp, **up;
|
||||
int port = 0, count;
|
||||
int locals = 0;
|
||||
|
||||
/* interface may be new since startup */
|
||||
if (!option_bool(OPT_NOWILD))
|
||||
enumerate_interfaces(0);
|
||||
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
{
|
||||
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||
{
|
||||
port = prettyprint_addr(&serv->addr, daemon->namebuff);
|
||||
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
||||
sfd->used = 0;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* Disable DNSSEC validation when using server=/domain/.... servers
|
||||
unless there's a configured trust anchor. */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
serv->flags |= SERV_DO_DNSSEC;
|
||||
#endif
|
||||
|
||||
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
|
||||
{
|
||||
if (!(serv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)))
|
||||
{
|
||||
/* Init edns_pktsz for newly created server records. */
|
||||
if (serv->edns_pktsz == 0)
|
||||
serv->edns_pktsz = daemon->edns_pktsz;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID))
|
||||
{
|
||||
if (serv->flags & SERV_HAS_DOMAIN)
|
||||
{
|
||||
struct ds_config *ds;
|
||||
char *domain = serv->domain;
|
||||
|
||||
/* .example.com is valid */
|
||||
while (*domain == '.')
|
||||
domain++;
|
||||
|
||||
for (ds = daemon->ds; ds; ds = ds->next)
|
||||
if (ds->name[0] != 0 && hostname_isequal(domain, ds->name))
|
||||
break;
|
||||
|
||||
if (!ds)
|
||||
serv->flags &= ~SERV_DO_DNSSEC;
|
||||
}
|
||||
else if (serv->flags & SERV_FOR_NODOTS)
|
||||
serv->flags &= ~SERV_DO_DNSSEC;
|
||||
}
|
||||
#endif
|
||||
|
||||
port = prettyprint_addr(&serv->addr, daemon->namebuff);
|
||||
|
||||
/* 0.0.0.0 is nothing, the stack treats it like 127.0.0.1 */
|
||||
if (serv->addr.sa.sa_family == AF_INET &&
|
||||
serv->addr.in.sin_addr.s_addr == 0)
|
||||
@@ -1458,13 +1530,23 @@ void check_servers(void)
|
||||
serv->flags |= SERV_MARK;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (serv->sfd)
|
||||
serv->sfd->used = 1;
|
||||
}
|
||||
|
||||
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
|
||||
{
|
||||
if (++count > SERVERS_LOGGED)
|
||||
continue;
|
||||
|
||||
if (serv->flags & (SERV_HAS_DOMAIN | SERV_FOR_NODOTS | SERV_USE_RESOLV))
|
||||
{
|
||||
char *s1, *s2;
|
||||
char *s1, *s2, *s3 = "";
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && !(serv->flags & SERV_DO_DNSSEC))
|
||||
s3 = _("(no DNSSEC)");
|
||||
#endif
|
||||
if (!(serv->flags & SERV_HAS_DOMAIN))
|
||||
s1 = _("unqualified"), s2 = _("names");
|
||||
else if (strlen(serv->domain) == 0)
|
||||
@@ -1473,11 +1555,15 @@ void check_servers(void)
|
||||
s1 = _("domain"), s2 = serv->domain;
|
||||
|
||||
if (serv->flags & SERV_NO_ADDR)
|
||||
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
|
||||
{
|
||||
count--;
|
||||
if (++locals <= LOCALS_LOGGED)
|
||||
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2);
|
||||
}
|
||||
else if (serv->flags & SERV_USE_RESOLV)
|
||||
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1, s2);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s"), daemon->namebuff, port, s1, s2);
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), daemon->namebuff, port, s1, s2, s3);
|
||||
}
|
||||
#ifdef HAVE_LOOP
|
||||
else if (serv->flags & SERV_LOOP)
|
||||
@@ -1489,7 +1575,26 @@ void check_servers(void)
|
||||
my_syslog(LOG_INFO, _("using nameserver %s#%d"), daemon->namebuff, port);
|
||||
}
|
||||
}
|
||||
|
||||
if (locals > LOCALS_LOGGED)
|
||||
my_syslog(LOG_INFO, _("using %d more local addresses"), locals - LOCALS_LOGGED);
|
||||
if (count - 1 > SERVERS_LOGGED)
|
||||
my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
|
||||
|
||||
/* Remove unused sfds */
|
||||
for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
|
||||
{
|
||||
tmp = sfd->next;
|
||||
if (!sfd->used)
|
||||
{
|
||||
*up = sfd->next;
|
||||
close(sfd->fd);
|
||||
free(sfd);
|
||||
}
|
||||
else
|
||||
up = &sfd->next;
|
||||
}
|
||||
|
||||
cleanup_servers();
|
||||
}
|
||||
|
||||
|
||||
487
src/option.c
487
src/option.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -154,7 +154,13 @@ struct myoption {
|
||||
#define LOPT_HOST_INOTIFY 342
|
||||
#define LOPT_DNSSEC_STAMP 343
|
||||
#define LOPT_TFTP_NO_FAIL 344
|
||||
|
||||
#define LOPT_MAXPORT 345
|
||||
#define LOPT_CPE_ID 346
|
||||
#define LOPT_SCRIPT_ARP 347
|
||||
#define LOPT_DHCPTTL 348
|
||||
#define LOPT_TFTP_MTU 349
|
||||
#define LOPT_REPLY_DELAY 350
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
#else
|
||||
@@ -237,9 +243,10 @@ static const struct myoption opts[] =
|
||||
{ "enable-tftp", 2, 0, LOPT_TFTP },
|
||||
{ "tftp-secure", 0, 0, LOPT_SECURE },
|
||||
{ "tftp-no-fail", 0, 0, LOPT_TFTP_NO_FAIL },
|
||||
{ "tftp-unique-root", 0, 0, LOPT_APREF },
|
||||
{ "tftp-unique-root", 2, 0, LOPT_APREF },
|
||||
{ "tftp-root", 1, 0, LOPT_PREFIX },
|
||||
{ "tftp-max", 1, 0, LOPT_TFTP_MAX },
|
||||
{ "tftp-mtu", 1, 0, LOPT_TFTP_MTU },
|
||||
{ "tftp-lowercase", 0, 0, LOPT_TFTP_LC },
|
||||
{ "ptr-record", 1, 0, LOPT_PTR },
|
||||
{ "naptr-record", 1, 0, LOPT_NAPTR },
|
||||
@@ -270,6 +277,7 @@ static const struct myoption opts[] =
|
||||
{ "dhcp-alternate-port", 2, 0, LOPT_ALTPORT },
|
||||
{ "dhcp-scriptuser", 1, 0, LOPT_SCRIPTUSR },
|
||||
{ "min-port", 1, 0, LOPT_MINPORT },
|
||||
{ "max-port", 1, 0, LOPT_MAXPORT },
|
||||
{ "dhcp-fqdn", 0, 0, LOPT_DHCP_FQDN },
|
||||
{ "cname", 1, 0, LOPT_CNAME },
|
||||
{ "pxe-prompt", 1, 0, LOPT_PXE_PROMT },
|
||||
@@ -279,8 +287,9 @@ static const struct myoption opts[] =
|
||||
{ "dhcp-proxy", 2, 0, LOPT_PROXY },
|
||||
{ "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
|
||||
{ "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
|
||||
{ "add-mac", 0, 0, LOPT_ADD_MAC },
|
||||
{ "add-mac", 2, 0, LOPT_ADD_MAC },
|
||||
{ "add-subnet", 2, 0, LOPT_ADD_SBNET },
|
||||
{ "add-cpe-id", 1, 0 , LOPT_CPE_ID },
|
||||
{ "proxy-dnssec", 0, 0, LOPT_DNSSEC },
|
||||
{ "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
|
||||
{ "conntrack", 0, 0, LOPT_CONNTRACK },
|
||||
@@ -313,6 +322,9 @@ static const struct myoption opts[] =
|
||||
{ "quiet-dhcp6", 0, 0, LOPT_QUIET_DHCP6 },
|
||||
{ "quiet-ra", 0, 0, LOPT_QUIET_RA },
|
||||
{ "dns-loop-detect", 0, 0, LOPT_LOOP_DETECT },
|
||||
{ "script-arp", 0, 0, LOPT_SCRIPT_ARP },
|
||||
{ "dhcp-ttl", 1, 0 , LOPT_DHCPTTL },
|
||||
{ "dhcp-reply-delay", 1, 0, LOPT_REPLY_DELAY },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
|
||||
@@ -392,7 +404,7 @@ static struct {
|
||||
{ 'v', 0, NULL, gettext_noop("Display dnsmasq version and copyright information."), NULL },
|
||||
{ 'V', ARG_DUP, "<ipaddr>,<ipaddr>,<netmask>", gettext_noop("Translate IPv4 addresses from upstream servers."), NULL },
|
||||
{ 'W', ARG_DUP, "<name>,<target>,...", gettext_noop("Specify a SRV record."), NULL },
|
||||
{ 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp for known DHCP options."), NULL },
|
||||
{ 'w', 0, NULL, gettext_noop("Display this message. Use --help dhcp or --help dhcp6 for known DHCP options."), NULL },
|
||||
{ 'x', ARG_ONE, "<path>", gettext_noop("Specify path of PID file (defaults to %s)."), RUNFILE },
|
||||
{ 'X', ARG_ONE, "<integer>", gettext_noop("Specify maximum number of DHCP leases (defaults to %s)."), "&" },
|
||||
{ 'y', OPT_LOCALISE, NULL, gettext_noop("Answer DNS queries based on the interface a query was sent to."), NULL },
|
||||
@@ -410,8 +422,9 @@ static struct {
|
||||
{ '6', ARG_ONE, "<path>", gettext_noop("Shell script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ LOPT_LUASCRIPT, ARG_DUP, "path", gettext_noop("Lua script to run on DHCP lease creation and destruction."), NULL },
|
||||
{ LOPT_SCRIPTUSR, ARG_ONE, "<username>", gettext_noop("Run lease-change scripts as this user."), NULL },
|
||||
{ LOPT_SCRIPT_ARP, OPT_SCRIPT_ARP, NULL, gettext_noop("Call dhcp-script with changes to local ARP table."), NULL },
|
||||
{ '7', ARG_DUP, "<path>", gettext_noop("Read configuration from all the files in this directory."), NULL },
|
||||
{ '8', ARG_ONE, "<facilty>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
|
||||
{ '8', ARG_ONE, "<facility>|<file>", gettext_noop("Log to this syslog facility or file. (defaults to DAEMON)"), NULL },
|
||||
{ '9', OPT_LEASE_RO, NULL, gettext_noop("Do not use leasefile."), NULL },
|
||||
{ '0', ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent DNS queries. (defaults to %s)"), "!" },
|
||||
{ LOPT_RELOAD, OPT_RELOAD, NULL, gettext_noop("Clear DNS cache when reloading %s."), RESOLVFILE },
|
||||
@@ -419,10 +432,11 @@ static struct {
|
||||
{ LOPT_OVERRIDE, OPT_NO_OVERRIDE, NULL, gettext_noop("Do NOT reuse filename and server fields for extra DHCP options."), NULL },
|
||||
{ LOPT_TFTP, ARG_DUP, "[=<intr>[,<intr>]]", gettext_noop("Enable integrated read-only TFTP server."), NULL },
|
||||
{ LOPT_PREFIX, ARG_DUP, "<dir>[,<iface>]", gettext_noop("Export files by TFTP only from the specified subtree."), NULL },
|
||||
{ LOPT_APREF, OPT_TFTP_APREF, NULL, gettext_noop("Add client IP address to tftp-root."), NULL },
|
||||
{ LOPT_APREF, ARG_DUP, "[=ip|mac]", gettext_noop("Add client IP or hardware address to tftp-root."), NULL },
|
||||
{ LOPT_SECURE, OPT_TFTP_SECURE, NULL, gettext_noop("Allow access only to files owned by the user running dnsmasq."), NULL },
|
||||
{ LOPT_TFTP_NO_FAIL, OPT_TFTP_NO_FAIL, NULL, gettext_noop("Do not terminate the service if TFTP directories are inaccessible."), NULL },
|
||||
{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of conncurrent TFTP transfers (defaults to %s)."), "#" },
|
||||
{ LOPT_TFTP_MAX, ARG_ONE, "<integer>", gettext_noop("Maximum number of concurrent TFTP transfers (defaults to %s)."), "#" },
|
||||
{ LOPT_TFTP_MTU, ARG_ONE, "<integer>", gettext_noop("Maximum MTU to use for TFTP transfers."), NULL },
|
||||
{ LOPT_NOBLOCK, OPT_TFTP_NOBLOCK, NULL, gettext_noop("Disable the TFTP blocksize extension."), NULL },
|
||||
{ LOPT_TFTP_LC, OPT_TFTP_LC, NULL, gettext_noop("Convert TFTP filenames to lowercase"), NULL },
|
||||
{ LOPT_TFTPPORTS, ARG_ONE, "<start>,<end>", gettext_noop("Ephemeral port range for use by TFTP transfers."), NULL },
|
||||
@@ -436,32 +450,34 @@ static struct {
|
||||
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
|
||||
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
|
||||
{ LOPT_MAXPORT, ARG_ONE, "<port>", gettext_noop("Specify highest port available for DNS query transmission."), NULL },
|
||||
{ LOPT_DHCP_FQDN, OPT_DHCP_FQDN, NULL, gettext_noop("Use only fully qualified domain names for DHCP clients."), NULL },
|
||||
{ LOPT_GEN_NAMES, ARG_DUP, "[=tag:<tag>]", gettext_noop("Generate hostnames based on MAC address for nameless clients."), NULL},
|
||||
{ LOPT_PROXY, ARG_DUP, "[=<ipaddr>]...", gettext_noop("Use these DHCP relays as full proxies."), NULL },
|
||||
{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<interface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
|
||||
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
|
||||
{ LOPT_RELAY, ARG_DUP, "<local-addr>,<server>[,<iface>]", gettext_noop("Relay DHCP requests to a remote server"), NULL},
|
||||
{ LOPT_CNAME, ARG_DUP, "<alias>,<target>[,<ttl>]", gettext_noop("Specify alias name for LOCAL DNS name."), NULL },
|
||||
{ LOPT_PXE_PROMT, ARG_DUP, "<prompt>,[<timeout>]", gettext_noop("Prompt to send to PXE clients."), NULL },
|
||||
{ LOPT_PXE_SERV, ARG_DUP, "<service>", gettext_noop("Boot service for PXE menu."), NULL },
|
||||
{ LOPT_TEST, 0, NULL, gettext_noop("Check configuration syntax."), NULL },
|
||||
{ LOPT_ADD_MAC, OPT_ADD_MAC, NULL, gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
|
||||
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add requestor's IP subnet to forwarded DNS queries."), NULL },
|
||||
{ LOPT_ADD_MAC, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
|
||||
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
|
||||
{ LOPT_CPE_ID, ARG_ONE, "<text>", gettext_noop("Add client identification to forwarded DNS queries."), NULL },
|
||||
{ LOPT_DNSSEC, OPT_DNSSEC_PROXY, NULL, gettext_noop("Proxy DNSSEC validation results from upstream nameservers."), NULL },
|
||||
{ LOPT_INCR_ADDR, OPT_CONSEC_ADDR, NULL, gettext_noop("Attempt to allocate sequential IP addresses to DHCP clients."), NULL },
|
||||
{ LOPT_CONNTRACK, OPT_CONNTRACK, NULL, gettext_noop("Copy connection-track mark from queries to upstream connections."), NULL },
|
||||
{ LOPT_FQDN, OPT_FQDN_UPDATE, NULL, gettext_noop("Allow DHCP clients to do their own DDNS updates."), NULL },
|
||||
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
|
||||
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
|
||||
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
||||
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
||||
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
|
||||
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
|
||||
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
|
||||
{ LOPT_AUTHZONE, ARG_DUP, "<domain>,[<subnet>...]", gettext_noop("Domain to export to global DNS"), NULL },
|
||||
{ LOPT_AUTHTTL, ARG_ONE, "<integer>", gettext_noop("Set TTL for authoritative replies"), NULL },
|
||||
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritive zone information"), NULL },
|
||||
{ LOPT_AUTHSOA, ARG_ONE, "<serial>[,...]", gettext_noop("Set authoritative zone information"), NULL },
|
||||
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
||||
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
|
||||
{ LOPT_IPSET, ARG_DUP, "/<domain>/<ipset>[,<ipset>...]", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
||||
{ LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
||||
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
|
||||
{ LOPT_SEC_VALID, OPT_DNSSEC_VALID, NULL, gettext_noop("Activate DNSSEC validation"), NULL },
|
||||
{ LOPT_TRUST_ANCHOR, ARG_DUP, "<domain>,[<class>],...", gettext_noop("Specify trust anchor key digest."), NULL },
|
||||
@@ -472,17 +488,19 @@ static struct {
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
{ LOPT_PREF_CLSS, ARG_DUP, "set:tag,<class>", gettext_noop("Specify DHCPv6 prefix class"), NULL },
|
||||
#endif
|
||||
{ LOPT_RA_PARAM, ARG_DUP, "<interface>,[high,|low,]<interval>[,<lifetime>]", gettext_noop("Set priority, resend-interval and router-lifetime"), NULL },
|
||||
{ LOPT_RA_PARAM, ARG_DUP, "<iface>,[mtu:<value>|<interface>|off,][<prio>,]<intval>[,<lifetime>]", gettext_noop("Set MTU, priority, resend-interval and router-lifetime"), NULL },
|
||||
{ LOPT_QUIET_DHCP, OPT_QUIET_DHCP, NULL, gettext_noop("Do not log routine DHCP."), NULL },
|
||||
{ LOPT_QUIET_DHCP6, OPT_QUIET_DHCP6, NULL, gettext_noop("Do not log routine DHCPv6."), NULL },
|
||||
{ LOPT_QUIET_RA, OPT_QUIET_RA, NULL, gettext_noop("Do not log RA."), NULL },
|
||||
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks"), NULL },
|
||||
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops"), NULL },
|
||||
{ LOPT_LOCAL_SERVICE, OPT_LOCAL_SERVICE, NULL, gettext_noop("Accept queries only from directly-connected networks."), NULL },
|
||||
{ LOPT_LOOP_DETECT, OPT_LOOP_DETECT, NULL, gettext_noop("Detect and remove DNS forwarding loops."), NULL },
|
||||
{ LOPT_IGNORE_ADDR, ARG_DUP, "<ipaddr>", gettext_noop("Ignore DNS responses containing ipaddr."), NULL },
|
||||
{ LOPT_DHCPTTL, ARG_ONE, "<ttl>", gettext_noop("Set TTL in DNS responses with DHCP-derived addresses."), NULL },
|
||||
{ LOPT_REPLY_DELAY, ARG_ONE, "<integer>", gettext_noop("Delay DHCP replies for at least number of seconds."), NULL },
|
||||
{ 0, 0, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
/* We hide metacharaters in quoted strings by mapping them into the ASCII control
|
||||
/* We hide metacharacters in quoted strings by mapping them into the ASCII control
|
||||
character space. Note that the \0, \t \b \r \033 and \n characters are carefully placed in the
|
||||
following sequence so that they map to themselves: it is therefore possible to call
|
||||
unhide_metas repeatedly on string without breaking things.
|
||||
@@ -642,7 +660,8 @@ static int atoi_check8(char *a, int *res)
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef NO_ID
|
||||
static void add_txt(char *name, char *txt, int stat)
|
||||
{
|
||||
struct txt_record *r = opt_malloc(sizeof(struct txt_record));
|
||||
@@ -655,13 +674,14 @@ static void add_txt(char *name, char *txt, int stat)
|
||||
*(r->txt) = len;
|
||||
memcpy((r->txt)+1, txt, len);
|
||||
}
|
||||
|
||||
|
||||
r->stat = stat;
|
||||
r->name = opt_string_alloc(name);
|
||||
r->next = daemon->txt;
|
||||
daemon->txt = r;
|
||||
r->class = C_CHAOS;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_usage(void)
|
||||
{
|
||||
@@ -706,7 +726,7 @@ static void do_usage(void)
|
||||
sprintf(buff, " ");
|
||||
|
||||
sprintf(buff+4, "--%s%s%s", opts[j].name, eq, desc);
|
||||
printf("%-40.40s", buff);
|
||||
printf("%-55.55s", buff);
|
||||
|
||||
if (usage[i].arg)
|
||||
{
|
||||
@@ -722,10 +742,25 @@ static void do_usage(void)
|
||||
|
||||
#define ret_err(x) do { strcpy(errstr, (x)); return 0; } while (0)
|
||||
|
||||
static char *parse_mysockaddr(char *arg, union mysockaddr *addr)
|
||||
{
|
||||
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
|
||||
addr->sa.sa_family = AF_INET;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &addr->in6.sin6_addr) > 0)
|
||||
addr->sa.sa_family = AF_INET6;
|
||||
#endif
|
||||
else
|
||||
return _("bad address");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_addr, char *interface, int *flags)
|
||||
{
|
||||
int source_port = 0, serv_port = NAMESERVER_PORT;
|
||||
char *portno, *source;
|
||||
char *interface_opt = NULL;
|
||||
#ifdef HAVE_IPV6
|
||||
int scope_index = 0;
|
||||
char *scope_id;
|
||||
@@ -751,6 +786,19 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
scope_id = split_chr(arg, '%');
|
||||
#endif
|
||||
|
||||
if (source) {
|
||||
interface_opt = split_chr(source, '@');
|
||||
|
||||
if (interface_opt)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
strncpy(interface, interface_opt, IF_NAMESIZE - 1);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, arg, &addr->in.sin_addr) > 0)
|
||||
{
|
||||
addr->in.sin_port = htons(serv_port);
|
||||
@@ -769,6 +817,9 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
if (!(inet_pton(AF_INET, source, &source_addr->in.sin_addr) > 0))
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
if (interface_opt)
|
||||
return _("interface can only be specified once");
|
||||
|
||||
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
@@ -801,7 +852,10 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
if (inet_pton(AF_INET6, source, &source_addr->in6.sin6_addr) == 0)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
source_addr->in6.sin6_addr = in6addr_any;
|
||||
if (interface_opt)
|
||||
return _("interface can only be specified once");
|
||||
|
||||
source_addr->in6.sin6_addr = in6addr_any;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
@@ -819,19 +873,31 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
static struct server *add_rev4(struct in_addr addr, int msize)
|
||||
{
|
||||
struct server *serv = opt_malloc(sizeof(struct server));
|
||||
in_addr_t a = ntohl(addr.s_addr) >> 8;
|
||||
in_addr_t a = ntohl(addr.s_addr);
|
||||
char *p;
|
||||
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
p = serv->domain = opt_malloc(25); /* strlen("xxx.yyy.zzz.in-addr.arpa")+1 */
|
||||
|
||||
if (msize == 24)
|
||||
p += sprintf(p, "%d.", a & 0xff);
|
||||
a = a >> 8;
|
||||
if (msize != 8)
|
||||
p += sprintf(p, "%d.", a & 0xff);
|
||||
a = a >> 8;
|
||||
p += sprintf(p, "%d.in-addr.arpa", a & 0xff);
|
||||
p = serv->domain = opt_malloc(29); /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
|
||||
|
||||
switch (msize)
|
||||
{
|
||||
case 32:
|
||||
p += sprintf(p, "%u.", a & 0xff);
|
||||
/* fall through */
|
||||
case 24:
|
||||
p += sprintf(p, "%d.", (a >> 8) & 0xff);
|
||||
/* fall through */
|
||||
case 16:
|
||||
p += sprintf(p, "%d.", (a >> 16) & 0xff);
|
||||
/* fall through */
|
||||
case 8:
|
||||
p += sprintf(p, "%d.", (a >> 24) & 0xff);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p += sprintf(p, "in-addr.arpa");
|
||||
|
||||
serv->flags = SERV_HAS_DOMAIN;
|
||||
serv->next = daemon->servers;
|
||||
@@ -1170,7 +1236,8 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
cp = comma;
|
||||
comma = split(cp);
|
||||
slash = split_chr(cp, '/');
|
||||
inet_pton(AF_INET, cp, &in);
|
||||
if (!inet_pton(AF_INET, cp, &in))
|
||||
ret_err(_("bad IPv4 address"));
|
||||
if (!slash)
|
||||
{
|
||||
memcpy(op, &in, INADDRSZ);
|
||||
@@ -1348,7 +1415,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
|
||||
}
|
||||
|
||||
p = newp;
|
||||
end = do_rfc1035_name(p + len, dom);
|
||||
end = do_rfc1035_name(p + len, dom, NULL);
|
||||
*end++ = 0;
|
||||
len = end - p;
|
||||
free(dom);
|
||||
@@ -1501,10 +1568,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
li = opt_malloc(sizeof(struct list));
|
||||
if (*arg == '*')
|
||||
{
|
||||
li->next = match_suffix;
|
||||
match_suffix = li;
|
||||
/* Have to copy: buffer is overwritten */
|
||||
li->suffix = opt_string_alloc(arg+1);
|
||||
/* "*" with no suffix is a no-op */
|
||||
if (arg[1] == 0)
|
||||
free(li);
|
||||
else
|
||||
{
|
||||
li->next = match_suffix;
|
||||
match_suffix = li;
|
||||
/* Have to copy: buffer is overwritten */
|
||||
li->suffix = opt_string_alloc(arg+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1585,7 +1658,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
li = match_suffix->next;
|
||||
free(match_suffix->suffix);
|
||||
free(match_suffix);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1593,10 +1666,46 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
set_option_bool(OPT_CLIENT_SUBNET);
|
||||
if (arg)
|
||||
{
|
||||
char *err, *end;
|
||||
comma = split(arg);
|
||||
if (!atoi_check(arg, &daemon->addr4_netmask) ||
|
||||
(comma && !atoi_check(comma, &daemon->addr6_netmask)))
|
||||
ret_err(gen_err);
|
||||
|
||||
struct mysubnet* new = opt_malloc(sizeof(struct mysubnet));
|
||||
if ((end = split_chr(arg, '/')))
|
||||
{
|
||||
/* has subnet+len */
|
||||
err = parse_mysockaddr(arg, &new->addr);
|
||||
if (err)
|
||||
ret_err(err);
|
||||
if (!atoi_check(end, &new->mask))
|
||||
ret_err(gen_err);
|
||||
new->addr_used = 1;
|
||||
}
|
||||
else if (!atoi_check(arg, &new->mask))
|
||||
ret_err(gen_err);
|
||||
|
||||
daemon->add_subnet4 = new;
|
||||
|
||||
if (comma)
|
||||
{
|
||||
new = opt_malloc(sizeof(struct mysubnet));
|
||||
if ((end = split_chr(comma, '/')))
|
||||
{
|
||||
/* has subnet+len */
|
||||
err = parse_mysockaddr(comma, &new->addr);
|
||||
if (err)
|
||||
ret_err(err);
|
||||
if (!atoi_check(end, &new->mask))
|
||||
ret_err(gen_err);
|
||||
new->addr_used = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!atoi_check(comma, &new->mask))
|
||||
ret_err(gen_err);
|
||||
}
|
||||
|
||||
daemon->add_subnet6 = new;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1834,6 +1943,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
new = opt_malloc(sizeof(struct auth_zone));
|
||||
new->domain = opt_string_alloc(arg);
|
||||
new->subnet = NULL;
|
||||
new->exclude = NULL;
|
||||
new->interface_names = NULL;
|
||||
new->next = daemon->auth_zones;
|
||||
daemon->auth_zones = new;
|
||||
@@ -1841,6 +1951,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
while ((arg = comma))
|
||||
{
|
||||
int prefixlen = 0;
|
||||
int is_exclude = 0;
|
||||
char *prefix;
|
||||
struct addrlist *subnet = NULL;
|
||||
struct all_addr addr;
|
||||
@@ -1851,6 +1962,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
if (prefix && !atoi_check(prefix, &prefixlen))
|
||||
ret_err(gen_err);
|
||||
|
||||
if (strstr(arg, "exclude:") == arg)
|
||||
{
|
||||
is_exclude = 1;
|
||||
arg = arg+8;
|
||||
}
|
||||
|
||||
if (inet_pton(AF_INET, arg, &addr.addr.addr4))
|
||||
{
|
||||
subnet = opt_malloc(sizeof(struct addrlist));
|
||||
@@ -1888,8 +2005,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
if (subnet)
|
||||
{
|
||||
subnet->addr = addr;
|
||||
subnet->next = new->subnet;
|
||||
new->subnet = subnet;
|
||||
|
||||
if (is_exclude)
|
||||
{
|
||||
subnet->next = new->exclude;
|
||||
new->exclude = subnet;
|
||||
}
|
||||
else
|
||||
{
|
||||
subnet->next = new->subnet;
|
||||
new->subnet = subnet;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1919,11 +2045,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
comma = split(arg);
|
||||
daemon->soa_retry = (u32)atoi(arg);
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
daemon->soa_expiry = (u32)atoi(arg);
|
||||
}
|
||||
daemon->soa_expiry = (u32)atoi(comma);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1980,6 +2102,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
/* generate the equivalent of
|
||||
local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||
struct server *serv = add_rev4(new->start, msize);
|
||||
if (!serv)
|
||||
ret_err(_("bad prefix"));
|
||||
|
||||
serv->flags |= SERV_NO_ADDR;
|
||||
|
||||
/* local=/<domain>/ */
|
||||
@@ -2095,6 +2220,26 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
break;
|
||||
|
||||
case LOPT_CPE_ID: /* --add-dns-client */
|
||||
if (arg)
|
||||
daemon->dns_client_id = opt_string_alloc(arg);
|
||||
break;
|
||||
|
||||
case LOPT_ADD_MAC: /* --add-mac */
|
||||
if (!arg)
|
||||
set_option_bool(OPT_ADD_MAC);
|
||||
else
|
||||
{
|
||||
unhide_metas(arg);
|
||||
if (strcmp(arg, "base64") == 0)
|
||||
set_option_bool(OPT_MAC_B64);
|
||||
else if (strcmp(arg, "text") == 0)
|
||||
set_option_bool(OPT_MAC_HEX);
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'u': /* --user */
|
||||
daemon->username = opt_string_alloc(arg);
|
||||
break;
|
||||
@@ -2331,7 +2476,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
ret_err(gen_err);
|
||||
|
||||
if (inet_pton(AF_INET, arg, &addr4))
|
||||
serv = add_rev4(addr4, size);
|
||||
{
|
||||
serv = add_rev4(addr4, size);
|
||||
if (!serv)
|
||||
ret_err(_("bad prefix"));
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &addr6))
|
||||
serv = add_rev6(&addr6, size);
|
||||
@@ -2448,6 +2597,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case LOPT_MAXPORT: /* --max-port */
|
||||
if (!atoi_check16(arg, &daemon->max_port))
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case '0': /* --dns-forward-max */
|
||||
if (!atoi_check(arg, &daemon->ftabsize))
|
||||
ret_err(gen_err);
|
||||
@@ -2491,6 +2645,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
case LOPT_MINCTTL: /* --min-cache-ttl */
|
||||
case LOPT_MAXCTTL: /* --max-cache-ttl */
|
||||
case LOPT_AUTHTTL: /* --auth-ttl */
|
||||
case LOPT_DHCPTTL: /* --dhcp-ttl */
|
||||
{
|
||||
int ttl;
|
||||
if (!atoi_check(arg, &ttl))
|
||||
@@ -2509,6 +2664,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
daemon->max_cache_ttl = (unsigned long)ttl;
|
||||
else if (option == LOPT_AUTHTTL)
|
||||
daemon->auth_ttl = (unsigned long)ttl;
|
||||
else if (option == LOPT_DHCPTTL)
|
||||
{
|
||||
daemon->dhcp_ttl = (unsigned long)ttl;
|
||||
daemon->use_dhcp_ttl = 1;
|
||||
}
|
||||
else
|
||||
daemon->local_ttl = (unsigned long)ttl;
|
||||
break;
|
||||
@@ -2527,6 +2687,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case LOPT_TFTP_MTU: /* --tftp-mtu */
|
||||
if (!atoi_check(arg, &daemon->tftp_mtu))
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
|
||||
case LOPT_PREFIX: /* --tftp-prefix */
|
||||
comma = split(arg);
|
||||
if (comma)
|
||||
@@ -2555,6 +2720,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LOPT_APREF: /* --tftp-unique-root */
|
||||
if (!arg || strcasecmp(arg, "ip") == 0)
|
||||
set_option_bool(OPT_TFTP_APREF_IP);
|
||||
else if (strcasecmp(arg, "mac") == 0)
|
||||
set_option_bool(OPT_TFTP_APREF_MAC);
|
||||
else
|
||||
ret_err(gen_err);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case LOPT_BRIDGE: /* --bridge-interface */
|
||||
@@ -2669,13 +2843,14 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
leasepos = 3;
|
||||
if (!is_same_net(new->start, new->end, new->netmask))
|
||||
ret_err(_("inconsistent DHCP range"));
|
||||
}
|
||||
|
||||
|
||||
if (k >= 4 && strchr(a[3], '.') &&
|
||||
(inet_pton(AF_INET, a[3], &new->broadcast) > 0))
|
||||
{
|
||||
new->flags |= CONTEXT_BRDCAST;
|
||||
leasepos = 4;
|
||||
if (k >= 4 && strchr(a[3], '.') &&
|
||||
(inet_pton(AF_INET, a[3], &new->broadcast) > 0))
|
||||
{
|
||||
new->flags |= CONTEXT_BRDCAST;
|
||||
leasepos = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
@@ -2765,6 +2940,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
|
||||
if (leasepos < k)
|
||||
{
|
||||
if (leasepos != k-1)
|
||||
ret_err(_("bad dhcp-range"));
|
||||
|
||||
if (strcmp(a[leasepos], "infinite") == 0)
|
||||
new->lease_time = 0xffffffff;
|
||||
else if (strcmp(a[leasepos], "deprecated") == 0)
|
||||
@@ -2859,7 +3037,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
|
||||
if (len == -1)
|
||||
|
||||
ret_err(_("bad hex constant"));
|
||||
else if ((new->clid = opt_malloc(len)))
|
||||
{
|
||||
@@ -3143,11 +3320,43 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_REPLY_DELAY: /* --dhcp-reply-delay */
|
||||
{
|
||||
struct dhcp_netid *id = NULL;
|
||||
while (is_tag_prefix(arg))
|
||||
{
|
||||
struct dhcp_netid *newid = opt_malloc(sizeof(struct dhcp_netid));
|
||||
newid->next = id;
|
||||
id = newid;
|
||||
comma = split(arg);
|
||||
newid->net = opt_string_alloc(arg+4);
|
||||
arg = comma;
|
||||
};
|
||||
|
||||
if (!arg)
|
||||
ret_err(gen_err);
|
||||
else
|
||||
{
|
||||
struct delay_config *new;
|
||||
int delay;
|
||||
if (!atoi_check(arg, &delay))
|
||||
ret_err(gen_err);
|
||||
|
||||
new = opt_malloc(sizeof(struct delay_config));
|
||||
new->delay = delay;
|
||||
new->netid = id;
|
||||
new->next = daemon->delay_conf;
|
||||
daemon->delay_conf = new;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_PXE_PROMT: /* --pxe-prompt */
|
||||
{
|
||||
struct dhcp_opt *new = opt_malloc(sizeof(struct dhcp_opt));
|
||||
int timeout;
|
||||
|
||||
|
||||
new->netid = NULL;
|
||||
new->opt = 10; /* PXE_MENU_PROMPT */
|
||||
|
||||
@@ -3191,7 +3400,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
{
|
||||
struct pxe_service *new = opt_malloc(sizeof(struct pxe_service));
|
||||
char *CSA[] = { "x86PC", "PC98", "IA64_EFI", "Alpha", "Arc_x86", "Intel_Lean_Client",
|
||||
"IA32_EFI", "BC_EFI", "Xscale_EFI", "x86-64_EFI", NULL };
|
||||
"IA32_EFI", "x86-64_EFI", "Xscale_EFI", "BC_EFI",
|
||||
"ARM32_EFI", "ARM64_EFI", NULL };
|
||||
static int boottype = 32768;
|
||||
|
||||
new->netid = NULL;
|
||||
@@ -3496,7 +3706,21 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
struct ra_interface *new = opt_malloc(sizeof(struct ra_interface));
|
||||
new->lifetime = -1;
|
||||
new->prio = 0;
|
||||
new->mtu = 0;
|
||||
new->mtu_name = NULL;
|
||||
new->name = opt_string_alloc(arg);
|
||||
if (strcasestr(comma, "mtu:") == comma)
|
||||
{
|
||||
arg = comma + 4;
|
||||
if (!(comma = split(comma)))
|
||||
goto err;
|
||||
if (!strcasecmp(arg, "off"))
|
||||
new->mtu = -1;
|
||||
else if (!atoi_check(arg, &new->mtu))
|
||||
new->mtu_name = opt_string_alloc(arg);
|
||||
else if (new->mtu < 1280)
|
||||
goto err;
|
||||
}
|
||||
if (strcasestr(comma, "high") == comma || strcasestr(comma, "low") == comma)
|
||||
{
|
||||
if (*comma == 'l' || *comma == 'L')
|
||||
@@ -3508,6 +3732,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
arg = split(comma);
|
||||
if (!atoi_check(comma, &new->interval) ||
|
||||
(arg && !atoi_check(arg, &new->lifetime)))
|
||||
err:
|
||||
ret_err(_("bad RA-params"));
|
||||
|
||||
new->next = daemon->ra_interfaces;
|
||||
@@ -3552,8 +3777,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
(!(inet_pton(AF_INET, a[1], &new->out) > 0)))
|
||||
option = '?';
|
||||
|
||||
if (k == 3)
|
||||
inet_pton(AF_INET, a[2], &new->mask);
|
||||
if (k == 3 && !inet_pton(AF_INET, a[2], &new->mask))
|
||||
option = '?';
|
||||
|
||||
if (dash &&
|
||||
(!(inet_pton(AF_INET, dash, &new->end) > 0) ||
|
||||
@@ -3603,27 +3828,41 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
case LOPT_CNAME: /* --cname */
|
||||
{
|
||||
struct cname *new;
|
||||
char *alias;
|
||||
char *target;
|
||||
char *alias, *target, *last, *pen;
|
||||
int ttl = -1;
|
||||
|
||||
if (!(comma = split(arg)))
|
||||
ret_err(gen_err);
|
||||
|
||||
alias = canonicalise_opt(arg);
|
||||
target = canonicalise_opt(comma);
|
||||
|
||||
if (!alias || !target)
|
||||
ret_err(_("bad CNAME"));
|
||||
else
|
||||
for (last = pen = NULL, comma = arg; comma; comma = split(comma))
|
||||
{
|
||||
pen = last;
|
||||
last = comma;
|
||||
}
|
||||
|
||||
if (!pen)
|
||||
ret_err(_("bad CNAME"));
|
||||
|
||||
if (pen != arg && atoi_check(last, &ttl))
|
||||
last = pen;
|
||||
|
||||
target = canonicalise_opt(last);
|
||||
|
||||
while (arg != last)
|
||||
{
|
||||
alias = canonicalise_opt(arg);
|
||||
|
||||
if (!alias || !target)
|
||||
ret_err(_("bad CNAME"));
|
||||
|
||||
for (new = daemon->cnames; new; new = new->next)
|
||||
if (hostname_isequal(new->alias, arg))
|
||||
if (hostname_isequal(new->alias, alias))
|
||||
ret_err(_("duplicate CNAME"));
|
||||
new = opt_malloc(sizeof(struct cname));
|
||||
new->next = daemon->cnames;
|
||||
daemon->cnames = new;
|
||||
new->alias = alias;
|
||||
new->target = target;
|
||||
new->ttl = ttl;
|
||||
|
||||
arg += strlen(arg)+1;
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -3689,7 +3928,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
case LOPT_RR: /* dns-rr */
|
||||
{
|
||||
struct txt_record *new;
|
||||
size_t len = len;
|
||||
size_t len = 0;
|
||||
char *data;
|
||||
int val;
|
||||
|
||||
@@ -3797,13 +4036,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
if (!atoi_check16(arg, &priority))
|
||||
ret_err(_("invalid priority"));
|
||||
|
||||
if (comma)
|
||||
{
|
||||
arg = comma;
|
||||
comma = split(arg);
|
||||
if (!atoi_check16(arg, &weight))
|
||||
ret_err(_("invalid weight"));
|
||||
}
|
||||
if (comma && !atoi_check16(comma, &weight))
|
||||
ret_err(_("invalid weight"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3824,14 +4058,22 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
{
|
||||
struct host_record *new = opt_malloc(sizeof(struct host_record));
|
||||
memset(new, 0, sizeof(struct host_record));
|
||||
|
||||
new->ttl = -1;
|
||||
|
||||
if (!arg || !(comma = split(arg)))
|
||||
ret_err(_("Bad host-record"));
|
||||
|
||||
while (arg)
|
||||
{
|
||||
struct all_addr addr;
|
||||
if (inet_pton(AF_INET, arg, &addr))
|
||||
char *dig;
|
||||
|
||||
for (dig = arg; *dig != 0; dig++)
|
||||
if (*dig < '0' || *dig > '9')
|
||||
break;
|
||||
if (*dig == 0)
|
||||
new->ttl = atoi(arg);
|
||||
else if (inet_pton(AF_INET, arg, &addr))
|
||||
new->addr = addr.addr.addr4;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &addr))
|
||||
@@ -3948,7 +4190,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
{
|
||||
int white, i;
|
||||
volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
|
||||
char *errmess, *p, *arg = NULL, *start;
|
||||
char *errmess, *p, *arg, *start;
|
||||
size_t len;
|
||||
|
||||
/* Memory allocation failure longjmps here if mem_recover == 1 */
|
||||
@@ -3959,6 +4201,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
mem_recover = 1;
|
||||
}
|
||||
|
||||
arg = NULL;
|
||||
lineno++;
|
||||
errmess = NULL;
|
||||
|
||||
@@ -4398,7 +4641,9 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
daemon->soa_refresh = SOA_REFRESH;
|
||||
daemon->soa_retry = SOA_RETRY;
|
||||
daemon->soa_expiry = SOA_EXPIRY;
|
||||
daemon->max_port = MAX_PORT;
|
||||
|
||||
#ifndef NO_ID
|
||||
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
|
||||
add_txt("authors.bind", "Simon Kelley", 0);
|
||||
add_txt("copyright.bind", COPYRIGHT, 0);
|
||||
@@ -4411,6 +4656,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
add_txt("auth.bind", NULL, TXT_STAT_AUTH);
|
||||
#endif
|
||||
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -4497,21 +4743,68 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
{
|
||||
struct server *tmp;
|
||||
for (tmp = daemon->servers; tmp; tmp = tmp->next)
|
||||
{
|
||||
tmp->edns_pktsz = daemon->edns_pktsz;
|
||||
|
||||
if (!(tmp->flags & SERV_HAS_SOURCE))
|
||||
{
|
||||
if (tmp->source_addr.sa.sa_family == AF_INET)
|
||||
tmp->source_addr.in.sin_port = htons(daemon->query_port);
|
||||
if (!(tmp->flags & SERV_HAS_SOURCE))
|
||||
{
|
||||
if (tmp->source_addr.sa.sa_family == AF_INET)
|
||||
tmp->source_addr.in.sin_port = htons(daemon->query_port);
|
||||
#ifdef HAVE_IPV6
|
||||
else if (tmp->source_addr.sa.sa_family == AF_INET6)
|
||||
tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
else if (tmp->source_addr.sa.sa_family == AF_INET6)
|
||||
tmp->source_addr.in6.sin6_port = htons(daemon->query_port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon->host_records)
|
||||
{
|
||||
struct host_record *hr;
|
||||
|
||||
for (hr = daemon->host_records; hr; hr = hr->next)
|
||||
if (hr->ttl == -1)
|
||||
hr->ttl = daemon->local_ttl;
|
||||
}
|
||||
|
||||
if (daemon->cnames)
|
||||
{
|
||||
struct cname *cn, *cn2, *cn3;
|
||||
|
||||
#define NOLOOP 1
|
||||
#define TESTLOOP 2
|
||||
|
||||
/* Fill in TTL for CNAMES noe we have local_ttl.
|
||||
Also prepare to do loop detection. */
|
||||
for (cn = daemon->cnames; cn; cn = cn->next)
|
||||
{
|
||||
if (cn->ttl == -1)
|
||||
cn->ttl = daemon->local_ttl;
|
||||
cn->flag = 0;
|
||||
cn->targetp = NULL;
|
||||
for (cn2 = daemon->cnames; cn2; cn2 = cn2->next)
|
||||
if (hostname_isequal(cn->target, cn2->alias))
|
||||
{
|
||||
cn->targetp = cn2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find any CNAME loops.*/
|
||||
for (cn = daemon->cnames; cn; cn = cn->next)
|
||||
{
|
||||
for (cn2 = cn->targetp; cn2; cn2 = cn2->targetp)
|
||||
{
|
||||
if (cn2->flag == NOLOOP)
|
||||
break;
|
||||
|
||||
if (cn2->flag == TESTLOOP)
|
||||
die(_("CNAME loop involving %s"), cn->alias, EC_BADCONF);
|
||||
|
||||
cn2->flag = TESTLOOP;
|
||||
}
|
||||
|
||||
for (cn3 = cn->targetp; cn3 != cn2; cn3 = cn3->targetp)
|
||||
cn3->flag = NOLOOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (daemon->if_addrs)
|
||||
{
|
||||
struct iname *tmp;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,9 +29,19 @@ void end_opt6(int container)
|
||||
PUTSHORT(len, p);
|
||||
}
|
||||
|
||||
void reset_counter(void)
|
||||
{
|
||||
/* Clear out buffer when starting from beginning */
|
||||
if (daemon->outpacket.iov_base)
|
||||
memset(daemon->outpacket.iov_base, 0, daemon->outpacket.iov_len);
|
||||
|
||||
save_counter(0);
|
||||
}
|
||||
|
||||
int save_counter(int newval)
|
||||
{
|
||||
int ret = outpacket_counter;
|
||||
|
||||
if (newval != -1)
|
||||
outpacket_counter = newval;
|
||||
|
||||
|
||||
125
src/poll.c
Normal file
125
src/poll.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
/* Wrapper for poll(). Allocates and extends array of struct pollfds,
|
||||
keeps them in fd order so that we can set and test conditions on
|
||||
fd using a simple but efficient binary chop. */
|
||||
|
||||
/* poll_reset()
|
||||
poll_listen(fd, event)
|
||||
.
|
||||
.
|
||||
poll_listen(fd, event);
|
||||
|
||||
hits = do_poll(timeout);
|
||||
|
||||
if (poll_check(fd, event)
|
||||
.
|
||||
.
|
||||
|
||||
if (poll_check(fd, event)
|
||||
.
|
||||
.
|
||||
|
||||
event is OR of POLLIN, POLLOUT, POLLERR, etc
|
||||
*/
|
||||
|
||||
static struct pollfd *pollfds = NULL;
|
||||
static nfds_t nfds, arrsize = 0;
|
||||
|
||||
/* Binary search. Returns either the pollfd with fd, or
|
||||
if the fd doesn't match, or return equals nfds, the entry
|
||||
to the left of which a new record should be inserted. */
|
||||
static nfds_t fd_search(int fd)
|
||||
{
|
||||
nfds_t left, right, mid;
|
||||
|
||||
if ((right = nfds) == 0)
|
||||
return 0;
|
||||
|
||||
left = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (right == left + 1)
|
||||
return (pollfds[left].fd >= fd) ? left : right;
|
||||
|
||||
mid = (left + right)/2;
|
||||
|
||||
if (pollfds[mid].fd > fd)
|
||||
right = mid;
|
||||
else
|
||||
left = mid;
|
||||
}
|
||||
}
|
||||
|
||||
void poll_reset(void)
|
||||
{
|
||||
nfds = 0;
|
||||
}
|
||||
|
||||
int do_poll(int timeout)
|
||||
{
|
||||
return poll(pollfds, nfds, timeout);
|
||||
}
|
||||
|
||||
int poll_check(int fd, short event)
|
||||
{
|
||||
nfds_t i = fd_search(fd);
|
||||
|
||||
if (i < nfds && pollfds[i].fd == fd)
|
||||
return pollfds[i].revents & event;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void poll_listen(int fd, short event)
|
||||
{
|
||||
nfds_t i = fd_search(fd);
|
||||
|
||||
if (i < nfds && pollfds[i].fd == fd)
|
||||
pollfds[i].events |= event;
|
||||
else
|
||||
{
|
||||
if (arrsize != nfds)
|
||||
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
else
|
||||
{
|
||||
/* Array too small, extend. */
|
||||
struct pollfd *new;
|
||||
|
||||
arrsize = (arrsize == 0) ? 64 : arrsize * 2;
|
||||
|
||||
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
|
||||
return;
|
||||
|
||||
if (pollfds)
|
||||
{
|
||||
memcpy(new, pollfds, i * sizeof(struct pollfd));
|
||||
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
free(pollfds);
|
||||
}
|
||||
|
||||
pollfds = new;
|
||||
}
|
||||
|
||||
pollfds[i].fd = fd;
|
||||
pollfds[i].events = event;
|
||||
nfds++;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
|
||||
74
src/radv.c
74
src/radv.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -28,11 +28,12 @@
|
||||
|
||||
struct ra_param {
|
||||
time_t now;
|
||||
int ind, managed, other, found_context, first, adv_router;
|
||||
int ind, managed, other, first, adv_router;
|
||||
char *if_name;
|
||||
struct dhcp_netid *tags;
|
||||
struct in6_addr link_local, link_global, ula;
|
||||
unsigned int glob_pref_time, link_pref_time, ula_pref_time, adv_interval, prio;
|
||||
struct dhcp_context *found_context;
|
||||
};
|
||||
|
||||
struct search_param {
|
||||
@@ -81,7 +82,7 @@ void ra_init(time_t now)
|
||||
/* ensure this is around even if we're not doing DHCPv6 */
|
||||
expand_buf(&daemon->outpacket, sizeof(struct dhcp_packet));
|
||||
|
||||
/* See if we're guessing SLAAC addresses, if so we need to recieve ping replies */
|
||||
/* See if we're guessing SLAAC addresses, if so we need to receive ping replies */
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if ((context->flags & CONTEXT_RA_NAME))
|
||||
break;
|
||||
@@ -111,10 +112,10 @@ void ra_init(time_t now)
|
||||
daemon->icmp6fd = fd;
|
||||
|
||||
if (daemon->doing_ra)
|
||||
ra_start_unsolicted(now, NULL);
|
||||
ra_start_unsolicited(now, NULL);
|
||||
}
|
||||
|
||||
void ra_start_unsolicted(time_t now, struct dhcp_context *context)
|
||||
void ra_start_unsolicited(time_t now, struct dhcp_context *context)
|
||||
{
|
||||
/* init timers so that we do ra's for some/all soon. some ra_times will end up zeroed
|
||||
if it's not appropriate to advertise those contexts.
|
||||
@@ -197,6 +198,9 @@ void icmp6_packet(time_t now)
|
||||
/* look for link-layer address option for logging */
|
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||
{
|
||||
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||
return;
|
||||
}
|
||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||
mac = daemon->namebuff;
|
||||
}
|
||||
@@ -242,7 +246,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
struct dhcp_netid iface_id;
|
||||
struct dhcp_opt *opt_cfg;
|
||||
struct ra_interface *ra_param = find_iface_param(iface_name);
|
||||
int done_dns = 0, old_prefix = 0;
|
||||
int done_dns = 0, old_prefix = 0, mtu = 0;
|
||||
unsigned int min_pref_time;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
FILE *f;
|
||||
@@ -251,7 +255,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
parm.ind = iface;
|
||||
parm.managed = 0;
|
||||
parm.other = 0;
|
||||
parm.found_context = 0;
|
||||
parm.found_context = NULL;
|
||||
parm.adv_router = 0;
|
||||
parm.if_name = iface_name;
|
||||
parm.first = 1;
|
||||
@@ -260,8 +264,10 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
parm.adv_interval = calc_interval(ra_param);
|
||||
parm.prio = calc_prio(ra_param);
|
||||
|
||||
save_counter(0);
|
||||
ra = expand(sizeof(struct ra_packet));
|
||||
reset_counter();
|
||||
|
||||
if (!(ra = expand(sizeof(struct ra_packet))))
|
||||
return;
|
||||
|
||||
ra->type = ND_ROUTER_ADVERT;
|
||||
ra->code = 0;
|
||||
@@ -308,8 +314,14 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
unsigned int old = difftime(now, context->address_lost_time);
|
||||
|
||||
if (old > context->saved_valid)
|
||||
{
|
||||
{
|
||||
/* We've advertised this enough, time to go */
|
||||
|
||||
/* If this context held the timeout, and there's another context in use
|
||||
transfer the timeout there. */
|
||||
if (context->ra_time != 0 && parm.found_context && parm.found_context->ra_time == 0)
|
||||
new_timeout(parm.found_context, iface_name, now);
|
||||
|
||||
*up = context->next;
|
||||
free(context);
|
||||
}
|
||||
@@ -390,22 +402,32 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
put_opt6_long(1000 * calc_interval(find_iface_param(iface_name)));
|
||||
}
|
||||
|
||||
/* Set the MTU from ra_param if any, an MTU of 0 mean automatic for linux, */
|
||||
/* an MTU of -1 prevents the option from being sent. */
|
||||
if (ra_param)
|
||||
mtu = ra_param->mtu;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* Note that IPv6 MTU is not necessarilly the same as the IPv4 MTU
|
||||
/* Note that IPv6 MTU is not neccessarily the same as the IPv4 MTU
|
||||
available from SIOCGIFMTU */
|
||||
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", iface_name);
|
||||
if ((f = fopen(daemon->namebuff, "r")))
|
||||
if (mtu == 0)
|
||||
{
|
||||
if (fgets(daemon->namebuff, MAXDNAME, f))
|
||||
{
|
||||
put_opt6_char(ICMP6_OPT_MTU);
|
||||
put_opt6_char(1);
|
||||
put_opt6_short(0);
|
||||
put_opt6_long(atoi(daemon->namebuff));
|
||||
}
|
||||
fclose(f);
|
||||
char *mtu_name = ra_param ? ra_param->mtu_name : NULL;
|
||||
sprintf(daemon->namebuff, "/proc/sys/net/ipv6/conf/%s/mtu", mtu_name ? : iface_name);
|
||||
if ((f = fopen(daemon->namebuff, "r")))
|
||||
{
|
||||
if (fgets(daemon->namebuff, MAXDNAME, f))
|
||||
mtu = atoi(daemon->namebuff);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (mtu > 0)
|
||||
{
|
||||
put_opt6_char(ICMP6_OPT_MTU);
|
||||
put_opt6_char(1);
|
||||
put_opt6_short(0);
|
||||
put_opt6_long(mtu);
|
||||
}
|
||||
|
||||
iface_enumerate(AF_LOCAL, &send_iface, add_lla);
|
||||
|
||||
@@ -519,7 +541,7 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
}
|
||||
|
||||
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(0), 0, (struct sockaddr *)&addr,
|
||||
save_counter(-1), 0, (struct sockaddr *)&addr,
|
||||
sizeof(addr))));
|
||||
|
||||
}
|
||||
@@ -636,8 +658,10 @@ static int add_prefixes(struct in6_addr *local, int prefix,
|
||||
off_link = (context->flags & CONTEXT_RA_OFF_LINK);
|
||||
}
|
||||
|
||||
param->first = 0;
|
||||
param->found_context = 1;
|
||||
param->first = 0;
|
||||
/* found_context is the _last_ one we found, so if there's
|
||||
more than one, it's not the first. */
|
||||
param->found_context = context;
|
||||
}
|
||||
|
||||
/* configured time is ceiling */
|
||||
@@ -769,7 +793,7 @@ time_t periodic_ra(time_t now)
|
||||
associated with it, because it's for a subnet we dont
|
||||
have an interface on. Probably we're doing DHCP on
|
||||
a remote subnet via a relay. Zero the timer, since we won't
|
||||
ever be able to send ra's and satistfy it. */
|
||||
ever be able to send ra's and satisfy it. */
|
||||
context->ra_time = 0;
|
||||
|
||||
if (param.iface != 0 &&
|
||||
|
||||
775
src/rfc1035.c
775
src/rfc1035.c
File diff suppressed because it is too large
Load Diff
180
src/rfc2131.c
180
src/rfc2131.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -32,7 +32,7 @@ static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, in
|
||||
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
|
||||
int opt, char *string, int null_term);
|
||||
static struct in_addr option_addr(unsigned char *opt);
|
||||
static unsigned int option_uint(unsigned char *opt, int i, int size);
|
||||
static unsigned int option_uint(unsigned char *opt, int offset, int size);
|
||||
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||
int mac_len, char *interface, char *string, char *err, u32 xid);
|
||||
static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
|
||||
@@ -42,14 +42,14 @@ static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
|
||||
static int in_list(unsigned char *list, int opt);
|
||||
static void do_options(struct dhcp_context *context,
|
||||
struct dhcp_packet *mess,
|
||||
unsigned char *real_end,
|
||||
unsigned char *end,
|
||||
unsigned char *req_options,
|
||||
char *hostname,
|
||||
char *config_domain,
|
||||
char *domain,
|
||||
struct dhcp_netid *netid,
|
||||
struct in_addr subnet_addr,
|
||||
unsigned char fqdn_flags,
|
||||
int null_term, int pxearch,
|
||||
int null_term, int pxe_arch,
|
||||
unsigned char *uuid,
|
||||
int vendor_class_len,
|
||||
time_t now,
|
||||
@@ -58,15 +58,17 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
|
||||
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
|
||||
static int do_encap_opts(struct dhcp_opt *opts, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||
static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
|
||||
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
|
||||
static int prune_vendor_opts(struct dhcp_netid *netid);
|
||||
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
|
||||
struct dhcp_boot *find_boot(struct dhcp_netid *netid);
|
||||
static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
|
||||
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
|
||||
|
||||
|
||||
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
size_t sz, time_t now, int unicast_dest, int *is_inform, int pxe, struct in_addr fallback)
|
||||
size_t sz, time_t now, int unicast_dest, int loopback,
|
||||
int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
|
||||
{
|
||||
unsigned char *opt, *clid = NULL;
|
||||
struct dhcp_lease *ltmp, *lease = NULL;
|
||||
@@ -155,7 +157,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
for (offset = 0; offset < (len - 5); offset += elen + 5)
|
||||
{
|
||||
elen = option_uint(opt, offset + 4 , 1);
|
||||
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA)
|
||||
if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
|
||||
{
|
||||
unsigned char *x = option_ptr(opt, offset + 5);
|
||||
unsigned char *y = option_ptr(opt, offset + elen + 5);
|
||||
@@ -186,7 +188,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
be enough free space at the end of the packet to copy the option. */
|
||||
unsigned char *sopt;
|
||||
unsigned int total = option_len(opt) + 2;
|
||||
unsigned char *last_opt = option_find(mess, sz, OPTION_END, 0);
|
||||
unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
|
||||
OPTION_END, 0);
|
||||
if (last_opt && last_opt < end - total)
|
||||
{
|
||||
end -= total;
|
||||
@@ -364,7 +367,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
||||
Otherwise assume the option is an array, and look for a matching element.
|
||||
If no data given, existance of the option is enough. This code handles
|
||||
If no data given, existence of the option is enough. This code handles
|
||||
rfc3925 V-I classes too. */
|
||||
for (o = daemon->dhcp_match; o; o = o->next)
|
||||
{
|
||||
@@ -380,7 +383,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
{
|
||||
len = option_uint(opt, offset + 4 , 1);
|
||||
/* Need to take care that bad data can't run us off the end of the packet */
|
||||
if ((offset + len + 5 <= (option_len(opt))) &&
|
||||
if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
|
||||
(option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
|
||||
for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
|
||||
{
|
||||
@@ -485,6 +488,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
known_id.next = netid;
|
||||
netid = &known_id;
|
||||
}
|
||||
else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
|
||||
mess->chaddr, mess->hlen, mess->htype, NULL))
|
||||
{
|
||||
known_id.net = "known-othernet";
|
||||
known_id.next = netid;
|
||||
netid = &known_id;
|
||||
}
|
||||
|
||||
if (mess_type == 0 && !pxe)
|
||||
{
|
||||
@@ -566,7 +576,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
lease_prune(lease, now);
|
||||
lease = NULL;
|
||||
}
|
||||
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now))
|
||||
if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
|
||||
message = _("no address available");
|
||||
}
|
||||
else
|
||||
@@ -824,7 +834,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
mess->siaddr = context->local;
|
||||
|
||||
snprintf((char *)mess->file, sizeof(mess->file), "%s.%d", service->basename, layer);
|
||||
if (strchr(service->basename, '.'))
|
||||
snprintf((char *)mess->file, sizeof(mess->file),
|
||||
"%s", service->basename);
|
||||
else
|
||||
snprintf((char *)mess->file, sizeof(mess->file),
|
||||
"%s.%d", service->basename, layer);
|
||||
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
|
||||
pxe_misc(mess, end, uuid);
|
||||
@@ -851,6 +867,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
|
||||
{
|
||||
struct dhcp_context *tmp;
|
||||
int workaround = 0;
|
||||
|
||||
for (tmp = context; tmp; tmp = tmp->current)
|
||||
if ((tmp->flags & CONTEXT_PROXY) &&
|
||||
@@ -860,7 +877,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (tmp)
|
||||
{
|
||||
struct dhcp_boot *boot;
|
||||
|
||||
int redirect4011 = 0;
|
||||
|
||||
if (tmp->netid.net)
|
||||
{
|
||||
tmp->netid.next = netid;
|
||||
@@ -878,10 +896,21 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
clear_packet(mess, end);
|
||||
|
||||
/* Provide the bootfile here, for gPXE, and in case we have no menu items
|
||||
and set discovery_control = 8 */
|
||||
if (boot)
|
||||
/* Redirect EFI clients to port 4011 */
|
||||
if (pxearch >= 6)
|
||||
{
|
||||
redirect4011 = 1;
|
||||
mess->siaddr = tmp->local;
|
||||
}
|
||||
|
||||
/* Returns true if only one matching service is available. On port 4011,
|
||||
it also inserts the boot file and server name. */
|
||||
workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
|
||||
|
||||
if (!workaround && boot)
|
||||
{
|
||||
/* Provide the bootfile here, for gPXE, and in case we have no menu items
|
||||
and set discovery_control = 8 */
|
||||
if (boot->next_server.s_addr)
|
||||
mess->siaddr = boot->next_server;
|
||||
else if (boot->tftp_sname)
|
||||
@@ -896,10 +925,13 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
|
||||
pxe_misc(mess, end, uuid);
|
||||
prune_vendor_opts(tagif_netid);
|
||||
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
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);
|
||||
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
if (!ignore)
|
||||
apply_delay(mess->xid, recvtime, tagif_netid);
|
||||
return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
||||
}
|
||||
}
|
||||
@@ -1020,11 +1052,11 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
!config_find_by_address(daemon->dhcp_conf, lease->addr))
|
||||
mess->yiaddr = lease->addr;
|
||||
else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
|
||||
!config_find_by_address(daemon->dhcp_conf, addr))
|
||||
!config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
|
||||
mess->yiaddr = addr;
|
||||
else if (emac_len == 0)
|
||||
message = _("no unique-id");
|
||||
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now))
|
||||
else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
|
||||
message = _("no address available");
|
||||
}
|
||||
|
||||
@@ -1040,7 +1072,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
|
||||
apply_delay(mess->xid, recvtime, tagif_netid);
|
||||
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));
|
||||
@@ -1286,6 +1318,24 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
add_extradata_opt(lease, NULL);
|
||||
}
|
||||
|
||||
/* DNSMASQ_REQUESTED_OPTIONS */
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
unsigned char *rop = option_ptr(opt, 0);
|
||||
char *q = daemon->namebuff;
|
||||
int i;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
q += snprintf(q, MAXDNAME - (q - daemon->namebuff), "%d%s", rop[i], i + 1 == len ? "" : ",");
|
||||
}
|
||||
lease_add_extradata(lease, (unsigned char *)daemon->namebuff, (q - daemon->namebuff), 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_extradata_opt(lease, NULL);
|
||||
}
|
||||
|
||||
/* space-concat tag set */
|
||||
if (!tagif_netid)
|
||||
add_extradata_opt(lease, NULL);
|
||||
@@ -1308,7 +1358,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
/* If the user-class option started as counted strings, the first byte will be zero. */
|
||||
if (len != 0 && ucp[0] == 0)
|
||||
ucp++, len--;
|
||||
lease_add_extradata(lease, ucp, len, 0);
|
||||
lease_add_extradata(lease, ucp, len, -1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1589,7 +1639,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
if (p > end)
|
||||
if (p >= end)
|
||||
return NULL;
|
||||
else if (*p == OPTION_END)
|
||||
return opt == OPTION_END ? p : NULL;
|
||||
@@ -1975,6 +2025,56 @@ static int prune_vendor_opts(struct dhcp_netid *netid)
|
||||
return force;
|
||||
}
|
||||
|
||||
|
||||
/* Many UEFI PXE implementations have badly broken menu code.
|
||||
If there's exactly one relevant menu item, we abandon the menu system,
|
||||
and jamb the data direct into the DHCP file, siaddr and sname fields.
|
||||
Note that in this case, we have to assume that layer zero would be requested
|
||||
by the client PXE stack. */
|
||||
static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
|
||||
{
|
||||
struct pxe_service *service, *found;
|
||||
|
||||
/* Only workaround UEFI archs. */
|
||||
if (pxe_arch < 6)
|
||||
return 0;
|
||||
|
||||
for (found = NULL, service = daemon->pxe_services; service; service = service->next)
|
||||
if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
|
||||
{
|
||||
if (found)
|
||||
return 0; /* More than one relevant menu item */
|
||||
|
||||
found = service;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return 0; /* No relevant menu items. */
|
||||
|
||||
if (!pxe)
|
||||
return 1;
|
||||
|
||||
if (found->sname)
|
||||
{
|
||||
mess->siaddr = a_record_from_hosts(found->sname, now);
|
||||
snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (found->server.s_addr != 0)
|
||||
mess->siaddr = found->server;
|
||||
else
|
||||
mess->siaddr = local;
|
||||
|
||||
inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
snprintf((char *)mess->file, sizeof(mess->file),
|
||||
strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
|
||||
{
|
||||
#define NUM_OPTS 4
|
||||
@@ -2352,10 +2452,10 @@ static void do_options(struct dhcp_context *context,
|
||||
|
||||
if (fqdn_flags & 0x04)
|
||||
{
|
||||
p = do_rfc1035_name(p, hostname);
|
||||
p = do_rfc1035_name(p, hostname, NULL);
|
||||
if (domain)
|
||||
{
|
||||
p = do_rfc1035_name(p, domain);
|
||||
p = do_rfc1035_name(p, domain, NULL);
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
@@ -2509,7 +2609,8 @@ static void do_options(struct dhcp_context *context,
|
||||
if (context && pxe_arch != -1)
|
||||
{
|
||||
pxe_misc(mess, end, uuid);
|
||||
config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
|
||||
if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
|
||||
config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
|
||||
}
|
||||
|
||||
if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
|
||||
@@ -2528,6 +2629,29 @@ static void do_options(struct dhcp_context *context,
|
||||
}
|
||||
}
|
||||
|
||||
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
|
||||
{
|
||||
struct delay_config *delay_conf;
|
||||
|
||||
/* Decide which delay_config option we're using */
|
||||
for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
|
||||
if (match_netid(delay_conf->netid, netid, 0))
|
||||
break;
|
||||
|
||||
if (!delay_conf)
|
||||
/* No match, look for one without a netid */
|
||||
for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
|
||||
if (match_netid(delay_conf->netid, netid, 1))
|
||||
break;
|
||||
|
||||
if (delay_conf)
|
||||
{
|
||||
if (!option_bool(OPT_QUIET_DHCP))
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
|
||||
delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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
|
||||
@@ -89,7 +89,7 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
|
||||
for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
|
||||
vendor->netid.next = &vendor->netid;
|
||||
|
||||
save_counter(0);
|
||||
reset_counter();
|
||||
state.context = context;
|
||||
state.interface = interface;
|
||||
state.iface_name = iface_name;
|
||||
@@ -118,7 +118,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
void *opt;
|
||||
struct dhcp_vendor *vendor;
|
||||
|
||||
/* if not an encaplsulated relayed message, just do the stuff */
|
||||
/* if not an encapsulated relayed message, just do the stuff */
|
||||
if (msg_type != DHCP6RELAYFORW)
|
||||
{
|
||||
/* if link_address != NULL if points to the link address field of the
|
||||
@@ -130,7 +130,7 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
MAC address from the local ND cache. */
|
||||
|
||||
if (!state->link_address)
|
||||
get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type);
|
||||
get_client_mac(client_addr, state->interface, state->mac, &state->mac_len, &state->mac_type, now);
|
||||
else
|
||||
{
|
||||
struct dhcp_context *c;
|
||||
@@ -206,6 +206,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
/* RFC-6939 */
|
||||
if ((opt = opt6_find(opts, end, OPTION6_CLIENT_MAC, 3)))
|
||||
{
|
||||
if (opt6_len(opt) - 2 > DHCP_CHADDR_MAX) {
|
||||
return 0;
|
||||
}
|
||||
state->mac_type = opt6_uint(opt, 0, 2);
|
||||
state->mac_len = opt6_len(opt) - 2;
|
||||
memcpy(&state->mac[0], opt6_ptr(opt, 2), state->mac_len);
|
||||
@@ -213,6 +216,9 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||
{
|
||||
if (opt6_ptr(opt, 0) + opt6_len(opt) >= end) {
|
||||
return 0;
|
||||
}
|
||||
int o = new_opt6(opt6_type(opt));
|
||||
if (opt6_type(opt) == OPTION6_RELAY_MSG)
|
||||
{
|
||||
@@ -262,7 +268,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
state->hostname_auth = 0;
|
||||
state->hostname = NULL;
|
||||
state->client_hostname = NULL;
|
||||
state->fqdn_flags = 0x01; /* default to send if we recieve 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
|
||||
@@ -381,7 +387,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
|
||||
/* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
|
||||
Otherwise assume the option is an array, and look for a matching element.
|
||||
If no data given, existance of the option is enough. This code handles
|
||||
If no data given, existence of the option is enough. This code handles
|
||||
V-I opts too. */
|
||||
for (opt_cfg = daemon->dhcp_match6; opt_cfg; opt_cfg = opt_cfg->next)
|
||||
{
|
||||
@@ -526,7 +532,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
if (have_config(config, CONFIG_DISABLE))
|
||||
ignore = 1;
|
||||
}
|
||||
|
||||
else if (state->clid &&
|
||||
find_config(daemon->dhcp_conf, NULL, state->clid, state->clid_len, state->mac, state->mac_len, state->mac_type, NULL))
|
||||
{
|
||||
known_id.net = "known-othernet";
|
||||
known_id.next = state->tags;
|
||||
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))
|
||||
@@ -1273,7 +1286,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
|
||||
}
|
||||
|
||||
/* We must anwser with 'success' in global section anyway */
|
||||
/* We must answer with 'success' in global section anyway */
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6SUCCESS);
|
||||
put_opt6_string(_("success"));
|
||||
@@ -1320,15 +1333,15 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
||||
|
||||
if (opt_cfg->opt == OPTION6_REFRESH_TIME)
|
||||
done_refresh = 1;
|
||||
|
||||
if (opt_cfg->opt == OPTION6_DNS_SERVER)
|
||||
done_dns = 1;
|
||||
|
||||
if (opt_cfg->flags & DHOPT_ADDR6)
|
||||
{
|
||||
int len, j;
|
||||
struct in6_addr *a;
|
||||
|
||||
if (opt_cfg->opt == OPTION6_DNS_SERVER)
|
||||
done_dns = 1;
|
||||
|
||||
for (a = (struct in6_addr *)opt_cfg->val, len = opt_cfg->len, j = 0;
|
||||
j < opt_cfg->len; j += IN6ADDRSZ, a++)
|
||||
if ((IN6_IS_ADDR_ULA_ZERO(a) && IN6_IS_ADDR_UNSPECIFIED(state->ula_addr)) ||
|
||||
@@ -1387,7 +1400,7 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
||||
unsigned int lease_time = 0xffffffff;
|
||||
|
||||
/* Find the smallest lease tie of all contexts,
|
||||
subjext to the RFC-4242 stipulation that this must not
|
||||
subject to the RFC-4242 stipulation that this must not
|
||||
be less than 600. */
|
||||
for (c = state->context; c; c = c->next)
|
||||
if (c->lease_time < lease_time)
|
||||
@@ -1472,10 +1485,10 @@ static struct dhcp_netid *add_options(struct state *state, int do_refresh)
|
||||
if ((p = expand(len + 2)))
|
||||
{
|
||||
*(p++) = state->fqdn_flags;
|
||||
p = do_rfc1035_name(p, state->hostname);
|
||||
p = do_rfc1035_name(p, state->hostname, NULL);
|
||||
if (state->send_domain)
|
||||
{
|
||||
p = do_rfc1035_name(p, state->send_domain);
|
||||
p = do_rfc1035_name(p, state->send_domain, NULL);
|
||||
*p = 0;
|
||||
}
|
||||
}
|
||||
@@ -1975,7 +1988,7 @@ static void log6_packet(struct state *state, char *type, struct in6_addr *addr,
|
||||
|
||||
if (addr)
|
||||
{
|
||||
inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, 255);
|
||||
inet_ntop(AF_INET6, addr, daemon->dhcp_buff2, DHCP_BUFF_SZ - 1);
|
||||
strcat(daemon->dhcp_buff2, " ");
|
||||
}
|
||||
else
|
||||
@@ -2054,7 +2067,8 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address, u32 scope_id)
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
||||
struct in6_addr *peer_address, u32 scope_id, time_t now)
|
||||
{
|
||||
/* ->local is same value for all relays on ->current chain */
|
||||
|
||||
@@ -2068,7 +2082,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
|
||||
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype);
|
||||
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr.addr6 = relay->local.addr.addr6;
|
||||
@@ -2083,7 +2097,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
|
||||
if (hopcount > 32)
|
||||
return;
|
||||
|
||||
save_counter(0);
|
||||
reset_counter();
|
||||
|
||||
if ((header = put_opt6(NULL, 34)))
|
||||
{
|
||||
@@ -2126,7 +2140,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast to DHCPv6 server without correct interface"));
|
||||
}
|
||||
|
||||
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(0), &to, &from, 0);
|
||||
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
@@ -2160,7 +2174,7 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
|
||||
(!relay->interface || wildcard_match(relay->interface, arrival_interface)))
|
||||
break;
|
||||
|
||||
save_counter(0);
|
||||
reset_counter();
|
||||
|
||||
if (relay)
|
||||
{
|
||||
|
||||
339
src/rrfilter.c
Normal file
339
src/rrfilter.c
Normal file
@@ -0,0 +1,339 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2017 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/>.
|
||||
*/
|
||||
|
||||
/* Code to safely remove RRs from an DNS answer */
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
/* Go through a domain name, find "pointers" and fix them up based on how many bytes
|
||||
we've chopped out of the packet, or check they don't point into an elided part. */
|
||||
static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
|
||||
{
|
||||
unsigned char *ansp = *namep;
|
||||
|
||||
while(1)
|
||||
{
|
||||
unsigned int label_type;
|
||||
|
||||
if (!CHECK_LEN(header, ansp, plen, 1))
|
||||
return 0;
|
||||
|
||||
label_type = (*ansp) & 0xc0;
|
||||
|
||||
if (label_type == 0xc0)
|
||||
{
|
||||
/* pointer for compression. */
|
||||
unsigned int offset;
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
if (!CHECK_LEN(header, ansp, plen, 2))
|
||||
return 0;
|
||||
|
||||
offset = ((*ansp++) & 0x3f) << 8;
|
||||
offset |= *ansp++;
|
||||
|
||||
p = offset + (unsigned char *)header;
|
||||
|
||||
for (i = 0; i < rr_count; i++)
|
||||
if (p < rrs[i])
|
||||
break;
|
||||
else
|
||||
if (i & 1)
|
||||
offset -= rrs[i] - rrs[i-1];
|
||||
|
||||
/* does the pointer end up in an elided RR? */
|
||||
if (i & 1)
|
||||
return 0;
|
||||
|
||||
/* No, scale the pointer */
|
||||
if (fixup)
|
||||
{
|
||||
ansp -= 2;
|
||||
*ansp++ = (offset >> 8) | 0xc0;
|
||||
*ansp++ = offset & 0xff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (label_type == 0x80)
|
||||
return 0; /* reserved */
|
||||
else if (label_type == 0x40)
|
||||
{
|
||||
/* Extended label type */
|
||||
unsigned int count;
|
||||
|
||||
if (!CHECK_LEN(header, ansp, plen, 2))
|
||||
return 0;
|
||||
|
||||
if (((*ansp++) & 0x3f) != 1)
|
||||
return 0; /* we only understand bitstrings */
|
||||
|
||||
count = *(ansp++); /* Bits in bitstring */
|
||||
|
||||
if (count == 0) /* count == 0 means 256 bits */
|
||||
ansp += 32;
|
||||
else
|
||||
ansp += ((count-1)>>3)+1;
|
||||
}
|
||||
else
|
||||
{ /* label type == 0 Bottom six bits is length */
|
||||
unsigned int len = (*ansp++) & 0x3f;
|
||||
|
||||
if (!ADD_RDLEN(header, ansp, plen, len))
|
||||
return 0;
|
||||
|
||||
if (len == 0)
|
||||
break; /* zero length label marks the end. */
|
||||
}
|
||||
}
|
||||
|
||||
*namep = ansp;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Go through RRs and check or fixup the domain names contained within */
|
||||
static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
|
||||
{
|
||||
int i, j, type, class, rdlen;
|
||||
unsigned char *pp;
|
||||
|
||||
for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
|
||||
{
|
||||
pp = p;
|
||||
|
||||
if (!(p = skip_name(p, header, plen, 10)))
|
||||
return 0;
|
||||
|
||||
GETSHORT(type, p);
|
||||
GETSHORT(class, p);
|
||||
p += 4; /* TTL */
|
||||
GETSHORT(rdlen, p);
|
||||
|
||||
/* If this RR is to be elided, don't fix up its contents */
|
||||
for (j = 0; j < rr_count; j += 2)
|
||||
if (rrs[j] == pp)
|
||||
break;
|
||||
|
||||
if (j >= rr_count)
|
||||
{
|
||||
/* fixup name of RR */
|
||||
if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
|
||||
return 0;
|
||||
|
||||
if (class == C_IN)
|
||||
{
|
||||
u16 *d;
|
||||
|
||||
for (pp = p, d = rrfilter_desc(type); *d != (u16)-1; d++)
|
||||
{
|
||||
if (*d != 0)
|
||||
pp += *d;
|
||||
else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
|
||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
||||
{
|
||||
static unsigned char **rrs;
|
||||
static int rr_sz = 0;
|
||||
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
|
||||
|
||||
if (ntohs(header->qdcount) != 1 ||
|
||||
!(p = skip_name(p, header, plen, 4)))
|
||||
return plen;
|
||||
|
||||
GETSHORT(qtype, p);
|
||||
GETSHORT(qclass, p);
|
||||
|
||||
/* First pass, find pointers to start and end of all the records we wish to elide:
|
||||
records added for DNSSEC, unless explicitly queried for */
|
||||
for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0;
|
||||
i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
|
||||
i++)
|
||||
{
|
||||
unsigned char *pstart = p;
|
||||
int type, class;
|
||||
|
||||
if (!(p = skip_name(p, header, plen, 10)))
|
||||
return plen;
|
||||
|
||||
GETSHORT(type, p);
|
||||
GETSHORT(class, p);
|
||||
p += 4; /* TTL */
|
||||
GETSHORT(rdlen, p);
|
||||
|
||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||
return plen;
|
||||
|
||||
/* Don't remove the answer. */
|
||||
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
|
||||
continue;
|
||||
|
||||
if (mode == 0) /* EDNS */
|
||||
{
|
||||
/* EDNS mode, remove T_OPT from additional section only */
|
||||
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
|
||||
continue;
|
||||
}
|
||||
else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
|
||||
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
|
||||
continue;
|
||||
|
||||
|
||||
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
|
||||
return plen;
|
||||
|
||||
rrs[rr_found++] = pstart;
|
||||
rrs[rr_found++] = p;
|
||||
|
||||
if (i < ntohs(header->ancount))
|
||||
chop_an++;
|
||||
else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
|
||||
chop_ns++;
|
||||
else
|
||||
chop_ar++;
|
||||
}
|
||||
|
||||
/* Nothing to do. */
|
||||
if (rr_found == 0)
|
||||
return plen;
|
||||
|
||||
/* Second pass, look for pointers in names in the records we're keeping and make sure they don't
|
||||
point to records we're going to elide. This is theoretically possible, but unlikely. If
|
||||
it happens, we give up and leave the answer unchanged. */
|
||||
p = (unsigned char *)(header+1);
|
||||
|
||||
/* question first */
|
||||
if (!check_name(&p, header, plen, 0, rrs, rr_found))
|
||||
return plen;
|
||||
p += 4; /* qclass, qtype */
|
||||
|
||||
/* Now answers and NS */
|
||||
if (!check_rrs(p, header, plen, 0, rrs, rr_found))
|
||||
return plen;
|
||||
|
||||
/* Third pass, actually fix up pointers in the records */
|
||||
p = (unsigned char *)(header+1);
|
||||
|
||||
check_name(&p, header, plen, 1, rrs, rr_found);
|
||||
p += 4; /* qclass, qtype */
|
||||
|
||||
check_rrs(p, header, plen, 1, rrs, rr_found);
|
||||
|
||||
/* Fouth pass, elide records */
|
||||
for (p = rrs[0], i = 1; i < rr_found; i += 2)
|
||||
{
|
||||
unsigned char *start = rrs[i];
|
||||
unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)header) + plen;
|
||||
|
||||
memmove(p, start, end-start);
|
||||
p += end-start;
|
||||
}
|
||||
|
||||
plen = p - (unsigned char *)header;
|
||||
header->ancount = htons(ntohs(header->ancount) - chop_an);
|
||||
header->nscount = htons(ntohs(header->nscount) - chop_ns);
|
||||
header->arcount = htons(ntohs(header->arcount) - chop_ar);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
/* This is used in the DNSSEC code too, hence it's exported */
|
||||
u16 *rrfilter_desc(int type)
|
||||
{
|
||||
/* List of RRtypes which include domains in the data.
|
||||
0 -> domain
|
||||
integer -> no of plain bytes
|
||||
-1 -> end
|
||||
|
||||
zero is not a valid RRtype, so the final entry is returned for
|
||||
anything which needs no mangling.
|
||||
*/
|
||||
|
||||
static u16 rr_desc[] =
|
||||
{
|
||||
T_NS, 0, -1,
|
||||
T_MD, 0, -1,
|
||||
T_MF, 0, -1,
|
||||
T_CNAME, 0, -1,
|
||||
T_SOA, 0, 0, -1,
|
||||
T_MB, 0, -1,
|
||||
T_MG, 0, -1,
|
||||
T_MR, 0, -1,
|
||||
T_PTR, 0, -1,
|
||||
T_MINFO, 0, 0, -1,
|
||||
T_MX, 2, 0, -1,
|
||||
T_RP, 0, 0, -1,
|
||||
T_AFSDB, 2, 0, -1,
|
||||
T_RT, 2, 0, -1,
|
||||
T_SIG, 18, 0, -1,
|
||||
T_PX, 2, 0, 0, -1,
|
||||
T_NXT, 0, -1,
|
||||
T_KX, 2, 0, -1,
|
||||
T_SRV, 6, 0, -1,
|
||||
T_DNAME, 0, -1,
|
||||
0, -1 /* wildcard/catchall */
|
||||
};
|
||||
|
||||
u16 *p = rr_desc;
|
||||
|
||||
while (*p != type && *p != 0)
|
||||
while (*p++ != (u16)-1);
|
||||
|
||||
return p+1;
|
||||
}
|
||||
|
||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new)
|
||||
{
|
||||
unsigned char **p;
|
||||
int old = *szp;
|
||||
|
||||
if (old >= new+1)
|
||||
return 1;
|
||||
|
||||
if (new >= 100)
|
||||
return 0;
|
||||
|
||||
new += 5;
|
||||
|
||||
if (!(p = whine_malloc(new * sizeof(unsigned char *))))
|
||||
return 0;
|
||||
|
||||
if (old != 0 && *wkspc)
|
||||
{
|
||||
memcpy(p, *wkspc, old * sizeof(unsigned char *));
|
||||
free(*wkspc);
|
||||
}
|
||||
|
||||
*wkspc = p;
|
||||
*szp = new;
|
||||
|
||||
return 1;
|
||||
}
|
||||
13
src/slaac.c
13
src/slaac.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -94,7 +94,7 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
|
||||
slaac->backoff = 1;
|
||||
slaac->addr = addr;
|
||||
/* Do RA's to prod it */
|
||||
ra_start_unsolicted(now, context);
|
||||
ra_start_unsolicited(now, context);
|
||||
}
|
||||
|
||||
if (slaac)
|
||||
@@ -146,8 +146,11 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
||||
struct ping_packet *ping;
|
||||
struct sockaddr_in6 addr;
|
||||
|
||||
save_counter(0);
|
||||
ping = expand(sizeof(struct ping_packet));
|
||||
reset_counter();
|
||||
|
||||
if (!(ping = expand(sizeof(struct ping_packet))))
|
||||
continue;
|
||||
|
||||
ping->type = ICMP6_ECHO_REQUEST;
|
||||
ping->code = 0;
|
||||
ping->identifier = ping_id;
|
||||
@@ -161,7 +164,7 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
||||
addr.sin6_port = htons(IPPROTO_ICMPV6);
|
||||
addr.sin6_addr = slaac->addr;
|
||||
|
||||
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
|
||||
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
|
||||
errno == EHOSTUNREACH)
|
||||
slaac->ping_time = 0; /* Give up */
|
||||
|
||||
94
src/tables.c
94
src/tables.c
@@ -20,9 +20,7 @@
|
||||
|
||||
#if defined(HAVE_IPSET) && defined(HAVE_BSD_NETWORK)
|
||||
|
||||
#ifndef __FreeBSD__
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
@@ -53,52 +51,6 @@ static char *pfr_strerror(int errnum)
|
||||
}
|
||||
}
|
||||
|
||||
static int pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
|
||||
{
|
||||
struct pfioc_table io;
|
||||
|
||||
if (size < 0 || (size && tbl == NULL))
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = flags;
|
||||
io.pfrio_buffer = tbl;
|
||||
io.pfrio_esize = sizeof(*tbl);
|
||||
io.pfrio_size = size;
|
||||
if (ioctl(dev, DIOCRADDTABLES, &io))
|
||||
return (-1);
|
||||
if (nadd != NULL)
|
||||
*nadd = io.pfrio_nadd;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int fill_addr(const struct all_addr *ipaddr, int flags, struct pfr_addr* addr) {
|
||||
if ( !addr || !ipaddr)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: fill_addr missused"));
|
||||
return -1;
|
||||
}
|
||||
bzero(addr, sizeof(*addr));
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
{
|
||||
addr->pfra_af = AF_INET6;
|
||||
addr->pfra_net = 0x80;
|
||||
memcpy(&(addr->pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
addr->pfra_af = AF_INET;
|
||||
addr->pfra_net = 0x20;
|
||||
addr->pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void ipset_init(void)
|
||||
{
|
||||
@@ -111,14 +63,13 @@ void ipset_init(void)
|
||||
}
|
||||
|
||||
int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
||||
int flags, int remove)
|
||||
int flags, int remove)
|
||||
{
|
||||
struct pfr_addr addr;
|
||||
struct pfioc_table io;
|
||||
struct pfr_table table;
|
||||
int n = 0, rc = 0;
|
||||
|
||||
if ( dev == -1 )
|
||||
if (dev == -1)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("warning: no opened pf devices %s"), pf_device);
|
||||
return -1;
|
||||
@@ -126,31 +77,52 @@ int add_to_ipset(const char *setname, const struct all_addr *ipaddr,
|
||||
|
||||
bzero(&table, sizeof(struct pfr_table));
|
||||
table.pfrt_flags |= PFR_TFLAG_PERSIST;
|
||||
if ( strlen(setname) >= PF_TABLE_NAME_SIZE )
|
||||
if (strlen(setname) >= PF_TABLE_NAME_SIZE)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: cannot use table name %s"), setname);
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ( strlcpy(table.pfrt_name, setname,
|
||||
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
|
||||
if (strlcpy(table.pfrt_name, setname,
|
||||
sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error: cannot strlcpy table name %s"), setname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((rc = pfr_add_tables(&table, 1, &n, 0)))
|
||||
bzero(&io, sizeof io);
|
||||
io.pfrio_flags = 0;
|
||||
io.pfrio_buffer = &table;
|
||||
io.pfrio_esize = sizeof(table);
|
||||
io.pfrio_size = 1;
|
||||
if (ioctl(dev, DIOCRADDTABLES, &io))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("warning: pfr_add_tables: %s(%d)"),
|
||||
pfr_strerror(errno),rc);
|
||||
my_syslog(LOG_WARNING, _("IPset: error:%s"), pfr_strerror(errno));
|
||||
|
||||
return -1;
|
||||
}
|
||||
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
|
||||
if (n)
|
||||
my_syslog(LOG_INFO, _("info: table created"));
|
||||
|
||||
fill_addr(ipaddr,flags,&addr);
|
||||
table.pfrt_flags &= ~PFR_TFLAG_PERSIST;
|
||||
if (io.pfrio_nadd)
|
||||
my_syslog(LOG_INFO, _("info: table created"));
|
||||
|
||||
bzero(&addr, sizeof(addr));
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
{
|
||||
addr.pfra_af = AF_INET6;
|
||||
addr.pfra_net = 0x80;
|
||||
memcpy(&(addr.pfra_ip6addr), &(ipaddr->addr), sizeof(struct in6_addr));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
addr.pfra_af = AF_INET;
|
||||
addr.pfra_net = 0x20;
|
||||
addr.pfra_ip4addr.s_addr = ipaddr->addr.addr4.s_addr;
|
||||
}
|
||||
|
||||
bzero(&io, sizeof(io));
|
||||
io.pfrio_flags = 0;
|
||||
io.pfrio_table = table;
|
||||
|
||||
84
src/tftp.c
84
src/tftp.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||
static void free_transfer(struct tftp_transfer *transfer);
|
||||
static ssize_t tftp_err(int err, char *packet, char *mess, char *file);
|
||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
||||
static ssize_t tftp_err_oops(char *packet, char *file);
|
||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
||||
static char *next(char **p, char *end);
|
||||
@@ -103,8 +103,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (listen->iface)
|
||||
{
|
||||
addr = listen->iface->addr;
|
||||
mtu = listen->iface->mtu;
|
||||
name = listen->iface->name;
|
||||
mtu = listen->iface->mtu;
|
||||
if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
|
||||
mtu = daemon->tftp_mtu;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -234,9 +236,17 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
|
||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||
mtu = ifr.ifr_mtu;
|
||||
{
|
||||
mtu = ifr.ifr_mtu;
|
||||
if (daemon->tftp_mtu != 0 && daemon->tftp_mtu < mtu)
|
||||
mtu = daemon->tftp_mtu;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failed to get interface mtu - can use configured value. */
|
||||
if (mtu == 0)
|
||||
mtu = daemon->tftp_mtu;
|
||||
|
||||
if (name)
|
||||
{
|
||||
/* check for per-interface prefix */
|
||||
@@ -336,14 +346,15 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
{
|
||||
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
|
||||
{
|
||||
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
|
||||
int overhead = (listen->family == AF_INET) ? 32 : 52;
|
||||
transfer->blocksize = atoi(opt);
|
||||
if (transfer->blocksize < 1)
|
||||
transfer->blocksize = 1;
|
||||
if (transfer->blocksize > (unsigned)daemon->packet_buff_sz - 4)
|
||||
transfer->blocksize = (unsigned)daemon->packet_buff_sz - 4;
|
||||
/* 32 bytes for IP, UDP and TFTP headers */
|
||||
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - 32)
|
||||
transfer->blocksize = (unsigned)mtu - 32;
|
||||
if (mtu != 0 && transfer->blocksize > (unsigned)mtu - overhead)
|
||||
transfer->blocksize = (unsigned)mtu - overhead;
|
||||
transfer->opt_blocksize = 1;
|
||||
transfer->block = 0;
|
||||
}
|
||||
@@ -371,7 +382,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (prefix[strlen(prefix)-1] != '/')
|
||||
strncat(daemon->namebuff, "/", (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||
|
||||
if (option_bool(OPT_TFTP_APREF))
|
||||
if (option_bool(OPT_TFTP_APREF_IP))
|
||||
{
|
||||
size_t oldlen = strlen(daemon->namebuff);
|
||||
struct stat statbuf;
|
||||
@@ -383,7 +394,40 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
|
||||
daemon->namebuff[oldlen] = 0;
|
||||
}
|
||||
|
||||
|
||||
if (option_bool(OPT_TFTP_APREF_MAC))
|
||||
{
|
||||
unsigned char *macaddr = NULL;
|
||||
unsigned char macbuf[DHCP_CHADDR_MAX];
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp && peer.sa.sa_family == AF_INET)
|
||||
{
|
||||
/* Check if the client IP is in our lease database */
|
||||
struct dhcp_lease *lease = lease_find_by_addr(peer.in.sin_addr);
|
||||
if (lease && lease->hwaddr_type == ARPHRD_ETHER && lease->hwaddr_len == ETHER_ADDR_LEN)
|
||||
macaddr = lease->hwaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If no luck, try to find in ARP table. This only works if client is in same (V)LAN */
|
||||
if (!macaddr && find_mac(&peer, macbuf, 1, now) > 0)
|
||||
macaddr = macbuf;
|
||||
|
||||
if (macaddr)
|
||||
{
|
||||
size_t oldlen = strlen(daemon->namebuff);
|
||||
struct stat statbuf;
|
||||
|
||||
snprintf(daemon->namebuff + oldlen, (MAXDNAME-1) - oldlen, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x/",
|
||||
macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5]);
|
||||
|
||||
/* remove unique-directory if it doesn't exist */
|
||||
if (stat(daemon->namebuff, &statbuf) == -1 || !S_ISDIR(statbuf.st_mode))
|
||||
daemon->namebuff[oldlen] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Absolute pathnames OK if they match prefix */
|
||||
if (filename[0] == '/')
|
||||
{
|
||||
@@ -396,7 +440,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
else if (filename[0] == '/')
|
||||
daemon->namebuff[0] = 0;
|
||||
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||
|
||||
|
||||
/* check permissions and open file */
|
||||
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
|
||||
{
|
||||
@@ -459,7 +503,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
else if (option_bool(OPT_TFTP_SECURE) && uid != statbuf.st_uid)
|
||||
goto perm;
|
||||
|
||||
/* If we're doing many tranfers from the same file, only
|
||||
/* If we're doing many transfers from the same file, only
|
||||
open it once this saves lots of file descriptors
|
||||
when mass-booting a big cluster, for instance.
|
||||
Be conservative and only share when inode and name match
|
||||
@@ -502,7 +546,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
void check_tftp_listeners(time_t now)
|
||||
{
|
||||
struct tftp_transfer *transfer, *tmp, **up;
|
||||
ssize_t len;
|
||||
@@ -518,7 +562,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
|
||||
|
||||
prettyprint_addr(&transfer->peer, daemon->addrbuff);
|
||||
|
||||
if (FD_ISSET(transfer->sockfd, rset))
|
||||
if (poll_check(transfer->sockfd, POLLIN))
|
||||
{
|
||||
/* we overwrote the buffer... */
|
||||
daemon->srv_save = NULL;
|
||||
@@ -641,20 +685,24 @@ static void sanitise(char *buf)
|
||||
|
||||
}
|
||||
|
||||
#define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */
|
||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file)
|
||||
{
|
||||
struct errmess {
|
||||
unsigned short op, err;
|
||||
char message[];
|
||||
} *mess = (struct errmess *)packet;
|
||||
ssize_t ret = 4;
|
||||
ssize_t len, ret = 4;
|
||||
char *errstr = strerror(errno);
|
||||
|
||||
memset(packet, 0, daemon->packet_buff_sz);
|
||||
sanitise(file);
|
||||
|
||||
|
||||
mess->op = htons(OP_ERR);
|
||||
mess->err = htons(err);
|
||||
ret += (snprintf(mess->message, 500, message, file, errstr) + 1);
|
||||
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
|
||||
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
|
||||
|
||||
my_syslog(MS_TFTP | LOG_ERR, "%s", mess->message);
|
||||
|
||||
return ret;
|
||||
@@ -670,6 +718,8 @@ static ssize_t tftp_err_oops(char *packet, char *file)
|
||||
/* return -1 for error, zero for done. */
|
||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
||||
{
|
||||
memset(packet, 0, daemon->packet_buff_sz);
|
||||
|
||||
if (transfer->block == 0)
|
||||
{
|
||||
/* send OACK */
|
||||
@@ -684,7 +734,7 @@ static ssize_t get_block(char *packet, struct tftp_transfer *transfer)
|
||||
if (transfer->opt_blocksize)
|
||||
{
|
||||
p += (sprintf(p, "blksize") + 1);
|
||||
p += (sprintf(p, "%d", transfer->blocksize) + 1);
|
||||
p += (sprintf(p, "%u", transfer->blocksize) + 1);
|
||||
}
|
||||
if (transfer->opt_transize)
|
||||
{
|
||||
|
||||
104
src/util.c
104
src/util.c
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2015 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -24,7 +24,9 @@
|
||||
#include <sys/times.h>
|
||||
#endif
|
||||
|
||||
#if defined(LOCALEDIR) || defined(HAVE_IDN)
|
||||
#if defined(HAVE_LIBIDN2)
|
||||
#include <idn2.h>
|
||||
#elif defined(HAVE_IDN)
|
||||
#include <idna.h>
|
||||
#endif
|
||||
|
||||
@@ -109,6 +111,7 @@ u64 rand64(void)
|
||||
return (u64)out[outleft+1] + (((u64)out[outleft]) << 32);
|
||||
}
|
||||
|
||||
/* returns 2 if names is OK but contains one or more underscores */
|
||||
static int check_name(char *in)
|
||||
{
|
||||
/* remove trailing .
|
||||
@@ -116,6 +119,7 @@ static int check_name(char *in)
|
||||
size_t dotgap = 0, l = strlen(in);
|
||||
char c;
|
||||
int nowhite = 0;
|
||||
int hasuscore = 0;
|
||||
|
||||
if (l == 0 || l > MAXDNAME) return 0;
|
||||
|
||||
@@ -134,18 +138,22 @@ static int check_name(char *in)
|
||||
else if (isascii((unsigned char)c) && iscntrl((unsigned char)c))
|
||||
/* iscntrl only gives expected results for ascii */
|
||||
return 0;
|
||||
#if !defined(LOCALEDIR) && !defined(HAVE_IDN)
|
||||
#if !defined(HAVE_IDN) && !defined(HAVE_LIBIDN2)
|
||||
else if (!isascii((unsigned char)c))
|
||||
return 0;
|
||||
#endif
|
||||
else if (c != ' ')
|
||||
nowhite = 1;
|
||||
{
|
||||
nowhite = 1;
|
||||
if (c == '_')
|
||||
hasuscore = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nowhite)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
return hasuscore ? 2 : 1;
|
||||
}
|
||||
|
||||
/* Hostnames have a more limited valid charset than domain names
|
||||
@@ -184,49 +192,68 @@ int legal_hostname(char *name)
|
||||
char *canonicalise(char *in, int *nomem)
|
||||
{
|
||||
char *ret = NULL;
|
||||
#if defined(LOCALEDIR) || defined(HAVE_IDN)
|
||||
int rc;
|
||||
#endif
|
||||
|
||||
|
||||
if (nomem)
|
||||
*nomem = 0;
|
||||
|
||||
if (!check_name(in))
|
||||
if (!(rc = check_name(in)))
|
||||
return NULL;
|
||||
|
||||
#if defined(LOCALEDIR) || defined(HAVE_IDN)
|
||||
if ((rc = idna_to_ascii_lz(in, &ret, 0)) != IDNA_SUCCESS)
|
||||
#if defined(HAVE_LIBIDN2) && (!defined(IDN2_VERSION_NUMBER) || IDN2_VERSION_NUMBER < 0x02000003)
|
||||
/* older libidn2 strips underscores, so don't do IDN processing
|
||||
if the name has an underscore (check_name() returned 2) */
|
||||
if (rc != 2)
|
||||
#endif
|
||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2)
|
||||
{
|
||||
if (ret)
|
||||
free(ret);
|
||||
|
||||
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
||||
# ifdef HAVE_LIBIDN2
|
||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
||||
if (rc == IDN2_DISALLOWED)
|
||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
||||
# else
|
||||
rc = idna_to_ascii_lz(in, &ret, 0);
|
||||
# endif
|
||||
if (rc != IDNA_SUCCESS)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
||||
*nomem = 1;
|
||||
if (ret)
|
||||
free(ret);
|
||||
|
||||
if (nomem && (rc == IDNA_MALLOC_ERROR || rc == IDNA_DLOPEN_ERROR))
|
||||
{
|
||||
my_syslog(LOG_ERR, _("failed to allocate memory"));
|
||||
*nomem = 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
|
||||
if ((ret = whine_malloc(strlen(in)+1)))
|
||||
strcpy(ret, in);
|
||||
else if (nomem)
|
||||
*nomem = 1;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit)
|
||||
{
|
||||
int j;
|
||||
|
||||
while (sval && *sval)
|
||||
{
|
||||
if (limit && p + 1 > (unsigned char*)limit)
|
||||
return p;
|
||||
|
||||
unsigned char *cp = p++;
|
||||
for (j = 0; *sval && (*sval != '.'); sval++, j++)
|
||||
{
|
||||
if (limit && p + 1 > (unsigned char*)limit)
|
||||
return p;
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && *sval == NAME_ESCAPE)
|
||||
*p++ = (*(++sval))-1;
|
||||
@@ -244,11 +271,11 @@ unsigned char *do_rfc1035_name(unsigned char *p, char *sval)
|
||||
/* for use during startup */
|
||||
void *safe_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
void *ret = calloc(1, size);
|
||||
|
||||
if (!ret)
|
||||
die(_("could not get memory"), NULL, EC_NOMEM);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -262,11 +289,11 @@ void safe_pipe(int *fd, int read_noblock)
|
||||
|
||||
void *whine_malloc(size_t size)
|
||||
{
|
||||
void *ret = malloc(size);
|
||||
void *ret = calloc(1, size);
|
||||
|
||||
if (!ret)
|
||||
my_syslog(LOG_ERR, _("failed to allocate %d bytes"), (int) size);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -323,7 +350,7 @@ int hostname_isequal(const char *a, const char *b)
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
time_t dnsmasq_time(void)
|
||||
{
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
@@ -373,7 +400,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* return least signigicant 64 bits if IPv6 address */
|
||||
/* return least significant 64 bits if IPv6 address */
|
||||
u64 addr6part(struct in6_addr *addr)
|
||||
{
|
||||
int i;
|
||||
@@ -439,13 +466,13 @@ void prettyprint_time(char *buf, unsigned int t)
|
||||
{
|
||||
unsigned int x, p = 0;
|
||||
if ((x = t/86400))
|
||||
p += sprintf(&buf[p], "%dd", x);
|
||||
p += sprintf(&buf[p], "%ud", x);
|
||||
if ((x = (t/3600)%24))
|
||||
p += sprintf(&buf[p], "%dh", x);
|
||||
p += sprintf(&buf[p], "%uh", x);
|
||||
if ((x = (t/60)%60))
|
||||
p += sprintf(&buf[p], "%dm", x);
|
||||
p += sprintf(&buf[p], "%um", x);
|
||||
if ((x = t%60))
|
||||
p += sprintf(&buf[p], "%ds", x);
|
||||
p += sprintf(&buf[p], "%us", x);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -497,9 +524,14 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
|
||||
sav = in[(j+1)*2];
|
||||
in[(j+1)*2] = 0;
|
||||
}
|
||||
/* checks above allow mix of hexdigit and *, which
|
||||
is illegal. */
|
||||
if (strchr(&in[j*2], '*'))
|
||||
return -1;
|
||||
out[i] = strtol(&in[j*2], NULL, 16);
|
||||
mask = mask << 1;
|
||||
i++;
|
||||
if (++i == maxlen)
|
||||
break;
|
||||
if (j < bytes - 1)
|
||||
in[(j+1)*2] = sav;
|
||||
}
|
||||
@@ -570,12 +602,6 @@ char *print_mac(char *buff, unsigned char *mac, int len)
|
||||
return buff;
|
||||
}
|
||||
|
||||
void bump_maxfd(int fd, int *max)
|
||||
{
|
||||
if (fd > *max)
|
||||
*max = fd;
|
||||
}
|
||||
|
||||
/* rc is return from sendto and friends.
|
||||
Return 1 if we should retry.
|
||||
Set errno to zero if we succeeded. */
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
# The root DNSSEC trust anchor, valid as at 30/01/2014
|
||||
# The root DNSSEC trust anchor, valid as at 10/02/2017
|
||||
|
||||
# Note that this is a DS record (ie a hash of the root Zone Signing Key)
|
||||
# If was downloaded from https://data.iana.org/root-anchors/root-anchors.xml
|
||||
|
||||
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
|
||||
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user