mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-03 13:38:32 +00:00
Compare commits
102
Commits
v2.87test3
...
v2.87
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c4b9bc63e0 | ||
|
|
4447d48bb9 | ||
|
|
04cc2ae1a6 | ||
|
|
32588c755a | ||
|
|
84a6d07cdd | ||
|
|
d6c69f6bdb | ||
|
|
ce372917fe | ||
|
|
09d741f58a | ||
|
|
0666ae3d27 | ||
|
|
ba4c7d906b | ||
|
|
f4b2813818 | ||
|
|
5586934da0 | ||
|
|
6134b94c02 | ||
|
|
05e6728e98 | ||
|
|
6578acd668 | ||
|
|
b5581ed173 | ||
|
|
508d6b4885 | ||
|
|
ef6efd69ed | ||
|
|
151d7dc5ea | ||
|
|
20b4a4ea5b | ||
|
|
770bce967c | ||
|
|
a267a9e489 | ||
|
|
f65d210012 | ||
|
|
858bfcf261 | ||
|
|
9b801c4e72 | ||
|
|
1a98d1a94f | ||
|
|
03345ecefe | ||
|
|
191924576c | ||
|
|
756a1dcc19 | ||
|
|
3ab6dd1c37 | ||
|
|
4458d87289 | ||
|
|
b7f62475d0 | ||
|
|
4732aa663b | ||
|
|
c27cfeaa7b | ||
|
|
bb6f6bae0b | ||
|
|
f4c87b504b | ||
|
|
e426c2d3bc | ||
|
|
6279d9eaf3 | ||
|
|
12949aa0c0 | ||
|
|
84f3357dd9 | ||
|
|
4333d5d93a | ||
|
|
fa580ad3eb | ||
|
|
292dfa653e | ||
|
|
7fbf1cce7b | ||
|
|
dbceeb4178 | ||
|
|
ed200fa001 | ||
|
|
b5dafc0b7e | ||
|
|
fc664d114d | ||
|
|
c6d4c33d61 | ||
|
|
bf1fc6c6fd | ||
|
|
b18e9c8c61 | ||
|
|
a3293bb242 | ||
|
|
4e2a4b8788 | ||
|
|
2362784bc0 | ||
|
|
b2cec1b881 | ||
|
|
a946857133 | ||
|
|
10cd342f5c | ||
|
|
27ce754b3d | ||
|
|
3ab0ad8748 | ||
|
|
4308236262 | ||
|
|
ebd8350300 | ||
|
|
8285d335f4 | ||
|
|
9db275ebea | ||
|
|
1f8f78a49b | ||
|
|
c2f129ba3d | ||
|
|
07c47416a9 | ||
|
|
8f2a62b386 | ||
|
|
a6c0edd4f4 | ||
|
|
ff43d35aee | ||
|
|
70fca205be | ||
|
|
1033130b6c | ||
|
|
8cfcd9ff63 | ||
|
|
80a6c16dcc | ||
|
|
553c4c99cc | ||
|
|
4165c1331b | ||
|
|
b2690415bf | ||
|
|
011f8cf1d0 | ||
|
|
2748fb81e2 | ||
|
|
46312909d9 | ||
|
|
41adecad14 | ||
|
|
ea5d8c56a0 | ||
|
|
d242cbffa4 | ||
|
|
1c8855ed10 | ||
|
|
ea33a01303 | ||
|
|
18b1d1424e | ||
|
|
1176cd58c9 | ||
|
|
44a4643b62 | ||
|
|
ed96efd865 | ||
|
|
e3093b532c | ||
|
|
9560658c5b | ||
|
|
37a70d39e0 | ||
|
|
72fac0810c | ||
|
|
c166c07a93 | ||
|
|
39a625ff72 | ||
|
|
ad32ca18a7 | ||
|
|
efea282396 | ||
|
|
33d6a01cd3 | ||
|
|
d290630d31 | ||
|
|
d2ad5dc073 | ||
|
|
68ab5127af | ||
|
|
089a11f340 | ||
|
|
de1d04eb66 |
No files matched your search
@@ -8,6 +8,82 @@ version 2.87
|
||||
Add --nftset option, like --ipset but for the newer nftables.
|
||||
Thanks to Chen Zhenge for the patch.
|
||||
|
||||
Add --filter-A and --filter-AAAA options, to remove IPv4 or IPv6
|
||||
addresses from DNS answers.
|
||||
|
||||
Fix crash doing netbooting when --port is set to zero
|
||||
to disable the DNS server. Thanks to Drexl Johannes
|
||||
for the bug report.
|
||||
|
||||
Generalise --dhcp-relay. Sending via broadcast/multicast is
|
||||
now supported for both IPv4 and IPv6 and the configuration
|
||||
syntax made easier (but backwards compatible).
|
||||
|
||||
Add snooping of IPv6 prefix-delegations to the DHCP-relay system.
|
||||
|
||||
Finesse parsing of --dhcp-remoteid and --dhcp-subscrid. To be treated
|
||||
as hex, the pattern must consist of only hex digits AND contain
|
||||
at least one ':'. Thanks to Bengt-Erik Sandstrom who tripped
|
||||
over a pattern consisting of a decimal number which was interpreted
|
||||
surprisingly.
|
||||
|
||||
Include client address in TFTP file-not-found error reports.
|
||||
Thanks to Stefan Rink for the initial patch, which has been
|
||||
re-worked by me (srk). All bugs mine.
|
||||
|
||||
Note in manpage the change in behaviour of -address. This behaviour
|
||||
actually changed in v2.86, but was undocumented there. From 2.86 on,
|
||||
(eg) --address=/example.com/1.2.3.4 ONLY applies to A queries. All other
|
||||
types of query will be sent upstream. Pre 2.86, that would catch the
|
||||
whole example.com domain and queries for other types would get
|
||||
a local NODATA answer. The pre-2.86 behaviour is still available,
|
||||
by configuring --address=/example.com/1.2.3.4 --local=/example.com/
|
||||
|
||||
Fix problem with binding DHCP sockets to an individual interface.
|
||||
Despite the fact that the system call tales the interface _name_ as
|
||||
a parameter, it actually, binds the socket to interface _index_.
|
||||
Deleting the interface and creating a new one with the same name
|
||||
leaves the socket bound to the old index. (Creating new sockets
|
||||
always allocates a fresh index, they are not reused). We now
|
||||
take this behaviour into account and keep up with changing indexes.
|
||||
|
||||
Add --conf-script configuration option.
|
||||
|
||||
Enhance --domain to accept, for instance,
|
||||
--domain=net2.thekelleys.org.uk,eth2 so that hosts get a domain
|
||||
which relects the interface they are attached to in a way which
|
||||
doesn't require hard-coding addresses. Thanks to Sten Spans for
|
||||
the idea.
|
||||
|
||||
Fix write-after-free error in DHCPv6 server code.
|
||||
CVE-2022-0934 refers.
|
||||
|
||||
Add the ability to specify destination port in
|
||||
DHCP-relay mode. This change also removes a previous bug
|
||||
where --dhcp-alternate-port would affect the port used
|
||||
to relay _to_ as well as the port being listened on.
|
||||
The new feature allows configuration to provide bug-for-bug
|
||||
compatibility, if required. Thanks to Damian Kaczkowski
|
||||
for the feature suggestion.
|
||||
|
||||
Bound the value of UDP packet size in the EDNS0 header of
|
||||
forwarded queries to the configured or default value of
|
||||
edns-packet-max. There's no point letting a client set a larger
|
||||
value if we're unable to return the answer. Thanks to Bertie
|
||||
Taylor for pointing out the problem and supplying the patch.
|
||||
|
||||
Fix problem with the configuration
|
||||
|
||||
--server=/some.domain/# --address=/#/<ip> --server=<server_ip>
|
||||
|
||||
This would return <ip> for queries in some.domain, rather than
|
||||
forwarding the query via the default server.
|
||||
|
||||
Tweak DHCPv6 relay code so that packets relayed towards a server
|
||||
have source address on the server-facing network, not the
|
||||
client facing network. Thanks to Luis Thomas for spotting this
|
||||
and initial patch.
|
||||
|
||||
|
||||
version 2.86
|
||||
Handle DHCPREBIND requests in the DHCPv6 server code.
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -225,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -291,7 +291,7 @@ convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -303,17 +303,16 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -1,4 +1,4 @@
|
||||
# dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
# dnsmasq is Copyright (c) 2000-2022 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,6 +0,0 @@
|
||||
This packaging is now unmaintained in the dnsmasq source: dnsmasq is
|
||||
included in Suse proper, and up-to-date packages are now available
|
||||
from
|
||||
|
||||
ftp://ftp.suse.com/pub/people/ug/
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
|
||||
It fixes the dependency from the dns daemon name 'named'
|
||||
After appending the patch, the SuSEfirewall is again able to autodetect
|
||||
the dnsmasq named service.
|
||||
This is a very old bug in the SuSEfirewall script.
|
||||
The SuSE people think the name of the dns server will always 'named'
|
||||
|
||||
|
||||
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
|
||||
+++ /sbin/SuSEfirewall2 2004-01-23 13:31:56.000000000 +0100
|
||||
@@ -764,7 +764,7 @@
|
||||
echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
|
||||
|
||||
test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
|
||||
- test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
|
||||
+ test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
|
||||
echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
|
||||
You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
|
||||
FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
|
||||
@@ -878,7 +878,7 @@
|
||||
test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
|
||||
# Get ports/IP bindings of NAMED/SQUID
|
||||
test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
|
||||
- $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
||||
+ $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
||||
test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
|
||||
$AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`
|
||||
@@ -1,23 +0,0 @@
|
||||
--- man/dnsmasq.8 2004-08-08 20:57:56.000000000 +0200
|
||||
+++ man/dnsmasq.8 2004-08-12 00:40:01.000000000 +0200
|
||||
@@ -69,7 +69,7 @@
|
||||
.TP
|
||||
.B \-g, --group=<groupname>
|
||||
Specify the group which dnsmasq will run
|
||||
-as. The defaults to "dip", if available, to facilitate access to
|
||||
+as. The defaults to "dialout", if available, to facilitate access to
|
||||
/etc/ppp/resolv.conf which is not normally world readable.
|
||||
.TP
|
||||
.B \-v, --version
|
||||
--- src/config.h 2004-08-11 11:39:18.000000000 +0200
|
||||
+++ src/config.h 2004-08-12 00:40:01.000000000 +0200
|
||||
@@ -44,7 +44,7 @@
|
||||
#endif
|
||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
||||
#define CHUSER "nobody"
|
||||
-#define CHGRP "dip"
|
||||
+#define CHGRP "dialout"
|
||||
#define DHCP_SERVER_PORT 67
|
||||
#define DHCP_CLIENT_PORT 68
|
||||
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
###############################################################################
|
||||
#
|
||||
# General
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
Name: dnsmasq
|
||||
Version: 2.33
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: Productivity/Networking/DNS/Servers
|
||||
Vendor: Simon Kelley
|
||||
Packager: Simon Kelley
|
||||
URL: http://www.thekelleys.org.uk/dnsmasq
|
||||
Provides: dns_daemon
|
||||
Conflicts: bind bind8 bind9
|
||||
PreReq: %fillup_prereq %insserv_prereq
|
||||
Autoreqprov: on
|
||||
Source0: %{name}-%{version}.tar.bz2
|
||||
BuildRoot: /var/tmp/%{name}-%{version}
|
||||
Summary: A lightweight caching nameserver
|
||||
|
||||
%description
|
||||
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
|
||||
is designed to provide DNS and, optionally, DHCP, to a small network. It can
|
||||
serve the names of local machines which are not in the global DNS. The DHCP
|
||||
server integrates with the DNS server and allows machines with DHCP-allocated
|
||||
addresses to appear in the DNS with names configured either in each host or
|
||||
in a central configuration file. Dnsmasq supports static and dynamic DHCP
|
||||
leases and BOOTP for network booting of diskless machines.
|
||||
|
||||
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Build
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
patch -p0 <rpm/%{name}-SuSE.patch
|
||||
|
||||
%build
|
||||
%{?suse_update_config:%{suse_update_config -f}}
|
||||
make all-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Install
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
|
||||
make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
||||
install -o root -g root -m 755 rpm/rc.dnsmasq-suse $RPM_BUILD_ROOT/etc/init.d/dnsmasq
|
||||
install -o root -g root -m 644 dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
||||
strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
|
||||
ln -sf ../../etc/init.d/dnsmasq $RPM_BUILD_ROOT/usr/sbin/rcdnsmasq
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Clean up
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Post-install scriptlet
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%post
|
||||
%{fillup_and_insserv dnsmasq}
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Post-uninstall scriptlet
|
||||
#
|
||||
# The %postun script executes after the package has been removed. It is the
|
||||
# last chance for a package to clean up after itself.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%postun
|
||||
%{insserv_cleanup}
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# File list
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
|
||||
%doc contrib
|
||||
%config /etc/init.d/dnsmasq
|
||||
%config /etc/dnsmasq.conf
|
||||
/usr/sbin/rcdnsmasq
|
||||
/usr/sbin/dnsmasq
|
||||
/usr/share/locale/*/LC_MESSAGES/*
|
||||
%doc %{_mandir}/man8/dnsmasq.8.gz
|
||||
%doc %{_mandir}/*/man8/dnsmasq.8.gz
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#! /bin/sh
|
||||
#
|
||||
# init.d/dnsmasq
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: dnsmasq
|
||||
# Required-Start: $network $remote_fs $syslog
|
||||
# Required-Stop:
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop:
|
||||
# Description: Starts internet name service masq caching server (DNS)
|
||||
### END INIT INFO
|
||||
|
||||
NAMED_BIN=/usr/sbin/dnsmasq
|
||||
NAMED_PID=/var/run/dnsmasq.pid
|
||||
NAMED_CONF=/etc/dnsmasq.conf
|
||||
|
||||
if [ ! -x $NAMED_BIN ] ; then
|
||||
echo -n "dnsmasq not installed ! "
|
||||
exit 5
|
||||
fi
|
||||
|
||||
. /etc/rc.status
|
||||
rc_reset
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
if [ $? -eq 0 ] ; then
|
||||
echo -n "- Warning: dnsmasq already running ! "
|
||||
else
|
||||
[ -e $NAMED_PID ] && echo -n "- Warning: $NAMED_PID exists ! "
|
||||
fi
|
||||
startproc -p $NAMED_PID $NAMED_BIN -u nobody
|
||||
rc_status -v
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
||||
killproc -p $NAMED_PID -TERM $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
try-restart)
|
||||
$0 stop && $0 start
|
||||
rc_status
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
rc_status
|
||||
;;
|
||||
force-reload)
|
||||
$0 reload
|
||||
rc_status
|
||||
;;
|
||||
reload)
|
||||
echo -n "Reloading name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
||||
killproc -p $NAMED_PID -HUP $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
status)
|
||||
echo -n "Checking for name service masq caching server "
|
||||
checkproc -p $NAMED_PID $NAMED_BIN
|
||||
rc_status -v
|
||||
;;
|
||||
probe)
|
||||
test $NAMED_CONF -nt $NAMED_PID && echo reload
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
rc_exit
|
||||
|
||||
@@ -48,6 +48,10 @@ SetBogusPrivOption
|
||||
------------------
|
||||
Takes boolean, sets or resets the --bogus-priv option.
|
||||
|
||||
SetLocaliseQueriesOption
|
||||
------------------------
|
||||
Takes boolean, sets or resets the --localise-queries option.
|
||||
|
||||
SetServers
|
||||
----------
|
||||
Returns nothing. Takes a set of arguments representing the new
|
||||
|
||||
Vendored
+12
-2
@@ -1,10 +1,20 @@
|
||||
dnsmasq (2.87-1) unstable; urgency=low
|
||||
|
||||
* New upstream.
|
||||
* Include new NFTset support in the build.
|
||||
* New upstream. (closes: #1001209, #1003156)
|
||||
* Include new NFTset support in the build.
|
||||
* Fix crash on netboot with DNS server disabled. (closes: #996332)
|
||||
* Fix rare lockup in DNSSEC. (closes: #1001576)
|
||||
* Close old bug. (closes: #902963)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 08 Sep 2021 23:11:25 +0000
|
||||
|
||||
dnsmasq (2.86-1.1) unstable; urgency=medium
|
||||
|
||||
* Non-maintainer upload.
|
||||
* Fix --address=/#/...... which was lost in 2.86. (closes: #995655)
|
||||
|
||||
-- Michael Biebl <biebl@debian.org> Wed, 10 Nov 2021 22:05:45 +0100
|
||||
|
||||
dnsmasq (2.86-1) unstable; urgency=low
|
||||
|
||||
* Fix debian/changelog format error. (closes: #986626)
|
||||
|
||||
+95
-25
@@ -304,7 +304,8 @@ Return answers to DNS queries from /etc/hosts and \fB--interface-name\fP and \fB
|
||||
received. If a name has more than one address associated with
|
||||
it, and at least one of those addresses is on the same subnet as the
|
||||
interface to which the query was sent, then return only the
|
||||
address(es) on that subnet. This allows for a server to have multiple
|
||||
address(es) on that subnet and return all the available addresses otherwise.
|
||||
This allows for a server to have multiple
|
||||
addresses in /etc/hosts corresponding to each of its interfaces, and
|
||||
hosts will get the correct address based on which network they are
|
||||
attached to. Currently this facility is limited to IPv4.
|
||||
@@ -345,8 +346,15 @@ forged answer to a DNS request for certain domain, before the correct answer can
|
||||
.B \-f, --filterwin2k
|
||||
Later versions of windows make periodic DNS requests which don't get sensible answers from
|
||||
the public DNS and can cause problems by triggering dial-on-demand links. This flag turns on an option
|
||||
to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the
|
||||
requested name has underscores, to catch LDAP requests.
|
||||
to filter such requests. The requests blocked are for records of type ANY
|
||||
where the requested name has underscores, to catch LDAP requests, and for
|
||||
\fBall\fP records of types SOA and SRV.
|
||||
.TP
|
||||
.B --filter-A
|
||||
Remove A records from answers. No IPv4 addresses will be returned.
|
||||
.TP
|
||||
.B --filter-AAAA
|
||||
Remove AAAA records from answers. No IPv6 addresses will be returned.
|
||||
.TP
|
||||
.B \-r, --resolv-file=<file>
|
||||
Read the IP addresses of the upstream nameservers from <file>, instead of
|
||||
@@ -516,11 +524,9 @@ Allowed prefix lengths are 1-32 (IPv4) and 1-128 (IPv6). If the prefix length is
|
||||
.TP
|
||||
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
|
||||
Specify an IP address to return for any host in the given domains.
|
||||
Queries in the domains are never forwarded and always replied to
|
||||
A (or AAAA) queries in the domains are never forwarded and always replied to
|
||||
with the specified IP address which may be IPv4 or IPv6. To give
|
||||
both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
|
||||
To include multiple IP addresses for a single query, use
|
||||
\fB--addn-hosts=<path>\fP instead.
|
||||
multiple addresses or both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
|
||||
Note that /etc/hosts and DHCP leases override this for individual
|
||||
names. A common use of this is to redirect the entire doubleclick.net
|
||||
domain to some friendly local web server to avoid banner ads. The
|
||||
@@ -538,6 +544,11 @@ address of 0.0.0.0 and its IPv6 equivalent of :: so
|
||||
its subdomains. This is partly syntactic sugar for \fB--address=/example.com/0.0.0.0\fP
|
||||
and \fB--address=/example.com/::\fP but is also more efficient than including both
|
||||
as separate configuration lines. Note that NULL addresses normally work in the same way as localhost, so beware that clients looking up these names are likely to end up talking to themselves.
|
||||
|
||||
Note that the behaviour for queries which don't match the specified address literal changed in version 2.86.
|
||||
Previous versions, configured with (eg) --address=/example.com/1.2.3.4 and then queried for a RR type other than
|
||||
A would return a NoData answer. From 2.86, the query is sent upstream. To restore the pre-2.86 behaviour,
|
||||
use the configuration --address=/example.com/1.2.3.4 --local=/example.com/
|
||||
.TP
|
||||
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
|
||||
Places the resolved IP addresses of queries for one or more domains in
|
||||
@@ -724,7 +735,7 @@ Specify the location of a pcap-format file which dnsmasq uses to dump copies of
|
||||
.TP
|
||||
.B --dumpmask=<mask>
|
||||
Specify which types of packets should be added to the dumpfile. The argument should be the OR of the bitmasks for each type of packet to be dumped: it can be specified in hex by preceding the number with 0x in the normal way. Each time a packet is written to the dumpfile, dnsmasq logs the packet sequence and the mask
|
||||
representing its type. The current types are: 0x0001 - DNS queries from clients 0x0002 DNS replies to clients 0x0004 - DNS queries to upstream 0x0008 - DNS replies from upstream 0x0010 - queries send upstream for DNSSEC validation 0x0020 - replies to queries for DNSSEC validation 0x0040 - replies to client queries which fail DNSSEC validation 0x0080 replies to queries for DNSSEC validation which fail validation.
|
||||
representing its type. The current types are: 0x0001 - DNS queries from clients, 0x0002 DNS replies to clients, 0x0004 - DNS queries to upstream, 0x0008 - DNS replies from upstream, 0x0010 - queries send upstream for DNSSEC validation, 0x0020 - replies to queries for DNSSEC validation, 0x0040 - replies to client queries which fail DNSSEC validation, 0x0080 replies to queries for DNSSEC validation which fail validation, 0x1000 - DHCPv4, 0x2000 - DHCPv6, 0x4000 - Router advertisement, 0x8000 - TFTP.
|
||||
.TP
|
||||
.B --add-mac[=base64|text]
|
||||
Add the MAC address of the requestor to DNS queries which are
|
||||
@@ -737,6 +748,9 @@ have security and privacy implications. The warning about caching
|
||||
given for \fB--add-subnet\fP applies to \fB--add-mac\fP too. An alternative encoding of the
|
||||
MAC, as base64, is enabled by adding the "base64" parameter and a human-readable encoding of hex-and-colons is enabled by added the "text" parameter.
|
||||
.TP
|
||||
.B --strip-mac
|
||||
Remove any MAC address information already in downstream queries before forwarding upstream.
|
||||
.TP
|
||||
.B --add-cpe-id=<string>
|
||||
Add an arbitrary identifying string to DNS queries which are
|
||||
forwarded upstream.
|
||||
@@ -762,12 +776,18 @@ will add 1.2.3.0/24 for IPv4 requestors and ::/0 for IPv6 requestors.
|
||||
.B --add-subnet=1.2.3.4/24,1.2.3.4/24
|
||||
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
|
||||
.TP
|
||||
.B --umbrella[=deviceid:<deviceid>[,orgid:<orgid>]]
|
||||
.B --strip-subnet
|
||||
Remove any subnet address already present in a downstream query before forwarding it upstream. If --add-subnet is set this also
|
||||
ensures that any downstream-provided subnet is replaced by the one added by dnsmasq. Otherwise, dnsmasq will NOT replace an
|
||||
existing subnet in the query.
|
||||
.TP
|
||||
.B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]]
|
||||
Embeds the requestor's IP address in DNS queries forwarded upstream.
|
||||
If device id or organization id are specified, the information is
|
||||
If device id or, asset id or organization id are specified, the information is
|
||||
included in the forwarded queries and may be able to be used in
|
||||
filtering policies and reporting. The order of the deviceid and orgid
|
||||
attributes is irrelevant, but must be separated by a comma.
|
||||
filtering policies and reporting. The order of the id
|
||||
attributes is irrelevant, but they must be separated by a comma. Deviceid is
|
||||
a sixteen digit hexadecimal number, org and asset ids are decimal numbers.
|
||||
.TP
|
||||
.B \-c, --cache-size=<cachesize>
|
||||
Set the size of dnsmasq's cache. The default is 150 names. Setting the cache size to zero disables caching. Note: huge cache size impacts performance.
|
||||
@@ -1322,7 +1342,7 @@ DHCP options. This make extra space available in the DHCP packet for
|
||||
options but can, rarely, confuse old or broken clients. This flag
|
||||
forces "simple and safe" behaviour to avoid problems in such a case.
|
||||
.TP
|
||||
.B --dhcp-relay=<local address>,<server address>[,<interface]
|
||||
.B --dhcp-relay=<local address>[,<server address>[#<server port>]][,<interface]
|
||||
Configure dnsmasq to do DHCP relay. The local address is an address
|
||||
allocated to an interface on the host running dnsmasq. All DHCP
|
||||
requests arriving on that interface will we relayed to a remote DHCP
|
||||
@@ -1330,10 +1350,12 @@ server at the server address. It is possible to relay from a single local
|
||||
address to multiple remote servers by using multiple \fB--dhcp-relay\fP
|
||||
configs with the same local address and different server
|
||||
addresses. A server address must be an IP literal address, not a
|
||||
domain name. In the case of DHCPv6, the server address may be the
|
||||
ALL_SERVERS multicast address, ff05::1:3. In this case the interface
|
||||
must be given, not be wildcard, and is used to direct the multicast to the
|
||||
correct interface to reach the DHCP server.
|
||||
domain name. If the server address is omitted, the request will be
|
||||
forwarded by broadcast (IPv4) or multicast (IPv6). In this case the interface
|
||||
must be given and not be wildcard. The server address may specify a non-standard
|
||||
port to relay to. If this is used then \fB--dhcp-proxy\fP should likely also be set,
|
||||
otherwise parts of the DHCP conversation which do not pass through the relay
|
||||
will be delivered to the wrong port.
|
||||
|
||||
Access control for DHCP clients has the same rules as for the DHCP
|
||||
server, see \fB--interface\fP, \fB--except-interface\fP, etc. The optional
|
||||
@@ -1353,6 +1375,11 @@ supported: the relay function will take precedence.
|
||||
|
||||
Both DHCPv4 and DHCPv6 relay is supported. It's not possible to relay
|
||||
DHCPv4 to a DHCPv6 server or vice-versa.
|
||||
|
||||
The DHCP relay function for IPv6 includes the ability to snoop
|
||||
prefix-delegation from relayed DHCP transactions. See
|
||||
.B --dhcp-script
|
||||
for details.
|
||||
.TP
|
||||
.B \-U, --dhcp-vendorclass=set:<tag>,[enterprise:<IANA-enterprise number>,]<vendor-class>
|
||||
Map from a vendor-class string to a tag. Most DHCP clients provide a
|
||||
@@ -1688,7 +1715,13 @@ If dnsmasq was compiled with HAVE_BROKEN_RTC, then
|
||||
the length of the lease (in seconds) is stored in
|
||||
DNSMASQ_LEASE_LENGTH, otherwise the time of lease expiry is stored in
|
||||
DNSMASQ_LEASE_EXPIRES. The number of seconds until lease expiry is
|
||||
always stored in DNSMASQ_TIME_REMAINING.
|
||||
always stored in DNSMASQ_TIME_REMAINING.
|
||||
|
||||
DNSMASQ_DATA_MISSING is set to "1" during "old" events for existing
|
||||
leases generated at startup to indicate that data not stored in the
|
||||
persistent lease database will not be present. This comprises everything
|
||||
other than IP address, hostname, MAC address, DUID, IAID and lease length
|
||||
or expiry time.
|
||||
|
||||
If a lease used to have a hostname, which is
|
||||
removed, an "old" event is generated with the new state of the lease,
|
||||
@@ -1710,6 +1743,11 @@ DNSMASQ_LOG_DHCP is set if
|
||||
.B --log-dhcp
|
||||
is in effect.
|
||||
|
||||
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
|
||||
|
||||
DNSMASQ_MUD_URL the Manufacturer Usage Description URL if provided by the client. (See RFC8520 for details.)
|
||||
|
||||
|
||||
For IPv4 only:
|
||||
|
||||
DNSMASQ_CLIENT_ID if the host provided a client-id.
|
||||
@@ -1719,8 +1757,6 @@ DHCP relay-agent added any of these options.
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS.
|
||||
|
||||
DNSMASQ_REQUESTED_OPTIONS a string containing the decimal values in the Parameter Request List option, comma separated, if the parameter request list option is provided by the client.
|
||||
|
||||
For IPv6 only:
|
||||
|
||||
If the client provides vendor-class, DNSMASQ_VENDOR_CLASS_ID,
|
||||
@@ -1763,15 +1799,25 @@ receives a HUP signal, the script will be invoked for existing leases
|
||||
with an "old" event.
|
||||
|
||||
|
||||
There are four further actions which may appear as the first argument
|
||||
to the script, "init", "arp-add", "arp-del" and "tftp". More may be added in the future, so
|
||||
There are five further actions which may appear as the first argument
|
||||
to the script, "init", "arp-add", "arp-del", "relay-snoop" and "tftp".
|
||||
More may be added in the future, so
|
||||
scripts should be written to ignore unknown actions. "init" is
|
||||
described below in
|
||||
.B --leasefile-ro
|
||||
|
||||
The "tftp" action is invoked when a TFTP file transfer completes: the
|
||||
arguments are the file size in bytes, the address to which the file
|
||||
was sent, and the complete pathname of the file.
|
||||
|
||||
|
||||
The "relay-snoop" action is invoked when dnsmasq is configured as a DHCP
|
||||
relay for DHCPv6 and it relays a prefx delegation to a client. The arguments
|
||||
are the name of the interface where the client is conected, its (link-local)
|
||||
address on that interface and the delegated prefix. This information is
|
||||
sufficient to install routes to the delegated prefix of a router. See
|
||||
.B --dhcp-relay
|
||||
for more details on configuring DHCP relay.
|
||||
|
||||
The "arp-add" and "arp-del" actions are only called if enabled with
|
||||
.B --script-arp
|
||||
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
|
||||
@@ -1902,7 +1948,7 @@ is the address of the relay and the second, as before, specifies an extra subnet
|
||||
addresses may be allocated from.
|
||||
|
||||
.TP
|
||||
.B \-s, --domain=<domain>[,<address range>[,local]]
|
||||
.B \-s, --domain=<domain>[[,<address range>[,local]]|<interface>]
|
||||
Specifies DNS domains for the DHCP server. Domains may be be given
|
||||
unconditionally (without the IP range) or for limited IP ranges. This has two effects;
|
||||
firstly it causes the DHCP server to return the domain to any hosts
|
||||
@@ -1936,6 +1982,11 @@ additional flag "local" may be supplied which has the effect of adding
|
||||
is identical to
|
||||
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
||||
.B --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
||||
|
||||
The address range can also be given as a network interface name, in which case
|
||||
all of the subnets currently assigned to the interface are used in matching the
|
||||
address. This allows hosts on different physical subnets to be given different
|
||||
domains in a way which updates automatically as the interface addresses change.
|
||||
.TP
|
||||
.B --dhcp-fqdn
|
||||
In the default mode, dnsmasq inserts the unqualified names of
|
||||
@@ -2108,6 +2159,23 @@ A special case of
|
||||
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
|
||||
in the configuration file included. Secondly, the file is re-read and the configuration
|
||||
therein is updated when dnsmasq receives SIGHUP.
|
||||
.TP
|
||||
.B \--conf-script=<file>[ <arg]
|
||||
Execute <file>, and treat what it emits to stdout as the contents of a configuration file.
|
||||
If the script exits with a non-zero exit code, dnsmasq treats this as a fatal error.
|
||||
The script can be passed arguments, space seperated from the filename and each other so, for instance
|
||||
.B --conf-dir="/etc/dnsmasq-uncompress-ads /share/ads-domains.gz"
|
||||
|
||||
with /etc/dnsmasq-uncompress-ads containing
|
||||
|
||||
set -e
|
||||
|
||||
zcat ${1} | sed -e "s:^:address=/:" -e "s:$:/:"
|
||||
|
||||
exit 0
|
||||
|
||||
and /share/ads-domains.gz containing a compressed
|
||||
list of ad server domains will save disk space with large ad-server blocklists.
|
||||
.SH CONFIG FILE
|
||||
At startup, dnsmasq reads
|
||||
.I /etc/dnsmasq.conf,
|
||||
@@ -2504,7 +2572,9 @@ file/directory, permissions).
|
||||
5 - Other miscellaneous problem.
|
||||
.PP
|
||||
11 or greater - a non zero return code was received from the
|
||||
lease-script process "init" call. The exit code from dnsmasq is the
|
||||
lease-script process "init" call or a
|
||||
.B \--conf-script
|
||||
file. The exit code from dnsmasq is the
|
||||
script's exit code with 10 added.
|
||||
|
||||
.SH LIMITS
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#
|
||||
# This revised version is (C) Copyright by
|
||||
# Matthias Andree <matthias.andree@gmx.de>, 2010 - 2021.
|
||||
# Conrad Kostecki <ck@conrad-kostecki.de>, 2014 - 2020.
|
||||
# Conrad Kostecki <conrad@kostecki.com>, 2014 - 2022.
|
||||
# It is subject to the GNU General Public License v2,
|
||||
# or at your option, any later version.
|
||||
#
|
||||
@@ -10,17 +10,18 @@
|
||||
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: dnsmasq 2.85rc2\n"
|
||||
"Project-Id-Version: dnsmasq 2.87test8\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-03-20 00:00+0000\n"
|
||||
"PO-Revision-Date: 2021-03-27 15:30+0100\n"
|
||||
"Last-Translator: Matthias Andree <matthias.andree@gmx.de>\n"
|
||||
"PO-Revision-Date: 2022-02-28 14:49+0100\n"
|
||||
"Last-Translator: Conrad Kostecki <conrad@kostecki.com>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 3.0.1\n"
|
||||
|
||||
#: cache.c:572
|
||||
msgid "Internal error in cache."
|
||||
@@ -243,7 +244,7 @@ msgstr "RFC3993 \"subscriber-id\" auf Marke abbilden."
|
||||
|
||||
#: option.c:400
|
||||
msgid "Specify vendor class to match for PXE requests."
|
||||
msgstr "Herstellerklasse für Vergleich von PXE-Anforderungen angeben"
|
||||
msgstr "Herstellerklasse für Vergleich von PXE-Anforderungen angeben."
|
||||
|
||||
#: option.c:401
|
||||
msgid "Don't do DHCP for hosts with tag set."
|
||||
@@ -726,11 +727,11 @@ msgstr "Spezifiziere IPSets, zu denen passende Domains hinzugefügt werden solle
|
||||
|
||||
#: option.c:517
|
||||
msgid "Enable filtering of DNS queries with connection-track marks."
|
||||
msgstr ""
|
||||
msgstr "Aktivieren Sie das Filtern von DNS-Abfragen mit \"connection-track\"-Markierungen."
|
||||
|
||||
#: option.c:518
|
||||
msgid "Set allowed DNS patterns for a connection-track mark."
|
||||
msgstr ""
|
||||
msgstr "Legen Sie zulässige DNS-Muster für eine \"connection-track\"-Markierung fest."
|
||||
|
||||
#: option.c:519
|
||||
msgid "Specify a domain and address range for synthesised names"
|
||||
@@ -819,12 +820,11 @@ msgstr "Rufe dhcp-script auf, wenn der Ablauf des Leases sich ändert."
|
||||
|
||||
#: option.c:540
|
||||
msgid "Send Cisco Umbrella identifiers including remote IP."
|
||||
msgstr ""
|
||||
msgstr "Senden Sie Cisco Umbrella-Identifikatoren einschließlich der Remote-IP."
|
||||
|
||||
#: option.c:541
|
||||
#, fuzzy
|
||||
msgid "Do not log routine TFTP."
|
||||
msgstr "Protokolliere kein Routine-DHCP."
|
||||
msgstr "Protokolliere kein Routine-TFTP."
|
||||
|
||||
#: option.c:771
|
||||
#, c-format
|
||||
@@ -867,11 +867,11 @@ msgstr "Fehlerhafter Schnittestellenname"
|
||||
|
||||
#: option.c:1192
|
||||
msgid "inappropriate vendor:"
|
||||
msgstr ""
|
||||
msgstr "Ungeeigneter Anbieter:"
|
||||
|
||||
#: option.c:1199
|
||||
msgid "inappropriate encap:"
|
||||
msgstr ""
|
||||
msgstr "Ungeeignete Kapselung:"
|
||||
|
||||
#: option.c:1225
|
||||
msgid "unsupported encapsulation for IPv6 option"
|
||||
@@ -952,28 +952,24 @@ msgid "recompile with HAVE_LUASCRIPT defined to enable Lua scripts"
|
||||
msgstr "Neuübersetzung mit HAVE_LUASCRIPT nötig, um benutzerdefinierte Lua-Skripte auszuführen"
|
||||
|
||||
#: option.c:2291 option.c:2327
|
||||
#, fuzzy
|
||||
msgid "bad prefix length"
|
||||
msgstr "fehlerhaftes Präfix"
|
||||
msgstr "fehlerhafte Präfixlänge"
|
||||
|
||||
#: option.c:2303 option.c:2348 option.c:2398
|
||||
msgid "bad prefix"
|
||||
msgstr "fehlerhaftes Präfix"
|
||||
|
||||
#: option.c:2418
|
||||
#, fuzzy
|
||||
msgid "prefix length too small"
|
||||
msgstr "Die Präfixlänge muss mindestens 64 sein"
|
||||
msgstr "Präfixlänge ist zu klein"
|
||||
|
||||
#: option.c:2697
|
||||
#, fuzzy
|
||||
msgid "Bad address in --address"
|
||||
msgstr "Adresse in Gebrauch"
|
||||
msgstr "Fehlerhafte Adresse in --address"
|
||||
|
||||
#: option.c:2751
|
||||
#, fuzzy
|
||||
msgid "bad IPv4 prefix"
|
||||
msgstr "fehlerhaftes IPv6-Präfix"
|
||||
msgstr "fehlerhaftes IPv4-Präfix"
|
||||
|
||||
#: option.c:2756 option.c:3569
|
||||
msgid "bad IPv6 prefix"
|
||||
@@ -984,9 +980,8 @@ msgid "recompile with HAVE_IPSET defined to enable ipset directives"
|
||||
msgstr "Neuübersetzung mit HAVE_IPSET nötig, um IPSet-Direktiven zu aktivieren"
|
||||
|
||||
#: option.c:2843 option.c:2861
|
||||
#, fuzzy
|
||||
msgid "recompile with HAVE_CONNTRACK defined to enable connmark-allowlist directives"
|
||||
msgstr "Neuübersetzung mit HAVE_IPSET nötig, um IPSet-Direktiven zu aktivieren"
|
||||
msgstr "Neukompilierung mit HAVE_CONNTRACK notwendig, um connmark-allowlist-Direktiven zu aktivieren"
|
||||
|
||||
#: option.c:3119
|
||||
msgid "bad port range"
|
||||
@@ -1131,7 +1126,7 @@ msgstr "unzulässige Wichtung"
|
||||
|
||||
#: option.c:4661
|
||||
msgid "Bad host-record"
|
||||
msgstr "fehlerhafter \"host-record\""
|
||||
msgstr "Fehlerhafter \"host-record\""
|
||||
|
||||
#: option.c:4700
|
||||
msgid "Bad name in host-record"
|
||||
@@ -1314,9 +1309,9 @@ msgid "Maximum number of concurrent DNS queries reached (max: %d)"
|
||||
msgstr "Höchstzahl an nebenläufiger DNS-Anfragen erreicht (max. %d)"
|
||||
|
||||
#: forward.c:2496
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "Maximum number of concurrent DNS queries to %s reached (max: %d)"
|
||||
msgstr "Höchstzahl an nebenläufiger DNS-Anfragen erreicht (max. %d)"
|
||||
msgstr "Maximale Anzahl gleichzeitiger DNS-Abfragen, die erreicht %s (max. %d)"
|
||||
|
||||
#: network.c:670
|
||||
#, c-format
|
||||
@@ -1403,9 +1398,9 @@ msgid "domain"
|
||||
msgstr "Domäne"
|
||||
|
||||
#: network.c:1607
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "using nameserver %s#%d for %s %s%s %s"
|
||||
msgstr "Benutze Namensserver %s#%d für %s %s %s"
|
||||
msgstr "benutze Namensserver %s#%d für %s %s %s %s"
|
||||
|
||||
#: network.c:1611
|
||||
#, c-format
|
||||
@@ -1423,14 +1418,14 @@ msgid "using nameserver %s#%d"
|
||||
msgstr "Benutze Namensserver %s#%d"
|
||||
|
||||
#: network.c:1630
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "using only locally-known addresses for %s"
|
||||
msgstr "Benutze nur lokal-bekannte Adressen für %s %s"
|
||||
msgstr "benutze nur lokal-bekannte Adressen für %s"
|
||||
|
||||
#: network.c:1633
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "using standard nameservers for %s"
|
||||
msgstr "Benutze standard Namensserver für %s %s"
|
||||
msgstr "benutze standard Namensserver für %s"
|
||||
|
||||
#: network.c:1637
|
||||
#, c-format
|
||||
@@ -1534,9 +1529,9 @@ msgid "DBus not available: set HAVE_DBUS in src/config.h"
|
||||
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
|
||||
|
||||
#: dnsmasq.c:456 dnsmasq.c:1228
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "UBus error: %s"
|
||||
msgstr "DBus-Fehler: %s"
|
||||
msgstr "UBus-Fehler: %s"
|
||||
|
||||
#: dnsmasq.c:459
|
||||
msgid "UBus not available: set HAVE_UBUS in src/config.h"
|
||||
@@ -1696,9 +1691,8 @@ msgid "connected to system DBus"
|
||||
msgstr "Mit System-DBus verbunden"
|
||||
|
||||
#: dnsmasq.c:1225
|
||||
#, fuzzy
|
||||
msgid "connected to system UBus"
|
||||
msgstr "Mit System-UBus verbunden"
|
||||
msgstr "mit System-UBus verbunden"
|
||||
|
||||
#: dnsmasq.c:1391
|
||||
#, c-format
|
||||
@@ -2145,13 +2139,13 @@ msgstr "nicht unterstützte Anfrage von %s"
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "Datei %s nicht gefunden"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "Datei %s nicht gefunden für %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
msgid "ignoring packet from %s (TID mismatch)"
|
||||
msgstr ""
|
||||
msgstr "Paket von %s wird ignoriert (TID-Nichtübereinstimmung)"
|
||||
|
||||
#: tftp.c:646
|
||||
#, c-format
|
||||
@@ -2378,95 +2372,95 @@ msgstr "Aktualisierung von ipset %s fehlgeschlagen: %s"
|
||||
#: pattern.c:29
|
||||
#, c-format
|
||||
msgid "[pattern.c:%d] Assertion failure: %s"
|
||||
msgstr ""
|
||||
msgstr "[pattern.c:%d] Assertion failure: %s"
|
||||
|
||||
#: pattern.c:142
|
||||
#, c-format
|
||||
msgid "Invalid DNS name: Invalid character %c."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Ungültiges Zeichen %c."
|
||||
|
||||
#: pattern.c:151
|
||||
msgid "Invalid DNS name: Empty label."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Leeres Label."
|
||||
|
||||
#: pattern.c:156
|
||||
msgid "Invalid DNS name: Label starts with hyphen."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Label beginnt mit Bindestrich."
|
||||
|
||||
#: pattern.c:170
|
||||
msgid "Invalid DNS name: Label ends with hyphen."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Bezeichnung endet mit Bindestrich."
|
||||
|
||||
#: pattern.c:176
|
||||
#, c-format
|
||||
msgid "Invalid DNS name: Label is too long (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Label ist zu lang (%zu)."
|
||||
|
||||
#: pattern.c:184
|
||||
#, c-format
|
||||
msgid "Invalid DNS name: Not enough labels (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Nicht genügend Labels (%zu)."
|
||||
|
||||
#: pattern.c:189
|
||||
msgid "Invalid DNS name: Final label is fully numeric."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: Das endgültige Label ist vollständig numerisch."
|
||||
|
||||
#: pattern.c:199
|
||||
msgid "Invalid DNS name: \"local\" pseudo-TLD."
|
||||
msgstr ""
|
||||
msgstr "Ungültiger DNS-Name: \"lokale\" Pseudo-TLD."
|
||||
|
||||
#: pattern.c:204
|
||||
#, c-format
|
||||
msgid "DNS name has invalid length (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Der DNS-Name hat eine ungültige Länge (%zu)."
|
||||
|
||||
#: pattern.c:258
|
||||
#, c-format
|
||||
msgid "Invalid DNS name pattern: Invalid character %c."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Ungültiges Zeichen %c."
|
||||
|
||||
#: pattern.c:267
|
||||
msgid "Invalid DNS name pattern: Empty label."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Leeres Label."
|
||||
|
||||
#: pattern.c:272
|
||||
msgid "Invalid DNS name pattern: Label starts with hyphen."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Bezeichnung beginnt mit Bindestrich."
|
||||
|
||||
#: pattern.c:285
|
||||
msgid "Invalid DNS name pattern: Wildcard character used more than twice per label."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Platzhalterzeichen werden mehr als zweimal pro Label verwendet."
|
||||
|
||||
#: pattern.c:295
|
||||
msgid "Invalid DNS name pattern: Label ends with hyphen."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Bezeichnung endet mit Bindestrich."
|
||||
|
||||
#: pattern.c:301
|
||||
#, c-format
|
||||
msgid "Invalid DNS name pattern: Label is too long (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Label ist zu lang (%zu)."
|
||||
|
||||
#: pattern.c:309
|
||||
#, c-format
|
||||
msgid "Invalid DNS name pattern: Not enough labels (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Nicht genügend Labels (%zu)."
|
||||
|
||||
#: pattern.c:314
|
||||
msgid "Invalid DNS name pattern: Wildcard within final two labels."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Platzhalter innerhalb der letzten beiden Labels."
|
||||
|
||||
#: pattern.c:319
|
||||
msgid "Invalid DNS name pattern: Final label is fully numeric."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: Das endgültige Label ist vollständig numerisch."
|
||||
|
||||
#: pattern.c:329
|
||||
msgid "Invalid DNS name pattern: \"local\" pseudo-TLD."
|
||||
msgstr ""
|
||||
msgstr "Ungültiges DNS-Namensmuster: \"lokale\" Pseudo-TLD."
|
||||
|
||||
#: pattern.c:334
|
||||
#, c-format
|
||||
msgid "DNS name pattern has invalid length after removing wildcards (%zu)."
|
||||
msgstr ""
|
||||
msgstr "Das DNS-Namensmuster hat nach dem Entfernen von Platzhaltern (%zu) eine ungültige Länge."
|
||||
|
||||
#: dnssec.c:206
|
||||
msgid "system time considered valid, now checking DNSSEC signature timestamps."
|
||||
@@ -2600,7 +2594,7 @@ msgstr "Von System-UBus trennen"
|
||||
#: ubus.c:179 ubus.c:326
|
||||
#, c-format
|
||||
msgid "UBus command failed: %d (%s)"
|
||||
msgstr ""
|
||||
msgstr "UBus-Befehl fehlgeschlagen: %d (%s)"
|
||||
|
||||
#: hash-questions.c:40
|
||||
msgid "Failed to create SHA-256 hash object"
|
||||
|
||||
@@ -2213,8 +2213,8 @@ msgstr "pedido no-soportado desde %s"
|
||||
|
||||
#: tftp.c:512
|
||||
#, fuzzy, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "archivo %s no encontrado"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "archivo %s no encontrado por %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
@@ -2114,7 +2114,7 @@ msgstr ""
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr ""
|
||||
|
||||
#: tftp.c:602
|
||||
|
||||
@@ -2197,8 +2197,8 @@ msgstr "requ
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "fichier %s non trouvé"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "fichier %s non trouvé pour %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
@@ -2460,8 +2460,8 @@ msgstr ""
|
||||
# OK
|
||||
#: tftp.c:512
|
||||
#, fuzzy, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "lease tak ditemukan"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "file %s tidak ditemukan untuk %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
@@ -2114,7 +2114,7 @@ msgstr ""
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr ""
|
||||
|
||||
#: tftp.c:602
|
||||
|
||||
@@ -2194,8 +2194,8 @@ msgstr ""
|
||||
|
||||
#: tftp.c:512
|
||||
#, fuzzy, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "leie ikke funnet"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "fil %s ikke funnet for %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
@@ -2149,8 +2149,8 @@ msgstr "nieobsługiwane żądanie od komputera %s"
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "plik %s nie został znaleziony"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "plik %s nie został znaleziony dla %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
+1
-1
@@ -2114,7 +2114,7 @@ msgstr ""
|
||||
|
||||
#: tftp.c:512
|
||||
#, c-format
|
||||
msgid "file %s not found"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr ""
|
||||
|
||||
#: tftp.c:602
|
||||
|
||||
@@ -2195,8 +2195,8 @@ msgstr ""
|
||||
|
||||
#: tftp.c:512
|
||||
#, fuzzy, c-format
|
||||
msgid "file %s not found"
|
||||
msgstr "împrumutul nu a fost găsit"
|
||||
msgid "file %s not found for %s"
|
||||
msgstr "fișier %s nu a fost găsit pentru %s"
|
||||
|
||||
#: tftp.c:602
|
||||
#, c-format
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+38
-24
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -413,7 +413,7 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
|
||||
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
||||
{
|
||||
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_SRV)) ||
|
||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_SRV | F_NXDOMAIN)) ||
|
||||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
||||
{
|
||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||
@@ -1399,10 +1399,12 @@ struct in_addr a_record_from_hosts(char *name, time_t now)
|
||||
struct crec *crecp = NULL;
|
||||
struct in_addr ret;
|
||||
|
||||
while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
|
||||
if (crecp->flags & F_HOSTS)
|
||||
return crecp->addr.addr4;
|
||||
|
||||
/* If no DNS service, cache not initialised. */
|
||||
if (daemon->port != 0)
|
||||
while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
|
||||
if (crecp->flags & F_HOSTS)
|
||||
return crecp->addr.addr4;
|
||||
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("No IPv4 address found for %s"), name);
|
||||
|
||||
ret.s_addr = 0;
|
||||
@@ -1674,10 +1676,8 @@ int cache_make_stat(struct txt_record *t)
|
||||
{
|
||||
/* expand buffer if necessary */
|
||||
newlen = bytes_needed + 1 + bufflen - bytes_avail;
|
||||
if (!(new = whine_malloc(newlen)))
|
||||
if (!(new = whine_realloc(buff, newlen)))
|
||||
return 0;
|
||||
memcpy(new, buff, bufflen);
|
||||
free(buff);
|
||||
p = new + (p - buff);
|
||||
lenp = p - 1;
|
||||
buff = new;
|
||||
@@ -1755,7 +1755,8 @@ void dump_cache(time_t now)
|
||||
{
|
||||
struct crec *cache ;
|
||||
int i;
|
||||
my_syslog(LOG_INFO, "Host Address Flags Expires");
|
||||
my_syslog(LOG_INFO, "Host Address Flags Expires Source");
|
||||
my_syslog(LOG_INFO, "------------------------------ ---------------------------------------- ---------- ------------------------ ------------");
|
||||
|
||||
for (i=0; i<hash_size; i++)
|
||||
for (cache = hash_table[i]; cache; cache = cache->hash_next)
|
||||
@@ -1813,7 +1814,10 @@ void dump_cache(time_t now)
|
||||
else if (cache->flags & F_DNSKEY)
|
||||
t = "K";
|
||||
#endif
|
||||
p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s ", a, t,
|
||||
else /* non-terminal */
|
||||
t = "!";
|
||||
|
||||
p += sprintf(p, "%-40.40s %s%s%s%s%s%s%s%s%s%s ", a, t,
|
||||
cache->flags & F_FORWARD ? "F" : " ",
|
||||
cache->flags & F_REVERSE ? "R" : " ",
|
||||
cache->flags & F_IMMORTAL ? "I" : " ",
|
||||
@@ -1821,14 +1825,16 @@ void dump_cache(time_t now)
|
||||
cache->flags & F_NEG ? "N" : " ",
|
||||
cache->flags & F_NXDOMAIN ? "X" : " ",
|
||||
cache->flags & F_HOSTS ? "H" : " ",
|
||||
cache->flags & F_CONFIG ? "C" : " ",
|
||||
cache->flags & F_DNSSECOK ? "V" : " ");
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
p += sprintf(p, "%lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
|
||||
p += sprintf(p, "%-24lu", cache->flags & F_IMMORTAL ? 0: (unsigned long)(cache->ttd - now));
|
||||
#else
|
||||
p += sprintf(p, "%s", cache->flags & F_IMMORTAL ? "\n" : ctime(&(cache->ttd)));
|
||||
/* ctime includes trailing \n - eat it */
|
||||
*(p-1) = 0;
|
||||
p += sprintf(p, "%-24.24s", cache->flags & F_IMMORTAL ? "" : ctime(&(cache->ttd)));
|
||||
#endif
|
||||
if(cache->flags & (F_HOSTS | F_CONFIG) && cache->uid > 0)
|
||||
p += sprintf(p, " %s", record_source(cache->uid));
|
||||
|
||||
my_syslog(LOG_INFO, "%s", daemon->namebuff);
|
||||
}
|
||||
}
|
||||
@@ -1949,12 +1955,13 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
char *source, *dest = arg;
|
||||
char *verb = "is";
|
||||
char *extra = "";
|
||||
char portstring[7]; /* space for #<portnum> */
|
||||
|
||||
if (!option_bool(OPT_LOG))
|
||||
return;
|
||||
|
||||
/* build query type string if requested */
|
||||
if(type > 0)
|
||||
if (!(flags & (F_SERVER | F_IPSET)) && type > 0)
|
||||
arg = querystr(arg, type);
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
@@ -1990,8 +1997,15 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
}
|
||||
}
|
||||
else if (flags & (F_IPV4 | F_IPV6))
|
||||
inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
|
||||
addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
{
|
||||
inet_ntop(flags & F_IPV4 ? AF_INET : AF_INET6,
|
||||
addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
if ((flags & F_SERVER) && type != NAMESERVER_PORT)
|
||||
{
|
||||
extra = portstring;
|
||||
sprintf(portstring, "#%u", type);
|
||||
}
|
||||
}
|
||||
else
|
||||
dest = arg;
|
||||
}
|
||||
@@ -2043,7 +2057,12 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
}
|
||||
else if (flags & F_AUTH)
|
||||
source = "auth";
|
||||
else if (flags & F_SERVER)
|
||||
else if (flags & F_DNSSEC)
|
||||
{
|
||||
source = arg;
|
||||
verb = "to";
|
||||
}
|
||||
else if (flags & F_SERVER)
|
||||
{
|
||||
source = "forwarded";
|
||||
verb = "to";
|
||||
@@ -2053,11 +2072,6 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
||||
source = arg;
|
||||
verb = "from";
|
||||
}
|
||||
else if (flags & F_DNSSEC)
|
||||
{
|
||||
source = arg;
|
||||
verb = "to";
|
||||
}
|
||||
else if (flags & F_IPSET)
|
||||
{
|
||||
source = type ? "ipset add" : "nftset add";
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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 @@
|
||||
#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 SAFE_PKTSZ 1232 /* "go anywhere" UDP packet size, see https://dnsflagday.net/2020/ */
|
||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+13
-3
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -52,6 +52,9 @@ const char* introspection_xml_template =
|
||||
" <method name=\"SetFilterWin2KOption\">\n"
|
||||
" <arg name=\"filterwin2k\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetLocaliseQueriesOption\">\n"
|
||||
" <arg name=\"localise-queries\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"SetBogusPrivOption\">\n"
|
||||
" <arg name=\"boguspriv\" direction=\"in\" type=\"b\"/>\n"
|
||||
" </method>\n"
|
||||
@@ -694,6 +697,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_FILTER, "filterwin2k");
|
||||
}
|
||||
else if (strcmp(method, "SetLocaliseQueriesOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_LOCALISE, "localise-queries");
|
||||
}
|
||||
else if (strcmp(method, "SetBogusPrivOption") == 0)
|
||||
{
|
||||
reply = dbus_set_bool(message, OPT_BOGUSPRIV, "bogus-priv");
|
||||
@@ -754,8 +761,11 @@ char *dbus_init(void)
|
||||
|
||||
dbus_error_init (&dbus_error);
|
||||
if (!(connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error)))
|
||||
return NULL;
|
||||
|
||||
{
|
||||
dbus_error_free(&dbus_error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(connection, FALSE);
|
||||
dbus_connection_set_watch_functions(connection, add_watch, remove_watch,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
+61
-7
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -566,12 +566,16 @@ char *whichdevice(void)
|
||||
}
|
||||
|
||||
if (found)
|
||||
return found->name;
|
||||
|
||||
{
|
||||
char *ret = safe_malloc(strlen(found->name)+1);
|
||||
strcpy(ret, found->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bindtodevice(char *device, int fd)
|
||||
static int bindtodevice(char *device, int fd)
|
||||
{
|
||||
size_t len = strlen(device)+1;
|
||||
if (len > IFNAMSIZ)
|
||||
@@ -579,7 +583,33 @@ void bindtodevice(char *device, int fd)
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
return 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bind_dhcp_devices(char *bound_device)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (bound_device)
|
||||
{
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (!daemon->relay4)
|
||||
ret |= bindtodevice(bound_device, daemon->dhcpfd);
|
||||
|
||||
if (daemon->enable_pxe && daemon->pxefd != -1)
|
||||
ret |= bindtodevice(bound_device, daemon->pxefd);
|
||||
}
|
||||
|
||||
#if defined(HAVE_DHCP6)
|
||||
if (daemon->doing_dhcp6 && !daemon->relay6)
|
||||
ret |= bindtodevice(bound_device, daemon->dhcp6fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -655,6 +685,7 @@ static const struct opttab_t {
|
||||
{ "client-machine-id", 97, 0 },
|
||||
{ "posix-timezone", 100, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||
{ "tzdb-timezone", 101, OT_NAME }, /* RFC 4833, Sec. 2 */
|
||||
{ "ipv6-only", 108, 4 | OT_DEC }, /* RFC 8925 */
|
||||
{ "subnet-select", 118, OT_INTERNAL },
|
||||
{ "domain-search", 119, OT_RFC1035_NAME },
|
||||
{ "sip-server", 120, 0 },
|
||||
@@ -985,11 +1016,34 @@ void log_context(int family, struct dhcp_context *context)
|
||||
|
||||
void log_relay(int family, struct dhcp_relay *relay)
|
||||
{
|
||||
int broadcast = relay->server.addr4.s_addr == 0;
|
||||
inet_ntop(family, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
|
||||
if (family == AF_INET && relay->port != DHCP_SERVER_PORT)
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
struct in6_addr multicast;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
|
||||
|
||||
if (family == AF_INET6)
|
||||
{
|
||||
broadcast = IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast);
|
||||
if (relay->port != DHCPV6_SERVER_PORT)
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), "#%u", relay->port);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (relay->interface)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||
{
|
||||
if (broadcast)
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s via %s"), daemon->addrbuff, relay->interface);
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||
}
|
||||
else
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
|
||||
}
|
||||
|
||||
+2
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -64,6 +64,7 @@
|
||||
#define OPTION_SIP_SERVER 120
|
||||
#define OPTION_VENDOR_IDENT 124
|
||||
#define OPTION_VENDOR_IDENT_OPT 125
|
||||
#define OPTION_MUD_URL_V4 161
|
||||
#define OPTION_END 255
|
||||
|
||||
#define SUBOPT_CIRCUIT_ID 1
|
||||
|
||||
+117
-62
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
struct iface_param {
|
||||
struct dhcp_context *current;
|
||||
struct dhcp_relay *relay;
|
||||
struct in_addr relay_local;
|
||||
int ind;
|
||||
};
|
||||
|
||||
@@ -34,7 +32,7 @@ static int complete_context(struct in_addr local, int if_index, char *label,
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
||||
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
|
||||
struct in_addr netmask, struct in_addr broadcast, void *vparam);
|
||||
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index);
|
||||
static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz);
|
||||
static struct dhcp_relay *relay_reply4(struct dhcp_packet *mess, char *arrival_interface);
|
||||
|
||||
static int make_fd(int port)
|
||||
@@ -177,11 +175,15 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
if ((sz = recv_dhcp_packet(fd, &msg)) == -1 ||
|
||||
(sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))))
|
||||
return;
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, NULL, fd);
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_LINUX_NETWORK)
|
||||
if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
|
||||
recvtime = tv.tv_sec;
|
||||
|
||||
|
||||
if (msg.msg_controllen >= sizeof(struct cmsghdr))
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
|
||||
@@ -302,12 +304,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
for (context = daemon->dhcp; context; context = context->next)
|
||||
context->current = context;
|
||||
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
relay->current = relay;
|
||||
|
||||
parm.current = NULL;
|
||||
parm.relay = NULL;
|
||||
parm.relay_local.s_addr = 0;
|
||||
parm.ind = iface_index;
|
||||
|
||||
if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL))
|
||||
@@ -329,15 +326,19 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
there is more than one address on the interface in the same subnet */
|
||||
complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
|
||||
}
|
||||
|
||||
if (relay_upstream4(iface_index, mess, (size_t)sz))
|
||||
return;
|
||||
|
||||
if (!iface_enumerate(AF_INET, &parm, complete_context))
|
||||
return;
|
||||
|
||||
/* We're relaying this request */
|
||||
if (parm.relay_local.s_addr != 0 &&
|
||||
relay_upstream4(parm.relay, mess, (size_t)sz, iface_index))
|
||||
/* Check for a relay again after iface_enumerate/complete_context has had
|
||||
chance to fill in relay->iface_index fields. This handles first time through
|
||||
and any changes in interface config. */
|
||||
if (relay_upstream4(iface_index, mess, (size_t)sz))
|
||||
return;
|
||||
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->dhcp)
|
||||
return;
|
||||
@@ -455,6 +456,17 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#elif defined(HAVE_BSD_NETWORK)
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
if (ntohs(mess->flags) & 0x8000)
|
||||
dest.sin_addr.s_addr = INADDR_BROADCAST;
|
||||
else
|
||||
dest.sin_addr = mess->yiaddr;
|
||||
dest.sin_port = htons(daemon->dhcp_client_port);
|
||||
|
||||
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
|
||||
(union mysockaddr *)&dest, fd);
|
||||
#endif
|
||||
|
||||
send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
|
||||
return;
|
||||
}
|
||||
@@ -463,6 +475,11 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
#ifdef HAVE_SOLARIS_NETWORK
|
||||
setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
|
||||
(union mysockaddr *)&dest, fd);
|
||||
#endif
|
||||
|
||||
while(retry_send(sendmsg(fd, &msg, 0)));
|
||||
|
||||
@@ -613,14 +630,9 @@ static int complete_context(struct in_addr local, int if_index, char *label,
|
||||
}
|
||||
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
if (if_index == param->ind && relay->local.addr4.s_addr == local.s_addr && relay->current == relay &&
|
||||
(param->relay_local.s_addr == 0 || param->relay_local.s_addr == local.s_addr))
|
||||
{
|
||||
relay->current = param->relay;
|
||||
param->relay = relay;
|
||||
param->relay_local = local;
|
||||
}
|
||||
|
||||
if (relay->local.addr4.s_addr == local.s_addr)
|
||||
relay->iface_index = if_index;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1061,53 +1073,96 @@ char *host_from_dns(struct in_addr addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess, size_t sz, int iface_index)
|
||||
static int relay_upstream4(int iface_index, struct dhcp_packet *mess, size_t sz)
|
||||
{
|
||||
/* ->local is same value for all relays on ->current chain */
|
||||
union all_addr from;
|
||||
|
||||
struct in_addr giaddr = mess->giaddr;
|
||||
u8 hops = mess->hops;
|
||||
struct dhcp_relay *relay;
|
||||
|
||||
if (mess->op != BOOTREQUEST)
|
||||
return 0;
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr4 = relay->local.addr4;
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
break;
|
||||
|
||||
/* No relay config. */
|
||||
if (!relay)
|
||||
return 0;
|
||||
|
||||
/* already gatewayed ? */
|
||||
if (mess->giaddr.s_addr)
|
||||
{
|
||||
/* if so check if by us, to stomp on loops. */
|
||||
if (mess->giaddr.s_addr == relay->local.addr4.s_addr)
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* plug in our address */
|
||||
mess->giaddr.s_addr = relay->local.addr4.s_addr;
|
||||
}
|
||||
for (; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
{
|
||||
union mysockaddr to;
|
||||
union all_addr from;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
return 1;
|
||||
mess->hops = hops;
|
||||
mess->giaddr = giaddr;
|
||||
|
||||
if ((mess->hops++) > 20)
|
||||
continue;
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr4 = relay->local.addr4;
|
||||
|
||||
for (; relay; relay = relay->current)
|
||||
{
|
||||
union mysockaddr to;
|
||||
|
||||
to.sa.sa_family = AF_INET;
|
||||
to.in.sin_addr = relay->server.addr4;
|
||||
to.in.sin_port = htons(daemon->dhcp_server_port);
|
||||
|
||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
/* already gatewayed ? */
|
||||
if (giaddr.s_addr)
|
||||
{
|
||||
/* if so check if by us, to stomp on loops. */
|
||||
if (giaddr.s_addr == relay->local.addr4.s_addr)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* plug in our address */
|
||||
mess->giaddr.s_addr = relay->local.addr4.s_addr;
|
||||
}
|
||||
|
||||
to.sa.sa_family = AF_INET;
|
||||
to.in.sin_addr = relay->server.addr4;
|
||||
to.in.sin_port = htons(relay->port);
|
||||
|
||||
/* Broadcasting to server. */
|
||||
if (relay->server.addr4.s_addr == 0)
|
||||
{
|
||||
struct ifreq ifr;
|
||||
|
||||
if (relay->interface)
|
||||
safe_strncpy(ifr.ifr_name, relay->interface, IF_NAMESIZE);
|
||||
|
||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||
ioctl(daemon->dhcpfd, SIOCGIFBRDADDR, &ifr) == -1)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("Cannot broadcast DHCP relay via interface %s"), relay->interface);
|
||||
continue;
|
||||
}
|
||||
|
||||
to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
{
|
||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||
union mysockaddr fromsock;
|
||||
fromsock.in.sin_port = htons(daemon->dhcp_server_port);
|
||||
fromsock.in.sin_addr = from.addr4;
|
||||
fromsock.sa.sa_family = AF_INET;
|
||||
|
||||
dump_packet_udp(DUMP_DHCP, (void *)mess, sz, &fromsock, &to, -1);
|
||||
}
|
||||
|
||||
/* Save this for replies */
|
||||
relay->iface_index = iface_index;
|
||||
}
|
||||
#endif
|
||||
|
||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
if (relay->server.addr4.s_addr == 0)
|
||||
snprintf(daemon->dhcp_buff2, DHCP_BUFF_SZ, _("broadcast via %s"), relay->interface);
|
||||
else
|
||||
inet_ntop(AF_INET, &relay->server.addr4, daemon->dhcp_buff2, DHCP_BUFF_SZ);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -55,12 +55,15 @@
|
||||
#define OPTION6_RECONF_ACCEPT 20
|
||||
#define OPTION6_DNS_SERVER 23
|
||||
#define OPTION6_DOMAIN_SEARCH 24
|
||||
#define OPTION6_IA_PD 25
|
||||
#define OPTION6_IAPREFIX 26
|
||||
#define OPTION6_REFRESH_TIME 32
|
||||
#define OPTION6_REMOTE_ID 37
|
||||
#define OPTION6_SUBSCRIBER_ID 38
|
||||
#define OPTION6_FQDN 39
|
||||
#define OPTION6_NTP_SERVER 56
|
||||
#define OPTION6_CLIENT_MAC 79
|
||||
#define OPTION6_MUD_URL 112
|
||||
|
||||
#define NTP_SUBOPTION_SRV_ADDR 1
|
||||
#define NTP_SUBOPTION_MC_ADDR 2
|
||||
|
||||
+51
-44
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -22,8 +22,7 @@
|
||||
|
||||
struct iface_param {
|
||||
struct dhcp_context *current;
|
||||
struct dhcp_relay *relay;
|
||||
struct in6_addr fallback, relay_local, ll_addr, ula_addr;
|
||||
struct in6_addr fallback, ll_addr, ula_addr;
|
||||
int ind, addr_match;
|
||||
};
|
||||
|
||||
@@ -90,7 +89,6 @@ void dhcp6_init(void)
|
||||
void dhcp6_packet(time_t now)
|
||||
{
|
||||
struct dhcp_context *context;
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param parm;
|
||||
struct cmsghdr *cmptr;
|
||||
struct msghdr msg;
|
||||
@@ -105,7 +103,8 @@ void dhcp6_packet(time_t now)
|
||||
struct iname *tmp;
|
||||
unsigned short port;
|
||||
struct in6_addr dst_addr;
|
||||
|
||||
struct in6_addr all_servers;
|
||||
|
||||
memset(&dst_addr, 0, sizeof(dst_addr));
|
||||
|
||||
msg.msg_control = control_u.control6;
|
||||
@@ -119,6 +118,11 @@ void dhcp6_packet(time_t now)
|
||||
if ((sz = recv_dhcp_packet(daemon->dhcp6fd, &msg)) == -1)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->dhcp_packet.iov_base, sz,
|
||||
(union mysockaddr *)&from, NULL, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
@@ -135,9 +139,13 @@ void dhcp6_packet(time_t now)
|
||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||
return;
|
||||
|
||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
|
||||
if (relay_reply6(&from, sz, ifr.ifr_name))
|
||||
{
|
||||
from.sin6_port = htons(port);
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL,
|
||||
(union mysockaddr *)&from, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||
sizeof(from))));
|
||||
@@ -145,7 +153,7 @@ void dhcp6_packet(time_t now)
|
||||
else
|
||||
{
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
|
||||
|
||||
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
|
||||
if (tmp->name && wildcard_match(tmp->name, ifr.ifr_name))
|
||||
return;
|
||||
@@ -155,14 +163,12 @@ void dhcp6_packet(time_t now)
|
||||
return;
|
||||
|
||||
parm.current = NULL;
|
||||
parm.relay = NULL;
|
||||
memset(&parm.relay_local, 0, IN6ADDRSZ);
|
||||
parm.ind = if_index;
|
||||
parm.addr_match = 0;
|
||||
memset(&parm.fallback, 0, IN6ADDRSZ);
|
||||
memset(&parm.ll_addr, 0, IN6ADDRSZ);
|
||||
memset(&parm.ula_addr, 0, IN6ADDRSZ);
|
||||
|
||||
|
||||
/* If the interface on which the DHCPv6 request was received is
|
||||
an alias of some other interface (as specified by the
|
||||
--bridge-interface option), change parm.ind so that we look
|
||||
@@ -200,13 +206,25 @@ void dhcp6_packet(time_t now)
|
||||
context->current = context;
|
||||
memset(&context->local6, 0, IN6ADDRSZ);
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
relay->current = relay;
|
||||
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
return;
|
||||
|
||||
if (!iface_enumerate(AF_INET6, &parm, complete_context6))
|
||||
return;
|
||||
|
||||
|
||||
/* Check for a relay again after iface_enumerate/complete_context has had
|
||||
chance to fill in relay->iface_index fields. This handles first time through
|
||||
and any changes in interface config. */
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers) &&
|
||||
relay_upstream6(if_index, (size_t)sz, &from.sin6_addr, from.sin6_scope_id, now))
|
||||
return;
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
|
||||
@@ -218,23 +236,10 @@ void dhcp6_packet(time_t now)
|
||||
return;
|
||||
}
|
||||
|
||||
if (parm.relay)
|
||||
{
|
||||
/* Ignore requests sent to the ALL_SERVERS multicast address for relay when
|
||||
we're listening there for DHCPv6 server reasons. */
|
||||
struct in6_addr all_servers;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &all_servers);
|
||||
|
||||
if (!IN6_ARE_ADDR_EQUAL(&dst_addr, &all_servers))
|
||||
relay_upstream6(parm.relay, sz, &from.sin6_addr, from.sin6_scope_id, now);
|
||||
return;
|
||||
}
|
||||
|
||||
/* May have configured relay, but not DHCP server */
|
||||
if (!daemon->doing_dhcp6)
|
||||
return;
|
||||
|
||||
|
||||
lease_prune(NULL, now); /* lose any expired leases */
|
||||
|
||||
port = dhcp6_reply(parm.current, if_index, ifr.ifr_name, &parm.fallback,
|
||||
@@ -247,11 +252,16 @@ void dhcp6_packet(time_t now)
|
||||
if (port != 0)
|
||||
{
|
||||
from.sin6_port = htons(port);
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||
sizeof(from))));
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1),
|
||||
NULL, (union mysockaddr *)&from, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&from, sizeof(from))));
|
||||
}
|
||||
|
||||
|
||||
/* These need to be called _after_ we send DHCPv6 packet, since lease_update_file()
|
||||
may trigger sending an RA packet, which overwrites our buffer. */
|
||||
lease_update_file(now);
|
||||
@@ -312,6 +322,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
struct dhcp_relay *relay;
|
||||
struct iface_param *param = vparam;
|
||||
struct iname *tmp;
|
||||
int match = !daemon->if_addrs;
|
||||
|
||||
(void)scope; /* warning */
|
||||
|
||||
@@ -333,7 +344,7 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
|
||||
if (tmp->addr.sa.sa_family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, local))
|
||||
param->addr_match = 1;
|
||||
match = param->addr_match = 1;
|
||||
|
||||
/* Determine a globally address on the arrival interface, even
|
||||
if we have no matching dhcp-context, because we're only
|
||||
@@ -405,16 +416,12 @@ static int complete_context6(struct in6_addr *local, int prefix,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6) && relay->current == relay &&
|
||||
(IN6_IS_ADDR_UNSPECIFIED(¶m->relay_local) || IN6_ARE_ADDR_EQUAL(local, ¶m->relay_local)))
|
||||
{
|
||||
relay->current = param->relay;
|
||||
param->relay = relay;
|
||||
param->relay_local = *local;
|
||||
}
|
||||
|
||||
|
||||
if (match)
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (IN6_ARE_ADDR_EQUAL(local, &relay->local.addr6))
|
||||
relay->iface_index = if_index;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+38
-25
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -17,8 +17,13 @@
|
||||
/* Declare static char *compiler_opts in config.h */
|
||||
#define DNSMASQ_COMPILE_OPTS
|
||||
|
||||
/* dnsmasq.h has to be included first as it sources config.h */
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
struct daemon *daemon;
|
||||
|
||||
static volatile pid_t pid = 0;
|
||||
@@ -69,8 +74,10 @@ int main (int argc, char **argv)
|
||||
int tftp_prefix_missing = 0;
|
||||
#endif
|
||||
|
||||
#ifdef LOCALEDIR
|
||||
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
#ifdef LOCALEDIR
|
||||
bindtextdomain("dnsmasq", LOCALEDIR);
|
||||
textdomain("dnsmasq");
|
||||
#endif
|
||||
@@ -380,28 +387,9 @@ int main (int argc, char **argv)
|
||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
|
||||
/* after enumerate_interfaces() */
|
||||
bound_device = whichdevice();
|
||||
|
||||
if (daemon->dhcp)
|
||||
{
|
||||
if (!daemon->relay4 && bound_device)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->dhcpfd);
|
||||
did_bind = 1;
|
||||
}
|
||||
if (daemon->enable_pxe && bound_device && daemon->pxefd != -1)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->pxefd);
|
||||
did_bind = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
|
||||
if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
|
||||
{
|
||||
bindtodevice(bound_device, daemon->dhcp6fd);
|
||||
did_bind = 1;
|
||||
}
|
||||
if ((did_bind = bind_dhcp_devices(bound_device)) & 2)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -727,7 +715,11 @@ int main (int argc, char **argv)
|
||||
/* 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 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
|
||||
if ((daemon->dhcp ||
|
||||
daemon->dhcp6 ||
|
||||
daemon->relay6 ||
|
||||
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
|
||||
@@ -1089,6 +1081,17 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
# if defined(HAVE_LINUX_NETWORK)
|
||||
if (bind_dhcp_devices(bound_device) & 2)
|
||||
{
|
||||
static int warned = 0;
|
||||
if (!warned)
|
||||
{
|
||||
my_syslog(LOG_ERR, _("error binding DHCP socket to device %s"), bound_device);
|
||||
warned = 1;
|
||||
}
|
||||
}
|
||||
# endif
|
||||
if (daemon->dhcp || daemon->relay4)
|
||||
{
|
||||
poll_listen(daemon->dhcpfd, POLLIN);
|
||||
@@ -1132,6 +1135,10 @@ int main (int argc, char **argv)
|
||||
while (helper_buf_empty() && do_tftp_script_run());
|
||||
# endif
|
||||
|
||||
# ifdef HAVE_DHCP6
|
||||
while (helper_buf_empty() && do_snoop_script_run());
|
||||
# endif
|
||||
|
||||
if (!helper_buf_empty())
|
||||
poll_listen(daemon->helperfd, POLLOUT);
|
||||
#else
|
||||
@@ -1658,9 +1665,10 @@ static void poll_resolv(int force, int do_reload, time_t now)
|
||||
else
|
||||
{
|
||||
res->logged = 0;
|
||||
if (force || (statbuf.st_mtime != res->mtime))
|
||||
if (force || (statbuf.st_mtime != res->mtime || statbuf.st_ino != res->ino))
|
||||
{
|
||||
res->mtime = statbuf.st_mtime;
|
||||
res->ino = statbuf.st_ino;
|
||||
if (difftime(statbuf.st_mtime, last_change) > 0.0)
|
||||
{
|
||||
last_change = statbuf.st_mtime;
|
||||
@@ -1682,6 +1690,11 @@ static void poll_resolv(int force, int do_reload, time_t now)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we're delaying things, we don't call check_servers(), but
|
||||
reload_servers() may have deleted some servers, rendering the server_array
|
||||
invalid, so just rebuild that here. Once reload_servers() succeeds,
|
||||
we call check_servers() above, which calls build_server_array itself. */
|
||||
build_server_array();
|
||||
latest->mtime = 0;
|
||||
if (!warned)
|
||||
{
|
||||
|
||||
+59
-20
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -14,7 +14,7 @@
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define COPYRIGHT "Copyright (c) 2000-2021 Simon Kelley"
|
||||
#define COPYRIGHT "Copyright (c) 2000-2022 Simon Kelley"
|
||||
|
||||
/* We do defines that influence behavior of stdio.h, so complain
|
||||
if included too early. */
|
||||
@@ -275,7 +275,11 @@ struct event_desc {
|
||||
#define OPT_UMBRELLA_DEVID 64
|
||||
#define OPT_CMARK_ALST_EN 65
|
||||
#define OPT_QUIET_TFTP 66
|
||||
#define OPT_LAST 67
|
||||
#define OPT_FILTER_A 67
|
||||
#define OPT_FILTER_AAAA 68
|
||||
#define OPT_STRIP_ECS 69
|
||||
#define OPT_STRIP_MAC 70
|
||||
#define OPT_LAST 71
|
||||
|
||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||
@@ -661,6 +665,7 @@ struct resolvc {
|
||||
struct resolvc *next;
|
||||
int is_default, logged;
|
||||
time_t mtime;
|
||||
ino_t ino;
|
||||
char *name;
|
||||
#ifdef HAVE_INOTIFY
|
||||
int wd; /* inotify watch descriptor */
|
||||
@@ -686,14 +691,18 @@ struct hostsfile {
|
||||
};
|
||||
|
||||
/* packet-dump flags */
|
||||
#define DUMP_QUERY 0x0001
|
||||
#define DUMP_REPLY 0x0002
|
||||
#define DUMP_UP_QUERY 0x0004
|
||||
#define DUMP_UP_REPLY 0x0008
|
||||
#define DUMP_SEC_QUERY 0x0010
|
||||
#define DUMP_SEC_REPLY 0x0020
|
||||
#define DUMP_BOGUS 0x0040
|
||||
#define DUMP_SEC_BOGUS 0x0080
|
||||
#define DUMP_QUERY 0x0001
|
||||
#define DUMP_REPLY 0x0002
|
||||
#define DUMP_UP_QUERY 0x0004
|
||||
#define DUMP_UP_REPLY 0x0008
|
||||
#define DUMP_SEC_QUERY 0x0010
|
||||
#define DUMP_SEC_REPLY 0x0020
|
||||
#define DUMP_BOGUS 0x0040
|
||||
#define DUMP_SEC_BOGUS 0x0080
|
||||
#define DUMP_DHCP 0x1000
|
||||
#define DUMP_DHCPV6 0x2000
|
||||
#define DUMP_RA 0x4000
|
||||
#define DUMP_TFTP 0x8000
|
||||
|
||||
/* DNSSEC status values. */
|
||||
#define STAT_SECURE 0x10000
|
||||
@@ -720,7 +729,7 @@ struct hostsfile {
|
||||
|
||||
#define FREC_NOREBIND 1
|
||||
#define FREC_CHECKING_DISABLED 2
|
||||
#define FREC_HAS_SUBNET 4
|
||||
#define FREC_NO_CACHE 4
|
||||
#define FREC_DNSKEY_QUERY 8
|
||||
#define FREC_DS_QUERY 16
|
||||
#define FREC_AD_QUESTION 32
|
||||
@@ -729,7 +738,6 @@ struct hostsfile {
|
||||
#define FREC_TEST_PKTSZ 256
|
||||
#define FREC_HAS_EXTRADATA 512
|
||||
#define FREC_HAS_PHEADER 1024
|
||||
#define FREC_NO_CACHE 2048
|
||||
|
||||
#define HASH_SIZE 32 /* SHA-256 digest size */
|
||||
|
||||
@@ -776,6 +784,7 @@ struct frec {
|
||||
#define ACTION_TFTP 5
|
||||
#define ACTION_ARP 6
|
||||
#define ACTION_ARP_DEL 7
|
||||
#define ACTION_RELAY_SNOOP 8
|
||||
|
||||
#define LEASE_NEW 1 /* newly created */
|
||||
#define LEASE_CHANGED 2 /* modified */
|
||||
@@ -967,6 +976,8 @@ struct dhcp_bridge {
|
||||
|
||||
struct cond_domain {
|
||||
char *domain, *prefix; /* prefix is text-prefix on domain name */
|
||||
char *interface; /* These two set when domain comes from interface. */
|
||||
struct addrlist *al;
|
||||
struct in_addr start, end;
|
||||
struct in6_addr start6, end6;
|
||||
int is6, indexed, prefixlen;
|
||||
@@ -1074,7 +1085,15 @@ struct dhcp_relay {
|
||||
union all_addr local, server;
|
||||
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
|
||||
int iface_index; /* working - interface in which requests arrived, for return */
|
||||
struct dhcp_relay *current, *next;
|
||||
int port; /* Port of relay we forward to. */
|
||||
#ifdef HAVE_SCRIPT
|
||||
struct snoop_record {
|
||||
struct in6_addr client, prefix;
|
||||
int prefix_len;
|
||||
struct snoop_record *next;
|
||||
} *snoop_records;
|
||||
#endif
|
||||
struct dhcp_relay *next;
|
||||
};
|
||||
|
||||
extern struct daemon {
|
||||
@@ -1225,13 +1244,18 @@ extern struct daemon {
|
||||
unsigned char *duid;
|
||||
struct iovec outpacket;
|
||||
int dhcp6fd, icmp6fd;
|
||||
# ifdef HAVE_SCRIPT
|
||||
struct snoop_record *free_snoops;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* DBus stuff */
|
||||
/* void * here to avoid depending on dbus headers outside dbus.c */
|
||||
void *dbus;
|
||||
#ifdef HAVE_DBUS
|
||||
struct watch *watches;
|
||||
#endif
|
||||
|
||||
/* UBus stuff */
|
||||
#ifdef HAVE_UBUS
|
||||
/* void * here to avoid depending on ubus headers outside ubus.c */
|
||||
@@ -1372,8 +1396,10 @@ void *safe_malloc(size_t size);
|
||||
void safe_strncpy(char *dest, const char *src, size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
void *whine_realloc(void *ptr, size_t size);
|
||||
int sa_len(union mysockaddr *addr);
|
||||
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
|
||||
int hostname_order(const char *a, const char *b);
|
||||
int hostname_isequal(const char *a, const char *b);
|
||||
int hostname_issubdomain(char *a, char *b);
|
||||
time_t dnsmasq_time(void);
|
||||
@@ -1616,6 +1642,9 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
||||
void queue_arp(int action, unsigned char *mac, int maclen,
|
||||
int family, union all_addr *addr);
|
||||
int helper_buf_empty(void);
|
||||
#ifdef HAVE_DHCP6
|
||||
void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* tftp.c */
|
||||
@@ -1658,10 +1687,13 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac,
|
||||
unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *iface_name,
|
||||
struct in6_addr *fallback, struct in6_addr *ll_addr, struct in6_addr *ula_addr,
|
||||
size_t sz, struct in6_addr *client_addr, time_t now);
|
||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
|
||||
int relay_upstream6(int iface_index, ssize_t sz, struct in6_addr *peer_address,
|
||||
u32 scope_id, time_t now);
|
||||
|
||||
unsigned short relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
|
||||
int relay_reply6( struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface);
|
||||
# ifdef HAVE_SCRIPT
|
||||
int do_snoop_script_run(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* dhcp-common.c */
|
||||
@@ -1688,7 +1720,7 @@ struct dhcp_config *find_config(struct dhcp_config *configs,
|
||||
int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type);
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
char *whichdevice(void);
|
||||
void bindtodevice(char *device, int fd);
|
||||
int bind_dhcp_devices(char *bound_device);
|
||||
#endif
|
||||
# ifdef HAVE_DHCP6
|
||||
void display_opts6(void);
|
||||
@@ -1749,7 +1781,11 @@ int do_poll(int timeout);
|
||||
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);
|
||||
|
||||
/* modes. */
|
||||
#define RRFILTER_EDNS0 0
|
||||
#define RRFILTER_DNSSEC 1
|
||||
#define RRFILTER_A 2
|
||||
#define RRFILTER_AAAA 3
|
||||
/* 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);
|
||||
@@ -1757,7 +1793,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
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 *cacheable);
|
||||
union mysockaddr *source, time_t now, int *cacheable);
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
|
||||
|
||||
/* arp.c */
|
||||
@@ -1767,7 +1803,10 @@ int do_arp_script_run(void);
|
||||
/* dump.c */
|
||||
#ifdef HAVE_DUMPFILE
|
||||
void dump_init(void);
|
||||
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst);
|
||||
void dump_packet_udp(int mask, void *packet, size_t len, union mysockaddr *src,
|
||||
union mysockaddr *dst, int fd);
|
||||
void dump_packet_icmp(int mask, void *packet, size_t len, union mysockaddr *src,
|
||||
union mysockaddr *dst);
|
||||
#endif
|
||||
|
||||
/* domain-match.c */
|
||||
|
||||
+33
-33
@@ -1851,7 +1851,7 @@ static int zone_status(char *name, int class, char *keyname, time_t now)
|
||||
STAT_NEED_DS need DS to complete validation (name is returned in keyname)
|
||||
|
||||
daemon->rr_status points to a char array which corressponds to the RRs in the
|
||||
answer and auth sections. This is set to 1 for each RR which is validated, and 0 for any which aren't.
|
||||
answer and auth sections. This is set to >1 for each RR which is validated, and 0 for any which aren't.
|
||||
|
||||
When validating replies to DS records, we're only interested in the NSEC{3} RRs in the auth section.
|
||||
Other RRs in that section missing sigs will not cause am INSECURE reply. We determine this mode
|
||||
@@ -1867,7 +1867,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx;
|
||||
int i, j, rc = STAT_INSECURE;
|
||||
int secure = STAT_SECURE;
|
||||
|
||||
|
||||
/* extend rr_status if necessary */
|
||||
if (daemon->rr_status_sz < ntohs(header->ancount) + ntohs(header->nscount))
|
||||
{
|
||||
@@ -1989,7 +1989,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
{
|
||||
/* NSEC and NSEC3 records must be signed. We make this assumption elsewhere. */
|
||||
if (type1 == T_NSEC || type1 == T_NSEC3)
|
||||
rc = STAT_INSECURE;
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NOSIG;
|
||||
else if (nons && i >= ntohs(header->ancount))
|
||||
/* If we're validating a DS reply, rather than looking for the value of AD bit,
|
||||
we only care that NSEC and NSEC3 RRs in the auth section are signed.
|
||||
@@ -2003,6 +2003,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
rc = zone_status(name, class1, keyname, now);
|
||||
if (STAT_ISEQUAL(rc, STAT_SECURE))
|
||||
rc = STAT_BOGUS | DNSSEC_FAIL_NOSIG;
|
||||
|
||||
if (class)
|
||||
*class = class1; /* Class for NEED_DS or NEED_KEY */
|
||||
}
|
||||
@@ -2081,36 +2082,35 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
}
|
||||
|
||||
/* OK, all the RRsets validate, now see if we have a missing answer or CNAME target. */
|
||||
if (STAT_ISEQUAL(secure, STAT_SECURE))
|
||||
for (j = 0; j <targetidx; j++)
|
||||
if ((p2 = targets[j]))
|
||||
{
|
||||
if (neganswer)
|
||||
*neganswer = 1;
|
||||
|
||||
if (!extract_name(header, plen, &p2, name, 1, 10))
|
||||
return STAT_BOGUS; /* bad packet */
|
||||
|
||||
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
||||
|
||||
/* For anything other than a DS record, this situation is OK if either
|
||||
the answer is in an unsigned zone, or there's a NSEC records. */
|
||||
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl))
|
||||
{
|
||||
/* Empty DS without NSECS */
|
||||
if (qtype == T_DS)
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC;
|
||||
|
||||
if (STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE))
|
||||
{
|
||||
if (class)
|
||||
*class = qclass; /* Class for NEED_DS or NEED_KEY */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC; /* signed zone, no NSECs */
|
||||
}
|
||||
}
|
||||
for (j = 0; j <targetidx; j++)
|
||||
if ((p2 = targets[j]))
|
||||
{
|
||||
if (neganswer)
|
||||
*neganswer = 1;
|
||||
|
||||
if (!extract_name(header, plen, &p2, name, 1, 10))
|
||||
return STAT_BOGUS; /* bad packet */
|
||||
|
||||
/* NXDOMAIN or NODATA reply, unanswered question is (name, qclass, qtype) */
|
||||
|
||||
/* For anything other than a DS record, this situation is OK if either
|
||||
the answer is in an unsigned zone, or there's a NSEC records. */
|
||||
if (!prove_non_existence(header, plen, keyname, name, qtype, qclass, NULL, nons, nsec_ttl))
|
||||
{
|
||||
/* Empty DS without NSECS */
|
||||
if (qtype == T_DS)
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC;
|
||||
|
||||
if (!STAT_ISEQUAL((rc = zone_status(name, qclass, keyname, now)), STAT_SECURE))
|
||||
{
|
||||
if (class)
|
||||
*class = qclass; /* Class for NEED_DS or NEED_KEY */
|
||||
return rc;
|
||||
}
|
||||
|
||||
return STAT_BOGUS | DNSSEC_FAIL_NONSEC; /* signed zone, no NSECs */
|
||||
}
|
||||
}
|
||||
|
||||
return secure;
|
||||
}
|
||||
|
||||
+105
-82
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -213,9 +213,13 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
||||
to continue generalising */
|
||||
{
|
||||
/* We've matched a setting which says to use servers without a domain.
|
||||
Continue the search with empty query */
|
||||
Continue the search with empty query. We set the F_SERVER flag
|
||||
so that --address=/#/... doesn't match. */
|
||||
if (daemon->serverarray[nlow]->flags & SERV_USE_RESOLV)
|
||||
crop_query = qlen;
|
||||
{
|
||||
crop_query = qlen;
|
||||
flags |= F_SERVER;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
@@ -299,7 +303,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_6ADDR); i++);
|
||||
|
||||
if (i != nlow && (flags & F_IPV6))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV6))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
@@ -307,7 +311,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_4ADDR); i++);
|
||||
|
||||
if (i != nlow && (flags & F_IPV4))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & F_IPV4))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
@@ -315,7 +319,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
||||
|
||||
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_ALL_ZEROS); i++);
|
||||
|
||||
if (i != nlow && (flags & (F_IPV4 | F_IPV6)))
|
||||
if (!(flags & F_SERVER) && i != nlow && (flags & (F_IPV4 | F_IPV6)))
|
||||
nhigh = i;
|
||||
else
|
||||
{
|
||||
@@ -395,7 +399,7 @@ int is_local_answer(time_t now, int first, char *name)
|
||||
|
||||
size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header *header, char *name, char *limit, int first, int last, int ede)
|
||||
{
|
||||
int trunc = 0;
|
||||
int trunc = 0, anscount = 0;
|
||||
unsigned char *p;
|
||||
int start;
|
||||
union all_addr addr;
|
||||
@@ -418,9 +422,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
else
|
||||
addr.addr4 = srv->addr;
|
||||
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
if (!add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
|
||||
return 0;
|
||||
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_A, C_IN, "4", &addr))
|
||||
anscount++;
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
|
||||
}
|
||||
|
||||
@@ -434,14 +437,15 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
||||
else
|
||||
addr.addr6 = srv->addr;
|
||||
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr);
|
||||
if (add_resource_record(header, limit, &trunc, sizeof(struct dns_header), &p, daemon->local_ttl, NULL, T_AAAA, C_IN, "6", &addr))
|
||||
anscount++;
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
|
||||
}
|
||||
|
||||
if (trunc)
|
||||
header->hb3 |= HB3_TC;
|
||||
|
||||
header->ancount = htons(anscount);
|
||||
|
||||
return p - (unsigned char *)header;
|
||||
}
|
||||
|
||||
@@ -494,7 +498,7 @@ static int order(char *qdomain, size_t qlen, struct server *serv)
|
||||
if (qlen > dlen)
|
||||
return -1;
|
||||
|
||||
return strcmp(qdomain, serv->domain);
|
||||
return hostname_order(qdomain, serv->domain);
|
||||
}
|
||||
|
||||
static int order_servers(struct server *s1, struct server *s2)
|
||||
@@ -542,22 +546,39 @@ static int order_qsort(const void *a, const void *b)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||
void mark_servers(int flag)
|
||||
{
|
||||
struct server *serv;
|
||||
struct server *serv, **up;
|
||||
|
||||
daemon->servers_tail = NULL;
|
||||
|
||||
/* mark everything with argument flag */
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
{
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
|
||||
for (serv = daemon->local_domains; serv; serv = serv->next)
|
||||
if (serv->flags & flag)
|
||||
serv->flags |= SERV_MARK;
|
||||
else
|
||||
serv->flags &= ~SERV_MARK;
|
||||
daemon->servers_tail = serv;
|
||||
}
|
||||
|
||||
/* --address etc is different: since they are expected to be
|
||||
1) numerous and 2) not reloaded often. We just delete
|
||||
and recreate. */
|
||||
if (flag)
|
||||
for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = serv->next)
|
||||
{
|
||||
if (serv->flags & flag)
|
||||
{
|
||||
*up = serv->next;
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup_servers(void)
|
||||
@@ -565,7 +586,7 @@ void cleanup_servers(void)
|
||||
struct server *serv, *tmp, **up;
|
||||
|
||||
/* unlink and free anything still marked. */
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
for (serv = daemon->servers, up = &daemon->servers, daemon->servers_tail = NULL; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
@@ -581,19 +602,6 @@ void cleanup_servers(void)
|
||||
daemon->servers_tail = serv;
|
||||
}
|
||||
}
|
||||
|
||||
for (serv = daemon->local_domains, up = &daemon->local_domains; serv; serv = tmp)
|
||||
{
|
||||
tmp = serv->next;
|
||||
if (serv->flags & SERV_MARK)
|
||||
{
|
||||
*up = serv->next;
|
||||
free(serv->domain);
|
||||
free(serv);
|
||||
}
|
||||
else
|
||||
up = &serv->next;
|
||||
}
|
||||
}
|
||||
|
||||
int add_update_server(int flags,
|
||||
@@ -626,36 +634,17 @@ int add_update_server(int flags,
|
||||
|
||||
if (!alloc_domain)
|
||||
return 0;
|
||||
|
||||
/* See if there is a suitable candidate, and unmark
|
||||
only do this for forwarding servers, not
|
||||
address or local, to avoid delays on large numbers. */
|
||||
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
for (serv = daemon->servers; serv; serv = serv->next)
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
break;
|
||||
|
||||
if (serv)
|
||||
{
|
||||
free(alloc_domain);
|
||||
alloc_domain = serv->domain;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t size;
|
||||
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
{
|
||||
if (flags & SERV_6ADDR)
|
||||
size = sizeof(struct serv_addr6);
|
||||
else if (flags & SERV_4ADDR)
|
||||
size = sizeof(struct serv_addr4);
|
||||
else
|
||||
size = sizeof(struct serv_local);
|
||||
}
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
size = sizeof(struct serv_addr6);
|
||||
else if (flags & SERV_4ADDR)
|
||||
size = sizeof(struct serv_addr4);
|
||||
else
|
||||
size = sizeof(struct server);
|
||||
size = sizeof(struct serv_local);
|
||||
|
||||
if (!(serv = whine_malloc(size)))
|
||||
{
|
||||
@@ -663,19 +652,53 @@ int add_update_server(int flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (flags & SERV_IS_LOCAL)
|
||||
serv->next = daemon->local_domains;
|
||||
daemon->local_domains = serv;
|
||||
|
||||
if (flags & SERV_4ADDR)
|
||||
((struct serv_addr4*)serv)->addr = local_addr->addr4;
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
((struct serv_addr6*)serv)->addr = local_addr->addr6;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Upstream servers. See if there is a suitable candidate, if so unmark
|
||||
and move to the end of the list, for order. The entry found may already
|
||||
be at the end. */
|
||||
struct server **up, *tmp;
|
||||
|
||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||
{
|
||||
serv->next = daemon->local_domains;
|
||||
daemon->local_domains = serv;
|
||||
tmp = serv->next;
|
||||
if ((serv->flags & SERV_MARK) &&
|
||||
hostname_isequal(alloc_domain, serv->domain))
|
||||
{
|
||||
/* Need to move down? */
|
||||
if (serv->next)
|
||||
{
|
||||
*up = serv->next;
|
||||
daemon->servers_tail->next = serv;
|
||||
daemon->servers_tail = serv;
|
||||
serv->next = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SERV_4ADDR)
|
||||
((struct serv_addr4*)serv)->addr = local_addr->addr4;
|
||||
|
||||
if (flags & SERV_6ADDR)
|
||||
((struct serv_addr6*)serv)->addr = local_addr->addr6;
|
||||
if (serv)
|
||||
{
|
||||
free(alloc_domain);
|
||||
alloc_domain = serv->domain;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(serv = whine_malloc(sizeof(struct server))))
|
||||
{
|
||||
free(alloc_domain);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(serv, 0, sizeof(struct server));
|
||||
|
||||
/* Add to the end of the chain, for order */
|
||||
@@ -684,20 +707,20 @@ int add_update_server(int flags,
|
||||
else
|
||||
daemon->servers = serv;
|
||||
daemon->servers_tail = serv;
|
||||
|
||||
}
|
||||
|
||||
#ifdef HAVE_LOOP
|
||||
serv->uid = rand32();
|
||||
serv->uid = rand32();
|
||||
#endif
|
||||
|
||||
if (interface)
|
||||
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
||||
if (addr)
|
||||
serv->addr = *addr;
|
||||
if (source_addr)
|
||||
serv->source_addr = *source_addr;
|
||||
}
|
||||
if (interface)
|
||||
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
||||
if (addr)
|
||||
serv->addr = *addr;
|
||||
if (source_addr)
|
||||
serv->source_addr = *source_addr;
|
||||
}
|
||||
|
||||
|
||||
serv->flags = flags;
|
||||
serv->domain = alloc_domain;
|
||||
serv->domain_len = strlen(alloc_domain);
|
||||
|
||||
+25
-8
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -230,9 +230,17 @@ int is_rev_synth(int flag, union all_addr *addr, char *name)
|
||||
|
||||
static int match_domain(struct in_addr addr, struct cond_domain *c)
|
||||
{
|
||||
if (!c->is6 &&
|
||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
if (c->interface)
|
||||
{
|
||||
struct addrlist *al;
|
||||
for (al = c->al; al; al = al->next)
|
||||
if (!(al->flags & ADDRLIST_IPV6) &&
|
||||
is_same_net_prefix(addr, al->addr.addr4, al->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
else if (!c->is6 &&
|
||||
ntohl(addr.s_addr) >= ntohl(c->start.s_addr) &&
|
||||
ntohl(addr.s_addr) <= ntohl(c->end.s_addr))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
@@ -259,12 +267,21 @@ char *get_domain(struct in_addr addr)
|
||||
|
||||
static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||
{
|
||||
u64 addrpart = addr6part(addr);
|
||||
|
||||
if (c->is6)
|
||||
|
||||
/* subnet from interface address. */
|
||||
if (c->interface)
|
||||
{
|
||||
struct addrlist *al;
|
||||
for (al = c->al; al; al = al->next)
|
||||
if (al->flags & ADDRLIST_IPV6 &&
|
||||
is_same_net6(addr, &al->addr.addr6, al->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
else if (c->is6)
|
||||
{
|
||||
if (c->prefixlen >= 64)
|
||||
{
|
||||
u64 addrpart = addr6part(addr);
|
||||
if (is_same_net6(addr, &c->start6, 64) &&
|
||||
addrpart >= addr6part(&c->start6) &&
|
||||
addrpart <= addr6part(&c->end6))
|
||||
@@ -273,7 +290,7 @@ static int match_domain6(struct in6_addr *addr, struct cond_domain *c)
|
||||
else if (is_same_net6(addr, &c->start6, c->prefixlen))
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+114
-30
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,11 @@
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
|
||||
#include <netinet/icmp6.h>
|
||||
|
||||
static u32 packet_count;
|
||||
static void do_dump_packet(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int port, int proto);
|
||||
|
||||
/* https://wiki.wireshark.org/Development/LibpcapFileFormat */
|
||||
struct pcap_hdr_s {
|
||||
@@ -79,7 +83,45 @@ void dump_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, union mysockaddr *dst)
|
||||
void dump_packet_udp(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int fd)
|
||||
{
|
||||
union mysockaddr fd_addr;
|
||||
socklen_t addr_len = sizeof(fd_addr);
|
||||
|
||||
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
|
||||
{
|
||||
/* if fd is negative it carries a port number (negated)
|
||||
which we use as a source or destination when not otherwise
|
||||
specified so wireshark can ID the packet.
|
||||
If both src and dst are specified, set this to -1 to avoid
|
||||
a spurious getsockname() call. */
|
||||
int port = (fd < 0) ? -fd : -1;
|
||||
|
||||
/* fd >= 0 is a file descriptor and the address of that file descriptor is used
|
||||
in place of a NULL src or dst. */
|
||||
if (fd >= 0 && getsockname(fd, (struct sockaddr *)&fd_addr, &addr_len) != -1)
|
||||
{
|
||||
if (!src)
|
||||
src = &fd_addr;
|
||||
|
||||
if (!dst)
|
||||
dst = &fd_addr;
|
||||
}
|
||||
|
||||
do_dump_packet(mask, packet, len, src, dst, port, IPPROTO_UDP);
|
||||
}
|
||||
}
|
||||
|
||||
void dump_packet_icmp(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst)
|
||||
{
|
||||
if (daemon->dumpfd != -1 && (mask & daemon->dump_mask))
|
||||
do_dump_packet(mask, packet, len, src, dst, -1, IPPROTO_ICMP);
|
||||
}
|
||||
|
||||
static void do_dump_packet(int mask, void *packet, size_t len,
|
||||
union mysockaddr *src, union mysockaddr *dst, int port, int proto)
|
||||
{
|
||||
struct ip ip;
|
||||
struct ip6_hdr ip6;
|
||||
@@ -96,13 +138,14 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
void *iphdr;
|
||||
size_t ipsz;
|
||||
int rc;
|
||||
|
||||
/* if port != -1 it carries a port number
|
||||
which we use as a source or destination when not otherwise
|
||||
specified so wireshark can ID the packet.
|
||||
If both src and dst are specified, set this to -1 to avoid
|
||||
a spurious getsockname() call. */
|
||||
udp.uh_sport = udp.uh_dport = htons(port < 0 ? 0 : port);
|
||||
|
||||
if (daemon->dumpfd == -1 || !(mask & daemon->dump_mask))
|
||||
return;
|
||||
|
||||
/* So wireshark can Id the packet. */
|
||||
udp.uh_sport = udp.uh_dport = htons(NAMESERVER_PORT);
|
||||
|
||||
if (src)
|
||||
family = src->sa.sa_family;
|
||||
else
|
||||
@@ -115,10 +158,16 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
memset(&ip6, 0, sizeof(ip6));
|
||||
|
||||
ip6.ip6_vfc = 6 << 4;
|
||||
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
|
||||
ip6.ip6_nxt = IPPROTO_UDP;
|
||||
ip6.ip6_hops = 64;
|
||||
|
||||
if ((ip6.ip6_nxt = proto) == IPPROTO_UDP)
|
||||
ip6.ip6_plen = htons(sizeof(struct udphdr) + len);
|
||||
else
|
||||
{
|
||||
proto = ip6.ip6_nxt = IPPROTO_ICMPV6;
|
||||
ip6.ip6_plen = htons(len);
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
memcpy(&ip6.ip6_src, &src->in6.sin6_addr, IN6ADDRSZ);
|
||||
@@ -134,9 +183,8 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
/* start UDP checksum */
|
||||
for (sum = 0, i = 0; i < IN6ADDRSZ; i+=2)
|
||||
{
|
||||
sum += ip6.ip6_src.s6_addr[i] + (ip6.ip6_src.s6_addr[i+1] << 8) ;
|
||||
sum += ip6.ip6_dst.s6_addr[i] + (ip6.ip6_dst.s6_addr[i+1] << 8) ;
|
||||
|
||||
sum += ntohs((ip6.ip6_src.s6_addr[i] << 8) + (ip6.ip6_src.s6_addr[i+1])) ;
|
||||
sum += ntohs((ip6.ip6_dst.s6_addr[i] << 8) + (ip6.ip6_dst.s6_addr[i+1])) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -147,9 +195,15 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
|
||||
ip.ip_v = IPVERSION;
|
||||
ip.ip_hl = sizeof(struct ip) / 4;
|
||||
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
|
||||
ip.ip_ttl = IPDEFTTL;
|
||||
ip.ip_p = IPPROTO_UDP;
|
||||
|
||||
if ((ip.ip_p = proto) == IPPROTO_UDP)
|
||||
ip.ip_len = htons(sizeof(struct ip) + sizeof(struct udphdr) + len);
|
||||
else
|
||||
{
|
||||
ip.ip_len = htons(sizeof(struct ip) + len);
|
||||
proto = ip.ip_p = IPPROTO_ICMP;
|
||||
}
|
||||
|
||||
if (src)
|
||||
{
|
||||
@@ -170,7 +224,7 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
ip.ip_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
/* start UDP checksum */
|
||||
/* start UDP/ICMP checksum */
|
||||
sum = ip.ip_src.s_addr & 0xffff;
|
||||
sum += (ip.ip_src.s_addr >> 16) & 0xffff;
|
||||
sum += ip.ip_dst.s_addr & 0xffff;
|
||||
@@ -180,31 +234,61 @@ void dump_packet(int mask, void *packet, size_t len, union mysockaddr *src, unio
|
||||
if (len & 1)
|
||||
((unsigned char *)packet)[len] = 0; /* for checksum, in case length is odd. */
|
||||
|
||||
udp.uh_sum = 0;
|
||||
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
|
||||
sum += htons(IPPROTO_UDP);
|
||||
sum += htons(sizeof(struct udphdr) + len);
|
||||
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||
sum += ((u16 *)&udp)[i];
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
if (proto == IPPROTO_UDP)
|
||||
{
|
||||
/* Add Remaining part of the pseudoheader. Note that though the
|
||||
IPv6 pseudoheader is very different to the IPv4 one, the
|
||||
net result of this calculation is correct as long as the
|
||||
packet length is less than 65536, which is fine for us. */
|
||||
sum += htons(IPPROTO_UDP);
|
||||
sum += htons(sizeof(struct udphdr) + len);
|
||||
|
||||
udp.uh_sum = 0;
|
||||
udp.uh_ulen = htons(sizeof(struct udphdr) + len);
|
||||
|
||||
for (i = 0; i < sizeof(struct udphdr)/2; i++)
|
||||
sum += ((u16 *)&udp)[i];
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
udp.uh_sum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ICMP - ICMPv6 packet is a superset of ICMP */
|
||||
struct icmp6_hdr *icmp = packet;
|
||||
|
||||
/* See comment in UDP code above. */
|
||||
sum += htons(proto);
|
||||
sum += htons(len);
|
||||
|
||||
icmp->icmp6_cksum = 0;
|
||||
for (i = 0; i < (len + 1) / 2; i++)
|
||||
sum += ((u16 *)packet)[i];
|
||||
while (sum >> 16)
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
icmp->icmp6_cksum = (sum == 0xffff) ? sum : ~sum;
|
||||
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + len;
|
||||
}
|
||||
|
||||
rc = gettimeofday(&time, NULL);
|
||||
pcap_header.ts_sec = time.tv_sec;
|
||||
pcap_header.ts_usec = time.tv_usec;
|
||||
pcap_header.incl_len = pcap_header.orig_len = ipsz + sizeof(udp) + len;
|
||||
|
||||
if (rc == -1 ||
|
||||
!read_write(daemon->dumpfd, (void *)&pcap_header, sizeof(pcap_header), 0) ||
|
||||
!read_write(daemon->dumpfd, iphdr, ipsz, 0) ||
|
||||
!read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0) ||
|
||||
(proto == IPPROTO_UDP && !read_write(daemon->dumpfd, (void *)&udp, sizeof(udp), 0)) ||
|
||||
!read_write(daemon->dumpfd, (void *)packet, len, 0))
|
||||
my_syslog(LOG_ERR, _("failed to write packet dump"));
|
||||
else if (option_bool(OPT_EXTRALOG))
|
||||
my_syslog(LOG_INFO, _("%u dumping packet %u mask 0x%04x"), daemon->log_display_id, ++packet_count, mask);
|
||||
else
|
||||
my_syslog(LOG_INFO, _("dumping UDP packet %u mask 0x%04x"), ++packet_count, mask);
|
||||
my_syslog(LOG_INFO, _("dumping packet %u mask 0x%04x"), ++packet_count, mask);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+84
-58
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
||||
memcpy(buff, datap, rdlen);
|
||||
|
||||
/* now, delete OPT RR */
|
||||
plen = rrfilter(header, plen, 0);
|
||||
plen = rrfilter(header, plen, RRFILTER_EDNS0);
|
||||
|
||||
/* Now, force addition of a new one */
|
||||
p = NULL;
|
||||
@@ -264,44 +264,62 @@ static void encoder(unsigned char *in, char *out)
|
||||
out[3] = char64(in[2]);
|
||||
}
|
||||
|
||||
/* OPT_ADD_MAC = MAC is added (if available)
|
||||
OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
|
||||
OPT_STRIP_MAC = MAC is removed */
|
||||
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *l3, time_t now, int *cacheablep)
|
||||
{
|
||||
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
|
||||
int replace = 0, maclen = 0;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
char encode[18]; /* handle 6 byte MACs */
|
||||
char encode[18]; /* handle 6 byte MACs ONLY */
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
|
||||
if ((option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX)) && (maclen = find_mac(l3, mac, 1, now)) == 6)
|
||||
{
|
||||
replace = 1;
|
||||
*cacheablep = 0;
|
||||
|
||||
if (option_bool(OPT_MAC_HEX))
|
||||
print_mac(encode, mac, maclen);
|
||||
else
|
||||
{
|
||||
encoder(mac, encode);
|
||||
encoder(mac+3, encode+4);
|
||||
encode[8] = 0;
|
||||
}
|
||||
if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 1;
|
||||
*cacheablep = 0;
|
||||
|
||||
if (option_bool(OPT_MAC_HEX))
|
||||
print_mac(encode, mac, maclen);
|
||||
else
|
||||
{
|
||||
encoder(mac, encode);
|
||||
encoder(mac+3, encode+4);
|
||||
encode[8] = 0;
|
||||
}
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 2;
|
||||
|
||||
return add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
|
||||
if (replace != 0 || maclen == 6)
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMDEVICEID, (unsigned char *)encode, strlen(encode), 0, replace);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
|
||||
/* OPT_ADD_MAC = MAC is added (if available)
|
||||
OPT_ADD_MAC + OPT_STRIP_MAC = MAC is replaced, if not available, it is only removed
|
||||
OPT_STRIP_MAC = MAC is removed */
|
||||
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *l3, time_t now, int *cacheablep)
|
||||
{
|
||||
int maclen;
|
||||
int maclen = 0, replace = 0;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
|
||||
if ((maclen = find_mac(l3, mac, 1, now)) != 0)
|
||||
|
||||
if (option_bool(OPT_ADD_MAC) && (maclen = find_mac(l3, mac, 1, now)) != 0)
|
||||
{
|
||||
*cacheablep = 0;
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
|
||||
if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 1;
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_MAC))
|
||||
replace = 2;
|
||||
|
||||
if (replace != 0 || maclen != 0)
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, replace);
|
||||
|
||||
return plen;
|
||||
}
|
||||
|
||||
@@ -378,15 +396,29 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source,
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
|
||||
/* OPT_CLIENT_SUBNET = client subnet is added
|
||||
OPT_CLIENT_SUBNET + OPT_STRIP_ECS = client subnet is replaced
|
||||
OPT_STRIP_ECS = client subnet is removed */
|
||||
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, int *cacheable)
|
||||
{
|
||||
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
|
||||
|
||||
int len;
|
||||
int replace = 0, len = 0;
|
||||
struct subnet_opt opt;
|
||||
|
||||
len = calc_subnet_opt(&opt, source, cacheable);
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
if (option_bool(OPT_STRIP_ECS))
|
||||
replace = 1;
|
||||
len = calc_subnet_opt(&opt, source, cacheable);
|
||||
}
|
||||
else if (option_bool(OPT_STRIP_ECS))
|
||||
replace = 2;
|
||||
else
|
||||
return plen;
|
||||
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, replace);
|
||||
}
|
||||
|
||||
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer)
|
||||
@@ -460,47 +492,45 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
|
||||
|
||||
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
|
||||
u8 *u = &opt.fields[0];
|
||||
|
||||
if (daemon->umbrella_org) {
|
||||
PUTSHORT(UMBRELLA_ORG, u);
|
||||
PUTLONG(daemon->umbrella_org, u);
|
||||
}
|
||||
|
||||
int family = source->sa.sa_family;
|
||||
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
||||
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
|
||||
|
||||
if (daemon->umbrella_org)
|
||||
{
|
||||
PUTSHORT(UMBRELLA_ORG, u);
|
||||
PUTLONG(daemon->umbrella_org, u);
|
||||
}
|
||||
|
||||
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
||||
memcpy(u, get_addrp(source, family), size);
|
||||
u += size;
|
||||
|
||||
if (option_bool(OPT_UMBRELLA_DEVID))
|
||||
{
|
||||
PUTSHORT(UMBRELLA_DEVICE, u);
|
||||
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
||||
u += UMBRELLA_DEVICESZ;
|
||||
}
|
||||
|
||||
if (option_bool(OPT_UMBRELLA_DEVID)) {
|
||||
PUTSHORT(UMBRELLA_DEVICE, u);
|
||||
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
||||
u += UMBRELLA_DEVICESZ;
|
||||
}
|
||||
|
||||
if (daemon->umbrella_asset) {
|
||||
PUTSHORT(UMBRELLA_ASSET, u);
|
||||
PUTLONG(daemon->umbrella_asset, u);
|
||||
}
|
||||
|
||||
int len = u - &opt.magic[0];
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, len, 0, 1);
|
||||
if (daemon->umbrella_asset)
|
||||
{
|
||||
PUTSHORT(UMBRELLA_ASSET, u);
|
||||
PUTLONG(daemon->umbrella_asset, u);
|
||||
}
|
||||
|
||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, u - (u8 *)&opt, 0, 1);
|
||||
}
|
||||
|
||||
/* Set *check_subnet if we add a client subnet option, which needs to checked
|
||||
in the reply. Set *cacheable to zero if we add an option which the answer
|
||||
may depend on. */
|
||||
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
|
||||
union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
|
||||
union mysockaddr *source, time_t now, int *cacheable)
|
||||
{
|
||||
*check_subnet = 0;
|
||||
*cacheable = 1;
|
||||
|
||||
if (option_bool(OPT_ADD_MAC))
|
||||
plen = add_mac(header, plen, limit, source, now, cacheable);
|
||||
|
||||
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
|
||||
plen = add_dns_client(header, plen, limit, source, now, cacheable);
|
||||
plen = add_mac(header, plen, limit, source, now, cacheable);
|
||||
plen = add_dns_client(header, plen, limit, source, now, cacheable);
|
||||
|
||||
if (daemon->dns_client_id)
|
||||
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
|
||||
@@ -509,11 +539,7 @@ size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *l
|
||||
if (option_bool(OPT_UMBRELLA))
|
||||
plen = add_umbrella_opt(header, plen, limit, source, cacheable);
|
||||
|
||||
if (option_bool(OPT_CLIENT_SUBNET))
|
||||
{
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
*check_subnet = 1;
|
||||
}
|
||||
|
||||
plen = add_source_addr(header, plen, limit, source, cacheable);
|
||||
|
||||
return plen;
|
||||
}
|
||||
+276
-169
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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,9 @@
|
||||
static struct frec *get_new_frec(time_t now, struct server *serv, int force);
|
||||
static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firstp, int *lastp);
|
||||
static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigned int flagmask);
|
||||
#ifdef HAVE_DNSSEC
|
||||
static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header);
|
||||
#endif
|
||||
|
||||
static unsigned short get_id(void);
|
||||
static void free_frec(struct frec *f);
|
||||
@@ -122,9 +125,17 @@ static void set_outgoing_mark(struct frec *forward, int fd)
|
||||
static void log_query_mysockaddr(unsigned int flags, char *name, union mysockaddr *addr, char *arg, unsigned short type)
|
||||
{
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg, type);
|
||||
{
|
||||
if (flags & F_SERVER)
|
||||
type = ntohs(addr->in.sin_port);
|
||||
log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg, type);
|
||||
}
|
||||
else
|
||||
log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg, type);
|
||||
{
|
||||
if (flags & F_SERVER)
|
||||
type = ntohs(addr->in6.sin6_port);
|
||||
log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg, type);
|
||||
}
|
||||
}
|
||||
|
||||
static void server_send(struct server *server, int fd,
|
||||
@@ -135,29 +146,24 @@ static void server_send(struct server *server, int fd,
|
||||
sa_len(&server->addr))));
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
static void server_send_log(struct server *server, int fd,
|
||||
const void *header, size_t plen, int dumpflags,
|
||||
unsigned int logflags, char *name, char *arg,
|
||||
unsigned short type)
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr);
|
||||
#endif
|
||||
log_query_mysockaddr(logflags, name, &server->addr, arg, type);
|
||||
server_send(server, fd, header, plen, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int domain_no_rebind(char *domain)
|
||||
{
|
||||
struct rebind_domain *rbd;
|
||||
size_t tlen, dlen = strlen(domain);
|
||||
|
||||
char *dots = strchr(domain, '.');
|
||||
|
||||
/* Match whole labels only. Empty domain matches no dots (any single label) */
|
||||
for (rbd = daemon->no_rebind; rbd; rbd = rbd->next)
|
||||
if (dlen >= (tlen = strlen(rbd->domain)) && strcmp(rbd->domain, &domain[dlen - tlen]) == 0)
|
||||
{
|
||||
if (dlen >= (tlen = strlen(rbd->domain)) &&
|
||||
hostname_isequal(rbd->domain, &domain[dlen - tlen]) &&
|
||||
(dlen == tlen || domain[dlen - tlen - 1] == '.'))
|
||||
return 1;
|
||||
|
||||
if (tlen == 0 && !dots)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -170,12 +176,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
unsigned int fwd_flags = 0;
|
||||
int is_dnssec = forward && (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY));
|
||||
struct server *master;
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
void *hash = hash_questions(header, plen, daemon->namebuff);
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||
int old_src = 0, old_reply = 0;
|
||||
int first, last, start = 0;
|
||||
int subnet, cacheable, forwarded = 0;
|
||||
int cacheable, forwarded = 0;
|
||||
size_t edns0_len;
|
||||
unsigned char *pheader;
|
||||
int ede = EDE_UNSET;
|
||||
@@ -215,7 +221,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
break;
|
||||
|
||||
if (src)
|
||||
old_src = 1;
|
||||
{
|
||||
old_src = 1;
|
||||
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
||||
src->log_id = daemon->log_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Existing query, but from new source, just add this
|
||||
@@ -234,6 +244,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
if (!daemon->free_frec_src)
|
||||
{
|
||||
query_full(now, NULL);
|
||||
/* This is tricky; if we're blasted with the same query
|
||||
over and over, we'll end up taking this path each time
|
||||
and never resetting until the frec gets deleted by
|
||||
aging followed by the receipt of a different query. This
|
||||
is a bit of a DoS vuln. Avoid by explicitly deleting the
|
||||
frec once it expires. */
|
||||
if (difftime(now, forward->time) >= TIMEOUT)
|
||||
free_frec(forward);
|
||||
goto reply;
|
||||
}
|
||||
|
||||
@@ -259,6 +277,15 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
/* new query */
|
||||
if (!forward)
|
||||
{
|
||||
/* If the query is malformed, we can't forward it because
|
||||
we can't get a reliable hash to recognise the answer. */
|
||||
if (!hash)
|
||||
{
|
||||
flags = 0;
|
||||
ede = EDE_INVALID_DATA;
|
||||
goto reply;
|
||||
}
|
||||
|
||||
if (lookup_domain(daemon->namebuff, gotname, &first, &last))
|
||||
flags = is_local_answer(now, first, daemon->namebuff);
|
||||
else
|
||||
@@ -286,6 +313,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
goto reply;
|
||||
/* table full - flags == 0, return REFUSED */
|
||||
|
||||
forward->frec_src.log_id = daemon->log_id;
|
||||
forward->frec_src.source = *udpaddr;
|
||||
forward->frec_src.orig_id = ntohs(header->id);
|
||||
forward->frec_src.dest = *dst_addr;
|
||||
@@ -329,7 +357,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* retry on existing query, from original source. Send to all available servers */
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* If we've already got an answer to this query, but we're awaiting keys for validation,
|
||||
there's no point retrying the query, retry the key query instead...... */
|
||||
@@ -340,7 +367,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
|
||||
while (forward->blocking_query)
|
||||
forward = forward->blocking_query;
|
||||
|
||||
|
||||
/* log_id should match previous DNSSEC query. */
|
||||
daemon->log_display_id = forward->frec_src.log_id;
|
||||
|
||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||
plen = forward->stash_len;
|
||||
/* get query for logging. */
|
||||
@@ -383,7 +413,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
Note that we can get here EITHER because a client retried,
|
||||
or an upstream server returned REFUSED. The above only
|
||||
applied in the later case. For client retries,
|
||||
keep tyring the last server.. */
|
||||
keep trying the last server.. */
|
||||
if (++start == last)
|
||||
{
|
||||
if (old_reply)
|
||||
@@ -402,18 +432,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
forward->flags |= FREC_TEST_PKTSZ;
|
||||
}
|
||||
|
||||
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
||||
forward->frec_src.log_id = daemon->log_id;
|
||||
|
||||
/* We may be resending a DNSSEC query here, for which the below processing is not necessary. */
|
||||
if (!is_dnssec)
|
||||
{
|
||||
header->id = htons(forward->new_id);
|
||||
|
||||
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet, &cacheable);
|
||||
|
||||
if (subnet)
|
||||
forward->flags |= FREC_HAS_SUBNET;
|
||||
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &cacheable);
|
||||
|
||||
if (!cacheable)
|
||||
forward->flags |= FREC_NO_CACHE;
|
||||
@@ -494,7 +518,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
if (errno == 0)
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_UP_QUERY, (void *)header, plen, NULL, &srv->addr);
|
||||
dump_packet_udp(DUMP_UP_QUERY, (void *)header, plen, NULL, &srv->addr, fd);
|
||||
#endif
|
||||
|
||||
/* Keep info in case we want to re-send this packet */
|
||||
@@ -511,8 +535,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
}
|
||||
#ifdef HAVE_DNSSEC
|
||||
else
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, daemon->namebuff, &srv->addr,
|
||||
"dnssec-retry", (forward->flags & FREC_DNSKEY_QUERY) ? T_DNSKEY : T_DS);
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->namebuff, &srv->addr,
|
||||
(forward->flags & FREC_DNSKEY_QUERY) ? "dnssec-retry[DNSKEY]" : "dnssec-retry[DS]", 0);
|
||||
#endif
|
||||
|
||||
srv->queries++;
|
||||
@@ -591,7 +615,7 @@ static struct ipsets *domain_find_sets(struct ipsets *setlist, const char *domai
|
||||
|
||||
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
|
||||
int no_cache, int cache_secure, int bogusanswer, int ad_reqd, int do_bit, int added_pheader,
|
||||
int check_subnet, union mysockaddr *query_source, unsigned char *limit, int ede)
|
||||
union mysockaddr *query_source, unsigned char *limit, int ede)
|
||||
{
|
||||
unsigned char *pheader, *sizep;
|
||||
struct ipsets *ipsets = NULL, *nftsets = NULL;
|
||||
@@ -618,7 +642,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
/* Get extended RCODE. */
|
||||
rcode |= sizep[2] << 4;
|
||||
|
||||
if (check_subnet && !check_source(header, plen, pheader, query_source))
|
||||
if (option_bool(OPT_CLIENT_SUBNET) && !check_source(header, plen, pheader, query_source))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("discarding DNS reply: subnet option mismatch"));
|
||||
return 0;
|
||||
@@ -629,7 +653,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
if (added_pheader)
|
||||
{
|
||||
/* client didn't send EDNS0, we added one, strip it off before returning answer. */
|
||||
n = rrfilter(header, n, 0);
|
||||
n = rrfilter(header, n, RRFILTER_EDNS0);
|
||||
pheader = NULL;
|
||||
}
|
||||
else
|
||||
@@ -718,7 +742,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
cache_secure = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Before extract_addresses() */
|
||||
if (rcode == NOERROR)
|
||||
{
|
||||
if (option_bool(OPT_FILTER_A))
|
||||
n = rrfilter(header, n, RRFILTER_A);
|
||||
|
||||
if (option_bool(OPT_FILTER_AAAA))
|
||||
n = rrfilter(header, n, RRFILTER_AAAA);
|
||||
}
|
||||
|
||||
if (extract_addresses(header, n, daemon->namebuff, now, ipsets, nftsets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||
@@ -748,7 +782,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
|
||||
/* If the requestor didn't set the DO bit, don't return DNSSEC info. */
|
||||
if (!do_bit)
|
||||
n = rrfilter(header, n, 1);
|
||||
n = rrfilter(header, n, RRFILTER_DNSSEC);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -772,7 +806,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
||||
u16 swap = htons((u16)ede);
|
||||
n = add_pseudoheader(header, n, limit, daemon->edns_pktsz, EDNS0_OPTION_EDE, (unsigned char *)&swap, 2, do_bit, 1);
|
||||
}
|
||||
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -813,8 +847,8 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
||||
NULL, NULL, NULL);
|
||||
#ifdef HAVE_DUMPFILE
|
||||
if (STAT_ISEQUAL(status, STAT_BOGUS))
|
||||
dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
|
||||
header, (size_t)plen, &forward->sentto->addr, NULL);
|
||||
dump_packet_udp((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_BOGUS : DUMP_BOGUS,
|
||||
header, (size_t)plen, &forward->sentto->addr, NULL, -daemon->port);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -823,106 +857,127 @@ static void dnssec_validate(struct frec *forward, struct dns_header *header,
|
||||
if (STAT_ISEQUAL(status, STAT_NEED_DS) || STAT_ISEQUAL(status, STAT_NEED_KEY))
|
||||
{
|
||||
struct frec *new = NULL;
|
||||
int serverind;
|
||||
struct blockdata *stash;
|
||||
|
||||
/* Now save reply pending receipt of key data */
|
||||
if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 &&
|
||||
(stash = blockdata_alloc((char *)header, plen)))
|
||||
if ((stash = blockdata_alloc((char *)header, plen)))
|
||||
{
|
||||
struct server *server = daemon->serverarray[serverind];
|
||||
struct frec *orig;
|
||||
unsigned int flags;
|
||||
void *hash;
|
||||
size_t nn;
|
||||
|
||||
/* validate routines leave name of required record in daemon->keyname */
|
||||
nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class,
|
||||
STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz);
|
||||
|
||||
flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY;
|
||||
hash = hash_questions(header, nn, daemon->namebuff);
|
||||
unsigned int flags = STAT_ISEQUAL(status, STAT_NEED_KEY) ? FREC_DNSKEY_QUERY : FREC_DS_QUERY;
|
||||
|
||||
if ((new = lookup_frec_by_query(hash, flags, FREC_DNSKEY_QUERY | FREC_DS_QUERY)))
|
||||
if ((new = lookup_frec_dnssec(daemon->keyname, forward->class, flags, header)))
|
||||
{
|
||||
forward->next_dependent = new->dependent;
|
||||
new->dependent = forward;
|
||||
/* Make consistent, only replace query copy with unvalidated answer
|
||||
when we set ->blocking_query. */
|
||||
if (forward->stash)
|
||||
blockdata_free(forward->stash);
|
||||
forward->blocking_query = new;
|
||||
forward->stash_len = plen;
|
||||
forward->stash = stash;
|
||||
return;
|
||||
/* This is tricky; it detects loops in the dependency
|
||||
graph for DNSSEC validation, say validating A requires DS B
|
||||
and validating DS B requires DNSKEY C and validating DNSKEY C requires DS B.
|
||||
This should never happen in correctly signed records, but it's
|
||||
likely the case that sufficiently broken ones can cause our validation
|
||||
code requests to exhibit cycles. The result is that the ->blocking_query list
|
||||
can form a cycle, and under certain circumstances that can lock us in
|
||||
an infinite loop. Here we transform the situation into ABANDONED. */
|
||||
struct frec *f;
|
||||
for (f = new; f; f = f->blocking_query)
|
||||
if (f == forward)
|
||||
break;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
forward->next_dependent = new->dependent;
|
||||
new->dependent = forward;
|
||||
/* Make consistent, only replace query copy with unvalidated answer
|
||||
when we set ->blocking_query. */
|
||||
if (forward->stash)
|
||||
blockdata_free(forward->stash);
|
||||
forward->blocking_query = new;
|
||||
forward->stash_len = plen;
|
||||
forward->stash = stash;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find the original query that started it all.... */
|
||||
for (orig = forward; orig->dependent; orig = orig->dependent);
|
||||
|
||||
/* Make sure we don't expire and free the orig frec during the
|
||||
allocation of a new one: third arg of get_new_frec() does that. */
|
||||
if (--orig->work_counter == 0 || !(new = get_new_frec(now, server, 1)))
|
||||
blockdata_free(stash); /* don't leak this on failure. */
|
||||
else
|
||||
{
|
||||
int fd;
|
||||
struct frec *next = new->next;
|
||||
|
||||
*new = *forward; /* copy everything, then overwrite */
|
||||
new->next = next;
|
||||
new->blocking_query = NULL;
|
||||
struct server *server;
|
||||
struct frec *orig;
|
||||
void *hash;
|
||||
size_t nn;
|
||||
int serverind, fd;
|
||||
struct randfd_list *rfds = NULL;
|
||||
|
||||
new->frec_src.log_id = daemon->log_display_id = ++daemon->log_id;
|
||||
new->sentto = server;
|
||||
new->rfds = NULL;
|
||||
new->frec_src.next = NULL;
|
||||
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
|
||||
new->flags |= flags;
|
||||
new->forwardall = 0;
|
||||
/* Find the original query that started it all.... */
|
||||
for (orig = forward; orig->dependent; orig = orig->dependent);
|
||||
|
||||
forward->next_dependent = NULL;
|
||||
new->dependent = forward; /* to find query awaiting new one. */
|
||||
|
||||
/* Make consistent, only replace query copy with unvalidated answer
|
||||
when we set ->blocking_query. */
|
||||
forward->blocking_query = new;
|
||||
if (forward->stash)
|
||||
blockdata_free(forward->stash);
|
||||
forward->stash_len = plen;
|
||||
forward->stash = stash;
|
||||
|
||||
memcpy(new->hash, hash, HASH_SIZE);
|
||||
new->new_id = get_id();
|
||||
header->id = htons(new->new_id);
|
||||
/* Save query for retransmission */
|
||||
new->stash = blockdata_alloc((char *)header, nn);
|
||||
new->stash_len = nn;
|
||||
|
||||
/* Don't resend this. */
|
||||
daemon->srv_save = NULL;
|
||||
|
||||
if ((fd = allocate_rfd(&new->rfds, server)) != -1)
|
||||
/* Make sure we don't expire and free the orig frec during the
|
||||
allocation of a new one: third arg of get_new_frec() does that. */
|
||||
if ((serverind = dnssec_server(forward->sentto, daemon->keyname, NULL, NULL)) != -1 &&
|
||||
(server = daemon->serverarray[serverind]) &&
|
||||
(nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class,
|
||||
STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS, server->edns_pktsz)) &&
|
||||
(hash = hash_questions(header, nn, daemon->namebuff)) &&
|
||||
--orig->work_counter != 0 &&
|
||||
(fd = allocate_rfd(&rfds, server)) != -1 &&
|
||||
(new = get_new_frec(now, server, 1)))
|
||||
{
|
||||
struct frec *next = new->next;
|
||||
|
||||
*new = *forward; /* copy everything, then overwrite */
|
||||
new->next = next;
|
||||
new->blocking_query = NULL;
|
||||
|
||||
new->frec_src.log_id = daemon->log_display_id = ++daemon->log_id;
|
||||
new->sentto = server;
|
||||
new->rfds = rfds;
|
||||
new->frec_src.next = NULL;
|
||||
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
|
||||
new->flags |= flags;
|
||||
new->forwardall = 0;
|
||||
|
||||
forward->next_dependent = NULL;
|
||||
new->dependent = forward; /* to find query awaiting new one. */
|
||||
|
||||
/* Make consistent, only replace query copy with unvalidated answer
|
||||
when we set ->blocking_query. */
|
||||
forward->blocking_query = new;
|
||||
if (forward->stash)
|
||||
blockdata_free(forward->stash);
|
||||
forward->stash_len = plen;
|
||||
forward->stash = stash;
|
||||
|
||||
memcpy(new->hash, hash, HASH_SIZE);
|
||||
new->new_id = get_id();
|
||||
header->id = htons(new->new_id);
|
||||
/* Save query for retransmission and de-dup */
|
||||
new->stash = blockdata_alloc((char *)header, nn);
|
||||
new->stash_len = nn;
|
||||
|
||||
/* Don't resend this. */
|
||||
daemon->srv_save = NULL;
|
||||
|
||||
#ifdef HAVE_CONNTRACK
|
||||
if (option_bool(OPT_CONNTRACK))
|
||||
set_outgoing_mark(orig, fd);
|
||||
#endif
|
||||
server_send_log(server, fd, header, nn, DUMP_SEC_QUERY,
|
||||
F_NOEXTRA | F_DNSSEC, daemon->keyname,
|
||||
"dnssec-query", STAT_ISEQUAL(status, STAT_NEED_KEY) ? T_DNSKEY : T_DS);
|
||||
|
||||
server_send(server, fd, header, nn, 0);
|
||||
server->queries++;
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr, fd);
|
||||
#endif
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, daemon->keyname, &server->addr,
|
||||
STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
free_rfds(&rfds); /* error unwind */
|
||||
}
|
||||
|
||||
blockdata_free(stash); /* don't leak this on failure. */
|
||||
}
|
||||
|
||||
/* sending DNSSEC query failed. */
|
||||
/* sending DNSSEC query failed or loop detected. */
|
||||
status = STAT_ABANDONED;
|
||||
}
|
||||
|
||||
|
||||
/* Validated original answer, all done. */
|
||||
if (!forward->dependent)
|
||||
return_reply(now, forward, header, plen, status);
|
||||
@@ -998,16 +1053,16 @@ void reply_query(int fd, time_t now)
|
||||
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
|
||||
server->edns_pktsz = daemon->edns_pktsz;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
|
||||
(void *)header, n, &serveraddr, NULL);
|
||||
#endif
|
||||
|
||||
/* log_query gets called indirectly all over the place, so
|
||||
pass these in global variables - sorry. */
|
||||
daemon->log_display_id = forward->frec_src.log_id;
|
||||
daemon->log_source_addr = &forward->frec_src.source;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) ? DUMP_SEC_REPLY : DUMP_UP_REPLY,
|
||||
(void *)header, n, &serveraddr, NULL, fd);
|
||||
#endif
|
||||
|
||||
if (daemon->ignore_addr && RCODE(header) == NOERROR &&
|
||||
check_for_ignored_address(header, n))
|
||||
return;
|
||||
@@ -1026,12 +1081,15 @@ void reply_query(int fd, time_t now)
|
||||
size_t nn = 0;
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* DNSSEC queries have a copy of the original query stashed.
|
||||
The query MAY have got a good answer, and be awaiting
|
||||
/* The query MAY have got a good answer, and be awaiting
|
||||
the results of further queries, in which case
|
||||
The Stash contains something else and we don't need to retry anyway. */
|
||||
if ((forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) && !forward->blocking_query)
|
||||
if (forward->blocking_query)
|
||||
return;
|
||||
|
||||
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
|
||||
{
|
||||
/* DNSSEC queries have a copy of the original query stashed. */
|
||||
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||
nn = forward->stash_len;
|
||||
udp_size = daemon->edns_pktsz;
|
||||
@@ -1097,6 +1155,13 @@ void reply_query(int fd, time_t now)
|
||||
}
|
||||
|
||||
forward->sentto = server;
|
||||
|
||||
/* We have a good answer, and will now validate it or return it.
|
||||
It may be some time before this the validation completes, but we don't need
|
||||
any more answers, so close the socket(s) on which we were expecting
|
||||
answers, to conserve file descriptors, and to save work reading and
|
||||
discarding answers for other upstreams. */
|
||||
free_rfds(&forward->rfds);
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if ((forward->sentto->flags & SERV_DO_DNSSEC) &&
|
||||
@@ -1179,7 +1244,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
|
||||
|
||||
if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
|
||||
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
|
||||
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source,
|
||||
forward->flags & FREC_ADDED_PHEADER, &forward->frec_src.source,
|
||||
((unsigned char *)header) + daemon->edns_pktsz, ede)))
|
||||
{
|
||||
struct frec_src *src;
|
||||
@@ -1204,7 +1269,7 @@ static void return_reply(time_t now, struct frec *forward, struct dns_header *he
|
||||
header->id = htons(src->orig_id);
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source);
|
||||
dump_packet_udp(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source, src->fd);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||
@@ -1400,7 +1465,8 @@ void receive_query(struct listener *listen, time_t now)
|
||||
static int warned = 0;
|
||||
if (!warned)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
|
||||
prettyprint_addr(&source_addr, daemon->addrbuff);
|
||||
my_syslog(LOG_WARNING, _("ignoring query from non-local network %s (logged only once)"), daemon->addrbuff);
|
||||
warned = 1;
|
||||
}
|
||||
return;
|
||||
@@ -1518,7 +1584,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
daemon->log_source_addr = &source_addr;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL);
|
||||
dump_packet_udp(DUMP_QUERY, daemon->packet, (size_t)n, &source_addr, NULL, listen->fd);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONNTRACK
|
||||
@@ -1571,13 +1637,17 @@ void receive_query(struct listener *listen, time_t now)
|
||||
|
||||
/* If the client provides an EDNS0 UDP size, use that to limit our reply.
|
||||
(bounded by the maximum configured). If no EDNS0, then it
|
||||
defaults to 512 */
|
||||
defaults to 512. We write this value into the query packet too, so that
|
||||
if it's forwarded, we don't specify a maximum size greater than we can handle. */
|
||||
if (udp_size > daemon->edns_pktsz)
|
||||
udp_size = daemon->edns_pktsz;
|
||||
else if (udp_size < PACKETSZ)
|
||||
udp_size = PACKETSZ; /* Sanity check - can't reduce below default. RFC 6891 6.2.3 */
|
||||
}
|
||||
|
||||
pheader -= 6; /* ext_class */
|
||||
PUTSHORT(udp_size, pheader); /* Bounding forwarded queries to maximum configured */
|
||||
}
|
||||
|
||||
#ifdef HAVE_CONNTRACK
|
||||
#ifdef HAVE_AUTH
|
||||
if (!auth_dns || local_auth)
|
||||
@@ -1601,7 +1671,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
if (m >= 1)
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
|
||||
#endif
|
||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||
@@ -1617,7 +1687,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
if (m >= 1)
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
|
||||
#endif
|
||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||
if (local_auth)
|
||||
@@ -1643,7 +1713,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
if (m >= 1)
|
||||
{
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet(DUMP_REPLY, daemon->packet, m, NULL, &source_addr);
|
||||
dump_packet_udp(DUMP_REPLY, daemon->packet, m, NULL, &source_addr, listen->fd);
|
||||
#endif
|
||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||
if (option_bool(OPT_CMARK_ALST_EN) && have_mark && ((u32)mark & daemon->allowlist_mask))
|
||||
@@ -1671,13 +1741,16 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
|
||||
unsigned char *payload = &packet[2];
|
||||
struct dns_header *header = (struct dns_header *)payload;
|
||||
unsigned char c1, c2;
|
||||
unsigned char hash[HASH_SIZE];
|
||||
unsigned char hash[HASH_SIZE], *hashp;
|
||||
unsigned int rsize;
|
||||
|
||||
(void)mark;
|
||||
(void)have_mark;
|
||||
|
||||
memcpy(hash, hash_questions(header, (unsigned int)qsize, daemon->namebuff), HASH_SIZE);
|
||||
if (!(hashp = hash_questions(header, (unsigned int)qsize, daemon->namebuff)))
|
||||
return 0;
|
||||
|
||||
memcpy(hash, hashp, HASH_SIZE);
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -1758,7 +1831,7 @@ static ssize_t tcp_talk(int first, int last, int start, unsigned char *packet,
|
||||
someone might be attempting to insert bogus values into the cache by
|
||||
sending replies containing questions and bogus answers.
|
||||
Try another server, or give up */
|
||||
if (memcmp(hash, hash_questions(header, rsize, daemon->namebuff), HASH_SIZE) != 0)
|
||||
if (!(hashp = hash_questions(header, rsize, daemon->namebuff)) || memcmp(hash, hashp, HASH_SIZE) != 0)
|
||||
continue;
|
||||
|
||||
serv->flags |= SERV_GOT_TCP;
|
||||
@@ -1827,8 +1900,8 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
log_save = daemon->log_display_id;
|
||||
daemon->log_display_id = ++daemon->log_id;
|
||||
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, keyname, &server->addr,
|
||||
"dnssec-query", STAT_ISEQUAL(new_status, STAT_NEED_KEY) ? T_DNSKEY : T_DS);
|
||||
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC | F_SERVER, keyname, &server->addr,
|
||||
STAT_ISEQUAL(status, STAT_NEED_KEY) ? "dnssec-query[DNSKEY]" : "dnssec-query[DS]", 0);
|
||||
|
||||
new_status = tcp_key_recurse(now, new_status, new_header, m, class, name, keyname, server, have_mark, mark, keycount);
|
||||
|
||||
@@ -1862,7 +1935,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
int local_auth = 0;
|
||||
#endif
|
||||
int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
|
||||
int check_subnet, cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
||||
int cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
|
||||
size_t m;
|
||||
unsigned short qtype;
|
||||
unsigned int gotname;
|
||||
@@ -1927,7 +2000,8 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
}
|
||||
if (!addr)
|
||||
{
|
||||
my_syslog(LOG_WARNING, _("Ignoring query from non-local network"));
|
||||
prettyprint_addr(&peer_addr, daemon->addrbuff);
|
||||
my_syslog(LOG_WARNING, _("ignoring query from non-local network %s"), daemon->addrbuff);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
@@ -2079,7 +2153,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
else
|
||||
start = master->last_server;
|
||||
|
||||
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable);
|
||||
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &cacheable);
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
if (option_bool(OPT_DNSSEC_VALID) && (master->flags & SERV_DO_DNSSEC))
|
||||
@@ -2157,7 +2231,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
|
||||
m = process_reply(header, now, serv, (unsigned int)m,
|
||||
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
|
||||
ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr, ((unsigned char *)header) + 65536, ede);
|
||||
ad_reqd, do_bit, added_pheader, &peer_addr, ((unsigned char *)header) + 65536, ede);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2523,28 +2597,29 @@ static struct frec *lookup_frec(unsigned short id, int fd, void *hash, int *firs
|
||||
struct server *s;
|
||||
int first, last;
|
||||
struct randfd_list *fdl;
|
||||
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->new_id == id &&
|
||||
(memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||
{
|
||||
filter_servers(f->sentto->arrayposn, F_SERVER, firstp, lastp);
|
||||
|
||||
/* sent from random port */
|
||||
for (fdl = f->rfds; fdl; fdl = fdl->next)
|
||||
if (fdl->rfd->fd == fd)
|
||||
return f;
|
||||
|
||||
/* Sent to upstream from socket associated with a server.
|
||||
Note we have to iterate over all the possible servers, since they may
|
||||
have different bound sockets. */
|
||||
for (first = *firstp, last = *lastp; first != last; first++)
|
||||
{
|
||||
s = daemon->serverarray[first];
|
||||
if (s->sfd && s->sfd->fd == fd)
|
||||
if (hash)
|
||||
for (f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto && f->new_id == id &&
|
||||
(memcmp(hash, f->hash, HASH_SIZE) == 0))
|
||||
{
|
||||
filter_servers(f->sentto->arrayposn, F_SERVER, firstp, lastp);
|
||||
|
||||
/* sent from random port */
|
||||
for (fdl = f->rfds; fdl; fdl = fdl->next)
|
||||
if (fdl->rfd->fd == fd)
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Sent to upstream from socket associated with a server.
|
||||
Note we have to iterate over all the possible servers, since they may
|
||||
have different bound sockets. */
|
||||
for (first = *firstp, last = *lastp; first != last; first++)
|
||||
{
|
||||
s = daemon->serverarray[first];
|
||||
if (s->sfd && s->sfd->fd == fd)
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -2553,15 +2628,47 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags, unsigne
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for(f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto &&
|
||||
(f->flags & flagmask) == flags &&
|
||||
memcmp(hash, f->hash, HASH_SIZE) == 0)
|
||||
return f;
|
||||
if (hash)
|
||||
for (f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto &&
|
||||
(f->flags & flagmask) == flags &&
|
||||
memcmp(hash, f->hash, HASH_SIZE) == 0)
|
||||
return f;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
/* DNSSEC frecs have the complete query in the block stash.
|
||||
Search for an existing query using that. */
|
||||
static struct frec *lookup_frec_dnssec(char *target, int class, int flags, struct dns_header *header)
|
||||
{
|
||||
struct frec *f;
|
||||
|
||||
for (f = daemon->frec_list; f; f = f->next)
|
||||
if (f->sentto &&
|
||||
(f->flags & flags) &&
|
||||
blockdata_retrieve(f->stash, f->stash_len, (void *)header))
|
||||
{
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
int hclass;
|
||||
|
||||
if (extract_name(header, f->stash_len, &p, target, 0, 4) != 1)
|
||||
continue;
|
||||
|
||||
p += 2; /* type, known from flags */
|
||||
GETSHORT(hclass, p);
|
||||
|
||||
if (class != hclass)
|
||||
continue;
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Send query packet again, if we can. */
|
||||
void resend_query()
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
The hash used is SHA-256. If we're building with DNSSEC support,
|
||||
we use the Nettle cypto library. If not, we prefer not to
|
||||
add a dependency on Nettle, and use a stand-alone implementaion.
|
||||
add a dependency on Nettle, and use a stand-alone implementation.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
@@ -55,7 +55,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
|
||||
char *cp, c;
|
||||
|
||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
break; /* bad packet */
|
||||
return NULL; /* bad packet */
|
||||
|
||||
for (cp = name; (c = *cp); cp++)
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
@@ -67,7 +67,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
|
||||
|
||||
p += 4;
|
||||
if (!CHECK_LEN(header, p, plen, 0))
|
||||
break; /* bad packet */
|
||||
return NULL; /* bad packet */
|
||||
}
|
||||
|
||||
hash->digest(ctx, hash->digest_size, digest);
|
||||
@@ -109,7 +109,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
|
||||
char *cp, c;
|
||||
|
||||
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||
break; /* bad packet */
|
||||
return NULL; /* bad packet */
|
||||
|
||||
for (cp = name; (c = *cp); cp++)
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
@@ -121,7 +121,7 @@ unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name
|
||||
|
||||
p += 4;
|
||||
if (!CHECK_LEN(header, p, plen, 0))
|
||||
break; /* bad packet */
|
||||
return NULL; /* bad packet */
|
||||
}
|
||||
|
||||
sha256_final(&ctx, digest);
|
||||
|
||||
+69
-11
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -233,8 +233,13 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
is6 = (data.flags != AF_INET);
|
||||
data.action = ACTION_ARP;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
else if (data.action == ACTION_RELAY_SNOOP)
|
||||
{
|
||||
is6 = 1;
|
||||
action_str = "relay-snoop";
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
/* stringify MAC into dhcp_buff */
|
||||
p = daemon->dhcp_buff;
|
||||
@@ -286,7 +291,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
char *dot;
|
||||
hostname = (char *)buf;
|
||||
hostname[data.hostname_len - 1] = 0;
|
||||
if (data.action != ACTION_TFTP)
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_RELAY_SNOOP)
|
||||
{
|
||||
if (!legal_hostname(hostname))
|
||||
hostname = NULL;
|
||||
@@ -332,6 +337,24 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else if (data.action == ACTION_RELAY_SNOOP)
|
||||
{
|
||||
lua_getglobal(lua, "snoop");
|
||||
if (lua_type(lua, -1) != LUA_TFUNCTION)
|
||||
lua_pop(lua, 1); /* tftp function optional */
|
||||
else
|
||||
{
|
||||
lua_pushstring(lua, action_str); /* arg1 - action */
|
||||
lua_newtable(lua); /* arg2 - data table */
|
||||
lua_pushstring(lua, daemon->addrbuff);
|
||||
lua_setfield(lua, -2, "client_address");
|
||||
lua_pushstring(lua, hostname);
|
||||
lua_setfield(lua, -2, "prefix");
|
||||
lua_pushstring(lua, data.interface);
|
||||
lua_setfield(lua, -2, "client_interface");
|
||||
lua_call(lua, 2, 0); /* pass 2 values, expect 0 */
|
||||
}
|
||||
}
|
||||
else if (data.action == ACTION_ARP)
|
||||
{
|
||||
lua_getglobal(lua, "arp");
|
||||
@@ -398,6 +421,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
end = extradata + data.ed_len;
|
||||
buf = extradata;
|
||||
|
||||
lua_pushnumber(lua, data.ed_len == 0 ? 1 : 0);
|
||||
lua_setfield(lua, -2, "data_missing");
|
||||
|
||||
if (!is6)
|
||||
buf = grab_extradata_lua(buf, end, "vendor_class");
|
||||
@@ -425,15 +451,17 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
buf = grab_extradata_lua(buf, end, "subscriber_id");
|
||||
buf = grab_extradata_lua(buf, end, "remote_id");
|
||||
}
|
||||
|
||||
|
||||
buf = grab_extradata_lua(buf, end, "requested_options");
|
||||
buf = grab_extradata_lua(buf, end, "mud_url");
|
||||
buf = grab_extradata_lua(buf, end, "tags");
|
||||
|
||||
if (is6)
|
||||
buf = grab_extradata_lua(buf, end, "relay_address");
|
||||
else if (data.giaddr.s_addr != 0)
|
||||
{
|
||||
inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||
lua_pushstring(lua, daemon->addrbuff);
|
||||
inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
|
||||
lua_pushstring(lua, daemon->dhcp_buff2);
|
||||
lua_setfield(lua, -2, "relay_address");
|
||||
}
|
||||
|
||||
@@ -553,7 +581,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
close(pipeout[1]);
|
||||
}
|
||||
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP)
|
||||
if (data.action != ACTION_TFTP && data.action != ACTION_ARP && data.action != ACTION_RELAY_SNOOP)
|
||||
{
|
||||
#ifdef HAVE_DHCP6
|
||||
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
|
||||
@@ -576,6 +604,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
|
||||
end = extradata + data.ed_len;
|
||||
buf = extradata;
|
||||
|
||||
if (data.ed_len == 0)
|
||||
my_setenv("DNSMASQ_DATA_MISSING", "1", &err);
|
||||
|
||||
if (!is6)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_VENDOR_CLASS", &err);
|
||||
@@ -604,18 +635,19 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_CIRCUIT_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_SUBSCRIBER_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REMOTE_ID", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
|
||||
}
|
||||
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_REQUESTED_OPTIONS", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_MUD_URL", &err);
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_TAGS", &err);
|
||||
|
||||
|
||||
if (is6)
|
||||
buf = grab_extradata(buf, end, "DNSMASQ_RELAY_ADDRESS", &err);
|
||||
else
|
||||
{
|
||||
const char *giaddr = NULL;
|
||||
if (data.giaddr.s_addr != 0)
|
||||
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||
giaddr = inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
|
||||
my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err);
|
||||
}
|
||||
|
||||
@@ -640,6 +672,9 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
||||
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
||||
close(pipefd[0]);
|
||||
|
||||
if (data.action == ACTION_RELAY_SNOOP)
|
||||
strcpy(daemon->packet, data.interface);
|
||||
|
||||
p = strrchr(daemon->lease_change_command, '/');
|
||||
if (err == 0)
|
||||
{
|
||||
@@ -810,6 +845,29 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
||||
bytes_in_buf = p - (unsigned char *)buf;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
void queue_relay_snoop(struct in6_addr *client, int if_index, struct in6_addr *prefix, int prefix_len)
|
||||
{
|
||||
/* no script */
|
||||
if (daemon->helperfd == -1)
|
||||
return;
|
||||
|
||||
inet_ntop(AF_INET6, prefix, daemon->addrbuff, ADDRSTRLEN);
|
||||
|
||||
/* 5 for /nnn and zero on the end of the prefix. */
|
||||
buff_alloc(sizeof(struct script_data) + ADDRSTRLEN + 5);
|
||||
memset(buf, 0, sizeof(struct script_data));
|
||||
|
||||
buf->action = ACTION_RELAY_SNOOP;
|
||||
buf->addr6 = *client;
|
||||
buf->hostname_len = sprintf((char *)(buf+1), "%s/%u", daemon->addrbuff, prefix_len) + 1;
|
||||
|
||||
indextoname(daemon->dhcp6fd, if_index, buf->interface);
|
||||
|
||||
bytes_in_buf = sizeof(struct script_data) + buf->hostname_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
/* This nastily re-uses DHCP-fields for TFTP stuff */
|
||||
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+2
-8
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -1180,17 +1180,11 @@ void lease_add_extradata(struct dhcp_lease *lease, unsigned char *data, unsigned
|
||||
if ((lease->extradata_size - lease->extradata_len) < (len + 1))
|
||||
{
|
||||
size_t newsz = lease->extradata_len + len + 100;
|
||||
unsigned char *new = whine_malloc(newsz);
|
||||
unsigned char *new = whine_realloc(lease->extradata, newsz);
|
||||
|
||||
if (!new)
|
||||
return;
|
||||
|
||||
if (lease->extradata)
|
||||
{
|
||||
memcpy(new, lease->extradata, lease->extradata_len);
|
||||
free(lease->extradata);
|
||||
}
|
||||
|
||||
lease->extradata = new;
|
||||
lease->extradata_size = newsz;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -100,10 +100,23 @@ int log_start(struct passwd *ent_pw, int errfd)
|
||||
/* If we're running as root and going to change uid later,
|
||||
change the ownership here so that the file is always owned by
|
||||
the dnsmasq user. Then logrotate can just copy the owner.
|
||||
Failure of the chown call is OK, (for instance when started as non-root) */
|
||||
if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0 &&
|
||||
fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
ret = errno;
|
||||
Failure of the chown call is OK, (for instance when started as non-root).
|
||||
|
||||
If we've created a file with group-id root, we also make
|
||||
the file group-writable. This gives processes in the root group
|
||||
write access to the file and avoids the problem that on some systems,
|
||||
once the file is owned by the dnsmasq user, it can't be written
|
||||
whilst dnsmasq is running as root during startup.
|
||||
*/
|
||||
if (log_to_file && !log_stderr && ent_pw && ent_pw->pw_uid != 0)
|
||||
{
|
||||
struct stat ls;
|
||||
if (getgid() == 0 && fstat(log_fd, &ls) == 0 && ls.st_gid == 0 &&
|
||||
(ls.st_mode & S_IWGRP) == 0)
|
||||
(void)fchmod(log_fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
if (fchown(log_fd, ent_pw->pw_uid, -1) != 0)
|
||||
ret = errno;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -118,7 +131,7 @@ int log_reopen(char *log_file)
|
||||
/* NOTE: umask is set to 022 by the time this gets called */
|
||||
|
||||
if (log_file)
|
||||
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
log_fd = open(log_file, O_WRONLY|O_CREAT|O_APPEND, S_IRUSR|S_IWUSR|S_IRGRP);
|
||||
else
|
||||
{
|
||||
#if defined(HAVE_SOLARIS_NETWORK) || defined(__ANDROID__)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+13
-11
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -66,17 +66,10 @@ char *netlink_init(void)
|
||||
addr.nl_pad = 0;
|
||||
addr.nl_pid = 0; /* autobind */
|
||||
addr.nl_groups = RTMGRP_IPV4_ROUTE;
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV4_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV6_ROUTE;
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_ra || daemon->doing_dhcp6)
|
||||
addr.nl_groups |= RTMGRP_IPV6_IFADDR;
|
||||
#endif
|
||||
|
||||
/* May not be able to have permission to set multicast groups don't die in that case */
|
||||
if ((daemon->netlinkfd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) != -1)
|
||||
{
|
||||
@@ -265,7 +258,16 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
|
||||
while (RTA_OK(rta, len1))
|
||||
{
|
||||
if (rta->rta_type == IFA_ADDRESS)
|
||||
/*
|
||||
* Important comment: (from if_addr.h)
|
||||
* IFA_ADDRESS is prefix address, rather than local interface address.
|
||||
* It makes no difference for normally configured broadcast interfaces,
|
||||
* but for point-to-point IFA_ADDRESS is DESTINATION address,
|
||||
* local address is supplied in IFA_LOCAL attribute.
|
||||
*/
|
||||
if (rta->rta_type == IFA_LOCAL)
|
||||
addrp = ((struct in6_addr *)(rta+1));
|
||||
else if (rta->rta_type == IFA_ADDRESS && !addrp)
|
||||
addrp = ((struct in6_addr *)(rta+1));
|
||||
else if (rta->rta_type == IFA_CACHEINFO)
|
||||
{
|
||||
|
||||
+82
-27
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -114,13 +114,8 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
struct iname *tmp;
|
||||
int ret = 1, match_addr = 0;
|
||||
|
||||
/* Note: have to check all and not bail out early, so that we set the
|
||||
"used" flags.
|
||||
|
||||
May be called with family == AF_LOCALto check interface by name only. */
|
||||
|
||||
if (auth)
|
||||
*auth = 0;
|
||||
/* Note: have to check all and not bail out early, so that we set the "used" flags.
|
||||
May be called with family == AF_LOCAL to check interface by name only. */
|
||||
|
||||
if (daemon->if_names || daemon->if_addrs)
|
||||
{
|
||||
@@ -149,25 +144,29 @@ int iface_check(int family, union all_addr *addr, char *name, int *auth)
|
||||
if (tmp->name && wildcard_match(tmp->name, name))
|
||||
ret = 0;
|
||||
|
||||
|
||||
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||
if (tmp->name)
|
||||
{
|
||||
if (strcmp(tmp->name, name) == 0 &&
|
||||
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
|
||||
break;
|
||||
}
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
break;
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
|
||||
break;
|
||||
|
||||
if (tmp && auth)
|
||||
if (auth)
|
||||
{
|
||||
*auth = 1;
|
||||
ret = 1;
|
||||
*auth = 0;
|
||||
|
||||
for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
|
||||
if (tmp->name)
|
||||
{
|
||||
if (strcmp(tmp->name, name) == 0 &&
|
||||
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
|
||||
break;
|
||||
}
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
|
||||
tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
|
||||
break;
|
||||
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
|
||||
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
|
||||
break;
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
*auth = 1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -232,6 +231,7 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
union mysockaddr *addr, struct in_addr netmask, int prefixlen, int iface_flags)
|
||||
{
|
||||
struct irec *iface;
|
||||
struct cond_domain *cond;
|
||||
int loopback;
|
||||
struct ifreq ifr;
|
||||
int tftp_ok = !!option_bool(OPT_TFTP);
|
||||
@@ -454,7 +454,37 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Update addresses for domain=<domain>,<interface> */
|
||||
for (cond = daemon->cond_domain; cond; cond = cond->next)
|
||||
if (cond->interface && strncmp(label, cond->interface, IF_NAMESIZE) == 0)
|
||||
{
|
||||
struct addrlist *al;
|
||||
|
||||
if (param->spare)
|
||||
{
|
||||
al = param->spare;
|
||||
param->spare = al->next;
|
||||
}
|
||||
else
|
||||
al = whine_malloc(sizeof(struct addrlist));
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
{
|
||||
al->addr.addr4 = addr->in.sin_addr;
|
||||
al->flags = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
al->addr.addr6 = addr->in6.sin6_addr;
|
||||
al->flags = ADDRLIST_IPV6;
|
||||
}
|
||||
|
||||
al->prefixlen = prefixlen;
|
||||
al->next = cond->al;
|
||||
cond->al = al;
|
||||
}
|
||||
|
||||
/* check whether the interface IP has been added already
|
||||
we call this routine multiple times. */
|
||||
for (iface = daemon->interfaces; iface; iface = iface->next)
|
||||
@@ -692,6 +722,7 @@ int enumerate_interfaces(int reset)
|
||||
int errsave, ret = 1;
|
||||
struct addrlist *addr, *tmp;
|
||||
struct interface_name *intname;
|
||||
struct cond_domain *cond;
|
||||
struct irec *iface;
|
||||
#ifdef HAVE_AUTH
|
||||
struct auth_zone *zone;
|
||||
@@ -751,6 +782,19 @@ again:
|
||||
intname->addr = NULL;
|
||||
}
|
||||
|
||||
/* remove addresses stored against cond-domains. */
|
||||
for (cond = daemon->cond_domain; cond; cond = cond->next)
|
||||
{
|
||||
for (addr = cond->al; addr; addr = tmp)
|
||||
{
|
||||
tmp = addr->next;
|
||||
addr->next = spare;
|
||||
spare = addr;
|
||||
}
|
||||
|
||||
cond->al = NULL;
|
||||
}
|
||||
|
||||
/* Remove list of addresses of local interfaces */
|
||||
for (addr = daemon->interface_addrs; addr; addr = tmp)
|
||||
{
|
||||
@@ -1743,6 +1787,8 @@ int reload_servers(char *fname)
|
||||
/* Called when addresses are added or deleted from an interface */
|
||||
void newaddress(time_t now)
|
||||
{
|
||||
struct dhcp_relay *relay;
|
||||
|
||||
(void)now;
|
||||
|
||||
if (option_bool(OPT_CLEVERBIND) || option_bool(OPT_LOCAL_SERVICE) ||
|
||||
@@ -1751,6 +1797,12 @@ void newaddress(time_t now)
|
||||
|
||||
if (option_bool(OPT_CLEVERBIND))
|
||||
create_bound_listeners(0);
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
/* clear cache of subnet->relay index */
|
||||
for (relay = daemon->relay4; relay; relay = relay->next)
|
||||
relay->iface_index = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
|
||||
@@ -1761,5 +1813,8 @@ void newaddress(time_t now)
|
||||
|
||||
if (daemon->doing_dhcp6)
|
||||
lease_find_interfaces(now);
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
relay->iface_index = 0;
|
||||
#endif
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+190
-72
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -175,7 +175,13 @@ struct myoption {
|
||||
#define LOPT_CMARK_ALST 366
|
||||
#define LOPT_QUIET_TFTP 367
|
||||
#define LOPT_NFTSET 368
|
||||
|
||||
#define LOPT_FILTER_A 369
|
||||
#define LOPT_FILTER_AAAA 370
|
||||
#define LOPT_STRIP_SBNET 371
|
||||
#define LOPT_STRIP_MAC 372
|
||||
#define LOPT_CONF_OPT 373
|
||||
#define LOPT_CONF_SCRIPT 374
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
#else
|
||||
@@ -212,6 +218,8 @@ static const struct myoption opts[] =
|
||||
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
|
||||
{ "selfmx", 0, 0, 'e' },
|
||||
{ "filterwin2k", 0, 0, 'f' },
|
||||
{ "filter-A", 0, 0, LOPT_FILTER_A },
|
||||
{ "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
|
||||
{ "pid-file", 2, 0, 'x' },
|
||||
{ "strict-order", 0, 0, 'o' },
|
||||
{ "server", 1, 0, 'S' },
|
||||
@@ -219,6 +227,7 @@ static const struct myoption opts[] =
|
||||
{ "local", 1, 0, LOPT_LOCAL },
|
||||
{ "address", 1, 0, 'A' },
|
||||
{ "conf-file", 2, 0, 'C' },
|
||||
{ "conf-script", 1, 0, LOPT_CONF_SCRIPT },
|
||||
{ "no-resolv", 0, 0, 'R' },
|
||||
{ "expand-hosts", 0, 0, 'E' },
|
||||
{ "localmx", 0, 0, 'L' },
|
||||
@@ -310,7 +319,9 @@ static const struct myoption opts[] =
|
||||
{ "dhcp-generate-names", 2, 0, LOPT_GEN_NAMES },
|
||||
{ "rebind-localhost-ok", 0, 0, LOPT_LOC_REBND },
|
||||
{ "add-mac", 2, 0, LOPT_ADD_MAC },
|
||||
{ "strip-mac", 0, 0, LOPT_STRIP_MAC },
|
||||
{ "add-subnet", 2, 0, LOPT_ADD_SBNET },
|
||||
{ "strip-subnet", 0, 0, LOPT_STRIP_SBNET },
|
||||
{ "add-cpe-id", 1, 0 , LOPT_CPE_ID },
|
||||
{ "proxy-dnssec", 0, 0, LOPT_DNSSEC },
|
||||
{ "dhcp-sequential-ip", 0, 0, LOPT_INCR_ADDR },
|
||||
@@ -353,7 +364,7 @@ static const struct myoption opts[] =
|
||||
{ "dhcp-ignore-clid", 0, 0, LOPT_IGNORE_CLID },
|
||||
{ "dynamic-host", 1, 0, LOPT_DYNHOST },
|
||||
{ "log-debug", 0, 0, LOPT_LOG_DEBUG },
|
||||
{ "umbrella", 2, 0, LOPT_UMBRELLA },
|
||||
{ "umbrella", 2, 0, LOPT_UMBRELLA },
|
||||
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
|
||||
{ NULL, 0, 0, 0 }
|
||||
};
|
||||
@@ -382,6 +393,8 @@ static struct {
|
||||
{ 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
|
||||
{ 'E', OPT_EXPAND, NULL, gettext_noop("Expand simple names in /etc/hosts with domain-suffix."), NULL },
|
||||
{ 'f', OPT_FILTER, NULL, gettext_noop("Don't forward spurious DNS requests from Windows hosts."), NULL },
|
||||
{ LOPT_FILTER_A, OPT_FILTER_A, NULL, gettext_noop("Don't include IPv4 addresses in DNS answers."), NULL },
|
||||
{ LOPT_FILTER_AAAA, OPT_FILTER_AAAA, NULL, gettext_noop("Don't include IPv6 addresses in DNS answers."), NULL },
|
||||
{ 'F', ARG_DUP, "<ipaddr>,...", gettext_noop("Enable DHCP in the range given with lease duration."), NULL },
|
||||
{ 'g', ARG_ONE, "<groupname>", gettext_noop("Change to this group after startup (defaults to %s)."), CHGRP },
|
||||
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
|
||||
@@ -457,6 +470,7 @@ static struct {
|
||||
{ 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 },
|
||||
{ LOPT_CONF_SCRIPT, ARG_DUP, "<path>", gettext_noop("Execute file and read configuration from stdin."), 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)"), "!" },
|
||||
@@ -495,7 +509,9 @@ static struct {
|
||||
{ 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, ARG_DUP, "[=base64|text]", gettext_noop("Add requestor's MAC address to forwarded DNS queries."), NULL },
|
||||
{ LOPT_STRIP_MAC, OPT_STRIP_MAC, NULL, gettext_noop("Strip MAC information from queries."), NULL },
|
||||
{ LOPT_ADD_SBNET, ARG_ONE, "<v4 pref>[,<v6 pref>]", gettext_noop("Add specified IP subnet to forwarded DNS queries."), NULL },
|
||||
{ LOPT_STRIP_SBNET, OPT_STRIP_ECS, NULL, gettext_noop("Strip ECS information from 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 },
|
||||
@@ -657,7 +673,7 @@ static char *canonicalise_opt(char *s)
|
||||
return 0;
|
||||
|
||||
if (strlen(s) == 0)
|
||||
return opt_string_alloc("");
|
||||
return opt_malloc(1); /* Heap-allocated empty string */
|
||||
|
||||
unhide_metas(s);
|
||||
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
||||
@@ -1798,6 +1814,17 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_CONF_SCRIPT: /* --conf-script */
|
||||
{
|
||||
char *file = opt_string_alloc(arg);
|
||||
if (file)
|
||||
{
|
||||
one_file(file, LOPT_CONF_SCRIPT);
|
||||
free(file);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case '7': /* --conf-dir */
|
||||
{
|
||||
DIR *dir_stream;
|
||||
@@ -2227,8 +2254,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
comma = split(arg);
|
||||
|
||||
new = opt_malloc(sizeof(struct auth_zone));
|
||||
new->domain = opt_string_alloc(arg);
|
||||
new->subnet = NULL;
|
||||
new->domain = canonicalise_opt(arg);
|
||||
if (!new->domain)
|
||||
ret_err_free(_("invalid auth-zone"), new);
|
||||
new->subnet = NULL;
|
||||
new->exclude = NULL;
|
||||
new->interface_names = NULL;
|
||||
new->next = daemon->auth_zones;
|
||||
@@ -2463,9 +2492,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
else if (!inet_pton(AF_INET6, arg, &new->end6))
|
||||
ret_err_free(gen_err, new);
|
||||
}
|
||||
else
|
||||
else if (option == 's')
|
||||
{
|
||||
/* subnet from interface. */
|
||||
new->interface = opt_string_alloc(comma);
|
||||
new->al = NULL;
|
||||
}
|
||||
else
|
||||
ret_err_free(gen_err, new);
|
||||
|
||||
|
||||
if (option != 's' && prefstr)
|
||||
{
|
||||
if (!(new->prefix = canonicalise_opt(prefstr)) ||
|
||||
@@ -2511,39 +2546,48 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
|
||||
case LOPT_UMBRELLA: /* --umbrella */
|
||||
set_option_bool(OPT_UMBRELLA);
|
||||
while (arg) {
|
||||
comma = split(arg);
|
||||
if (strstr(arg, "deviceid:")) {
|
||||
arg += 9;
|
||||
if (strlen(arg) != 16)
|
||||
ret_err(gen_err);
|
||||
for (char *p = arg; *p; p++) {
|
||||
if (!isxdigit((int)*p))
|
||||
ret_err(gen_err);
|
||||
}
|
||||
set_option_bool(OPT_UMBRELLA_DEVID);
|
||||
|
||||
u8 *u = daemon->umbrella_device;
|
||||
char word[3];
|
||||
for (u8 i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
|
||||
memcpy(word, &(arg[0]), 2);
|
||||
*u++ = strtoul(word, NULL, 16);
|
||||
}
|
||||
}
|
||||
else if (strstr(arg, "orgid:")) {
|
||||
if (!strtoul_check(arg+6, &daemon->umbrella_org)) {
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
else if (strstr(arg, "assetid:")) {
|
||||
if (!strtoul_check(arg+8, &daemon->umbrella_asset)) {
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
arg = comma;
|
||||
}
|
||||
while (arg)
|
||||
{
|
||||
comma = split(arg);
|
||||
if (strstr(arg, "deviceid:"))
|
||||
{
|
||||
char *p;
|
||||
u8 *u = daemon->umbrella_device;
|
||||
char word[3];
|
||||
|
||||
arg += 9;
|
||||
if (strlen(arg) != 16)
|
||||
ret_err(gen_err);
|
||||
|
||||
for (p = arg; *p; p++)
|
||||
if (!isxdigit((int)*p))
|
||||
ret_err(gen_err);
|
||||
|
||||
set_option_bool(OPT_UMBRELLA_DEVID);
|
||||
|
||||
for (i = 0; i < (int)sizeof(daemon->umbrella_device); i++, arg+=2)
|
||||
{
|
||||
memcpy(word, &(arg[0]), 2);
|
||||
*u++ = strtoul(word, NULL, 16);
|
||||
}
|
||||
}
|
||||
else if (strstr(arg, "orgid:"))
|
||||
{
|
||||
if (!strtoul_check(arg+6, &daemon->umbrella_org))
|
||||
ret_err(gen_err);
|
||||
}
|
||||
else if (strstr(arg, "assetid:"))
|
||||
{
|
||||
if (!strtoul_check(arg+8, &daemon->umbrella_asset))
|
||||
ret_err(gen_err);
|
||||
}
|
||||
else
|
||||
ret_err(gen_err);
|
||||
|
||||
arg = comma;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LOPT_ADD_MAC: /* --add-mac */
|
||||
if (!arg)
|
||||
set_option_bool(OPT_ADD_MAC);
|
||||
@@ -2758,7 +2802,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
|
||||
if (!arg || !*arg)
|
||||
flags = SERV_LITERAL_ADDRESS;
|
||||
else if (option != 'S')
|
||||
else if (option == 'A')
|
||||
{
|
||||
/* # as literal address means return zero address for 4 and 6 */
|
||||
if (strcmp(arg, "#") == 0)
|
||||
@@ -2790,7 +2834,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
flags &= ~SERV_FOR_NODOTS;
|
||||
|
||||
/* address=/#/ matches the same as without domain */
|
||||
if (option != 'S' && domain[0] == '#' && domain[1] == 0)
|
||||
if (option == 'A' && domain[0] == '#' && domain[1] == 0)
|
||||
domain[0] = 0;
|
||||
}
|
||||
|
||||
@@ -4120,7 +4164,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
case LOPT_SUBSCR: /* --dhcp-subscrid */
|
||||
{
|
||||
unsigned char *p;
|
||||
int dig = 0;
|
||||
int dig, colon;
|
||||
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
|
||||
|
||||
if (!(comma = split(arg)))
|
||||
@@ -4144,13 +4188,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
else
|
||||
comma = arg;
|
||||
|
||||
for (p = (unsigned char *)comma; *p; p++)
|
||||
for (dig = 0, colon = 0, p = (unsigned char *)comma; *p; p++)
|
||||
if (isxdigit(*p))
|
||||
dig = 1;
|
||||
else if (*p != ':')
|
||||
else if (*p == ':')
|
||||
colon = 1;
|
||||
else
|
||||
break;
|
||||
|
||||
unhide_metas(comma);
|
||||
if (option == 'U' || option == 'j' || *p || !dig)
|
||||
if (option == 'U' || option == 'j' || *p || !dig || !colon)
|
||||
{
|
||||
new->len = strlen(comma);
|
||||
new->data = opt_malloc(new->len);
|
||||
@@ -4273,26 +4320,66 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case LOPT_RELAY: /* --dhcp-relay */
|
||||
{
|
||||
struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
|
||||
comma = split(arg);
|
||||
new->interface = opt_string_alloc(split(comma));
|
||||
char *two = split(arg);
|
||||
char *three = split(two);
|
||||
|
||||
new->iface_index = 0;
|
||||
if (comma && inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
|
||||
|
||||
if (two)
|
||||
{
|
||||
new->next = daemon->relay4;
|
||||
daemon->relay4 = new;
|
||||
}
|
||||
if (inet_pton(AF_INET, arg, &new->local))
|
||||
{
|
||||
char *hash = split_chr(two, '#');
|
||||
|
||||
if (!hash || !atoi_check16(hash, &new->port))
|
||||
new->port = DHCP_SERVER_PORT;
|
||||
|
||||
if (!inet_pton(AF_INET, two, &new->server))
|
||||
{
|
||||
new->server.addr4.s_addr = 0;
|
||||
|
||||
/* Fail for three arg version where there are not two addresses.
|
||||
Also fail when broadcasting to wildcard address. */
|
||||
if (three || strchr(two, '*'))
|
||||
two = NULL;
|
||||
else
|
||||
three = two;
|
||||
}
|
||||
|
||||
new->next = daemon->relay4;
|
||||
daemon->relay4 = new;
|
||||
}
|
||||
#ifdef HAVE_DHCP6
|
||||
else if (comma && inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
|
||||
{
|
||||
new->next = daemon->relay6;
|
||||
daemon->relay6 = new;
|
||||
}
|
||||
else if (inet_pton(AF_INET6, arg, &new->local))
|
||||
{
|
||||
char *hash = split_chr(two, '#');
|
||||
|
||||
if (!hash || !atoi_check16(hash, &new->port))
|
||||
new->port = DHCPV6_SERVER_PORT;
|
||||
|
||||
if (!inet_pton(AF_INET6, two, &new->server))
|
||||
{
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &new->server.addr6);
|
||||
/* Fail for three arg version where there are not two addresses.
|
||||
Also fail when multicasting to wildcard address. */
|
||||
if (three || strchr(two, '*'))
|
||||
two = NULL;
|
||||
else
|
||||
three = two;
|
||||
}
|
||||
new->next = daemon->relay6;
|
||||
daemon->relay6 = new;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
||||
new->interface = opt_string_alloc(three);
|
||||
}
|
||||
|
||||
if (!two)
|
||||
{
|
||||
free(new->interface);
|
||||
ret_err_free(_("Bad dhcp-relay"), new);
|
||||
@@ -4903,7 +4990,7 @@ err:
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void read_file(char *file, FILE *f, int hard_opt)
|
||||
static void read_file(char *file, FILE *f, int hard_opt, int from_script)
|
||||
{
|
||||
volatile int lineno = 0;
|
||||
char *buff = daemon->namebuff;
|
||||
@@ -4911,10 +4998,12 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
while (fgets(buff, MAXDNAME, f))
|
||||
{
|
||||
int white, i;
|
||||
volatile int option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
|
||||
volatile int option;
|
||||
char *errmess, *p, *arg, *start;
|
||||
size_t len;
|
||||
|
||||
option = (hard_opt == LOPT_REV_SERV) ? 0 : hard_opt;
|
||||
|
||||
/* Memory allocation failure longjmps here if mem_recover == 1 */
|
||||
if (option != 0 || hard_opt == LOPT_REV_SERV)
|
||||
{
|
||||
@@ -4922,7 +5011,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
continue;
|
||||
mem_recover = 1;
|
||||
}
|
||||
|
||||
|
||||
arg = NULL;
|
||||
lineno++;
|
||||
errmess = NULL;
|
||||
@@ -5028,7 +5117,11 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
|
||||
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
|
||||
{
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
|
||||
if (from_script)
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" in output from %s"), file);
|
||||
else
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
|
||||
|
||||
if (hard_opt != 0)
|
||||
my_syslog(LOG_ERR, "%s", daemon->namebuff);
|
||||
else
|
||||
@@ -5037,7 +5130,6 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
}
|
||||
|
||||
mem_recover = 0;
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
#if defined(HAVE_DHCP) && defined(HAVE_INOTIFY)
|
||||
@@ -5057,7 +5149,7 @@ int option_read_dynfile(char *file, int flags)
|
||||
static int one_file(char *file, int hard_opt)
|
||||
{
|
||||
FILE *f;
|
||||
int nofile_ok = 0;
|
||||
int nofile_ok = 0, do_popen = 0;
|
||||
static int read_stdin = 0;
|
||||
static struct fileread {
|
||||
dev_t dev;
|
||||
@@ -5065,14 +5157,20 @@ static int one_file(char *file, int hard_opt)
|
||||
struct fileread *next;
|
||||
} *filesread = NULL;
|
||||
|
||||
if (hard_opt == '7')
|
||||
if (hard_opt == LOPT_CONF_OPT)
|
||||
{
|
||||
/* default conf-file reading */
|
||||
hard_opt = 0;
|
||||
nofile_ok = 1;
|
||||
}
|
||||
|
||||
if (hard_opt == 0 && strcmp(file, "-") == 0)
|
||||
if (hard_opt == LOPT_CONF_SCRIPT)
|
||||
{
|
||||
hard_opt = 0;
|
||||
do_popen = 1;
|
||||
}
|
||||
|
||||
if (hard_opt == 0 && !do_popen && strcmp(file, "-") == 0)
|
||||
{
|
||||
if (read_stdin == 1)
|
||||
return 1;
|
||||
@@ -5099,8 +5197,13 @@ static int one_file(char *file, int hard_opt)
|
||||
r->dev = statbuf.st_dev;
|
||||
r->ino = statbuf.st_ino;
|
||||
}
|
||||
|
||||
if (!(f = fopen(file, "r")))
|
||||
|
||||
if (do_popen)
|
||||
{
|
||||
if (!(f = popen(file, "r")))
|
||||
die(_("cannot execute %s: %s"), file, EC_FILE);
|
||||
}
|
||||
else if (!(f = fopen(file, "r")))
|
||||
{
|
||||
if (errno == ENOENT && nofile_ok)
|
||||
return 1; /* No conffile, all done. */
|
||||
@@ -5118,7 +5221,21 @@ static int one_file(char *file, int hard_opt)
|
||||
}
|
||||
}
|
||||
|
||||
read_file(file, f, hard_opt);
|
||||
read_file(file, f, hard_opt, do_popen);
|
||||
|
||||
if (do_popen)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((rc = pclose(f)) == -1)
|
||||
die(_("error executing %s: %s"), file, EC_MISC);
|
||||
|
||||
if (rc != 0)
|
||||
die(_("%s returns non-zero error code"), file, rc+10);
|
||||
}
|
||||
else
|
||||
fclose(f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -5258,7 +5375,8 @@ void read_servers_file(void)
|
||||
}
|
||||
|
||||
mark_servers(SERV_FROM_FILE);
|
||||
read_file(daemon->servers_file, f, LOPT_REV_SERV);
|
||||
read_file(daemon->servers_file, f, LOPT_REV_SERV, 0);
|
||||
fclose(f);
|
||||
cleanup_servers();
|
||||
check_servers(0);
|
||||
}
|
||||
@@ -5484,7 +5602,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
free(conffile);
|
||||
}
|
||||
else
|
||||
one_file(CONFFILE, '7');
|
||||
one_file(CONFFILE, LOPT_CONF_OPT);
|
||||
|
||||
/* port might not be known when the address is parsed - fill in here */
|
||||
if (daemon->servers)
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -129,9 +129,9 @@ int is_valid_dns_name(const char *value)
|
||||
|
||||
size_t num_bytes = 0;
|
||||
size_t num_labels = 0;
|
||||
const char *label = NULL;
|
||||
const char *c, *label = NULL;
|
||||
int is_label_numeric = 1;
|
||||
for (const char *c = value;; c++)
|
||||
for (c = value;; c++)
|
||||
{
|
||||
if (*c &&
|
||||
*c != '-' && *c != '.' &&
|
||||
@@ -242,11 +242,11 @@ int is_valid_dns_name_pattern(const char *value)
|
||||
|
||||
size_t num_bytes = 0;
|
||||
size_t num_labels = 0;
|
||||
const char *label = NULL;
|
||||
const char *c, *label = NULL;
|
||||
int is_label_numeric = 1;
|
||||
size_t num_wildcards = 0;
|
||||
int previous_label_has_wildcard = 1;
|
||||
for (const char *c = value;; c++)
|
||||
for (c = value;; c++)
|
||||
{
|
||||
if (*c &&
|
||||
*c != '*' && /* Wildcard. */
|
||||
|
||||
+6
-13
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -96,28 +96,21 @@ void poll_listen(int fd, short event)
|
||||
pollfds[i].events |= event;
|
||||
else
|
||||
{
|
||||
if (arrsize != nfds)
|
||||
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
else
|
||||
if (arrsize == nfds)
|
||||
{
|
||||
/* Array too small, extend. */
|
||||
struct pollfd *new;
|
||||
|
||||
arrsize = (arrsize == 0) ? 64 : arrsize * 2;
|
||||
|
||||
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
|
||||
if (!(new = whine_realloc(pollfds, arrsize * sizeof(struct pollfd))))
|
||||
return;
|
||||
|
||||
if (pollfds)
|
||||
{
|
||||
memcpy(new, pollfds, i * sizeof(struct pollfd));
|
||||
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
free(pollfds);
|
||||
}
|
||||
|
||||
pollfds = new;
|
||||
}
|
||||
|
||||
|
||||
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
|
||||
|
||||
pollfds[i].fd = fd;
|
||||
pollfds[i].events = event;
|
||||
nfds++;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+37
-11
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -123,7 +123,11 @@ void ra_start_unsolicited(time_t now, struct dhcp_context *context)
|
||||
and pick up new interfaces */
|
||||
|
||||
if (context)
|
||||
context->ra_short_period_start = context->ra_time = now;
|
||||
{
|
||||
context->ra_short_period_start = now;
|
||||
/* start after 1 second to get logging right at startup. */
|
||||
context->ra_time = now + 1;
|
||||
}
|
||||
else
|
||||
for (context = daemon->dhcp6; context; context = context->next)
|
||||
if (!(context->flags & CONTEXT_TEMPLATE))
|
||||
@@ -162,7 +166,7 @@ void icmp6_packet(time_t now)
|
||||
return;
|
||||
|
||||
packet = (unsigned char *)daemon->outpacket.iov_base;
|
||||
|
||||
|
||||
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
|
||||
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
|
||||
{
|
||||
@@ -187,24 +191,36 @@ void icmp6_packet(time_t now)
|
||||
|
||||
if (packet[1] != 0)
|
||||
return;
|
||||
|
||||
|
||||
if (packet[0] == ICMP6_ECHO_REPLY)
|
||||
lease_ping_reply(&from.sin6_addr, packet, interface);
|
||||
else if (packet[0] == ND_ROUTER_SOLICIT)
|
||||
{
|
||||
char *mac = "";
|
||||
struct dhcp_bridge *bridge, *alias;
|
||||
ssize_t rem;
|
||||
unsigned char *p;
|
||||
int opt_sz;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_icmp(DUMP_RA, (void *)packet, sz, (union mysockaddr *)&from, NULL);
|
||||
#endif
|
||||
|
||||
/* look for link-layer address option for logging */
|
||||
if (sz >= 16 && packet[8] == ICMP6_OPT_SOURCE_MAC && (packet[9] * 8) + 8 <= sz)
|
||||
for (rem = sz - 8, p = &packet[8]; rem >= 2; rem -= opt_sz, p += opt_sz)
|
||||
{
|
||||
if ((packet[9] * 8 - 2) * 3 - 1 >= MAXDNAME) {
|
||||
return;
|
||||
}
|
||||
print_mac(daemon->namebuff, &packet[10], (packet[9] * 8) - 2);
|
||||
mac = daemon->namebuff;
|
||||
opt_sz = p[1] * 8;
|
||||
|
||||
if (opt_sz == 0 || opt_sz > rem)
|
||||
return; /* Bad packet */
|
||||
|
||||
if (p[0] == ICMP6_OPT_SOURCE_MAC && ((opt_sz - 2) * 3 - 1 < MAXDNAME))
|
||||
{
|
||||
print_mac(daemon->namebuff, &p[2], opt_sz - 2);
|
||||
mac = daemon->namebuff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!option_bool(OPT_QUIET_RA))
|
||||
my_syslog(MS_DHCP | LOG_INFO, "RTR-SOLICIT(%s) %s", interface, mac);
|
||||
|
||||
@@ -543,6 +559,16 @@ static void send_ra_alias(time_t now, int iface, char *iface_name, struct in6_ad
|
||||
setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &send_iface, sizeof(send_iface));
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
{
|
||||
struct sockaddr_in6 src;
|
||||
src.sin6_family = AF_INET6;
|
||||
src.sin6_addr = parm.link_local;
|
||||
|
||||
dump_packet_icmp(DUMP_RA, (void *)daemon->outpacket.iov_base, save_counter(-1), (union mysockaddr *)&src, (union mysockaddr *)&addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
|
||||
save_counter(-1), 0, (struct sockaddr *)&addr,
|
||||
sizeof(addr))));
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -1597,7 +1597,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
|
||||
if (addrlist)
|
||||
break;
|
||||
else
|
||||
else if (!(intr->flags & INP4))
|
||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||
intr = intr->next;
|
||||
}
|
||||
@@ -1612,7 +1612,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
|
||||
if (addrlist)
|
||||
break;
|
||||
else
|
||||
else if (!(intr->flags & INP6))
|
||||
while (intr->next && strcmp(intr->intr, intr->next->intr) == 0)
|
||||
intr = intr->next;
|
||||
}
|
||||
|
||||
+12
-14
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -1420,21 +1420,18 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
/* DNSMASQ_REQUESTED_OPTIONS */
|
||||
if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
|
||||
{
|
||||
int len = option_len(opt);
|
||||
int i, 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);
|
||||
lease_add_extradata(lease, (unsigned char *)daemon->namebuff,
|
||||
sprintf(daemon->namebuff, "%u", rop[i]), (i + 1) == len ? 0 : ',');
|
||||
}
|
||||
else
|
||||
{
|
||||
add_extradata_opt(lease, NULL);
|
||||
}
|
||||
|
||||
lease_add_extradata(lease, NULL, 0, 0);
|
||||
|
||||
add_extradata_opt(lease, option_find(mess, sz, OPTION_MUD_URL_V4, 1));
|
||||
|
||||
/* space-concat tag set */
|
||||
if (!tagif_netid)
|
||||
add_extradata_opt(lease, NULL);
|
||||
@@ -2200,8 +2197,9 @@ static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dh
|
||||
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);
|
||||
if (found->basename)
|
||||
snprintf((char *)mess->file, sizeof(mess->file),
|
||||
strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
+201
-100
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -33,9 +33,9 @@ struct state {
|
||||
unsigned int mac_len, mac_type;
|
||||
};
|
||||
|
||||
static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
|
||||
struct in6_addr *client_addr, int is_unicast, time_t now);
|
||||
static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now);
|
||||
static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now);
|
||||
static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_opts);
|
||||
static void log6_packet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
static void log6_quiet(struct state *state, char *type, struct in6_addr *addr, char *string);
|
||||
@@ -104,12 +104,12 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
|
||||
}
|
||||
|
||||
/* This cost me blood to write, it will probably cost you blood to understand - srk. */
|
||||
static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
static int dhcp6_maybe_relay(struct state *state, unsigned char *inbuff, size_t sz,
|
||||
struct in6_addr *client_addr, int is_unicast, time_t now)
|
||||
{
|
||||
void *end = inbuff + sz;
|
||||
void *opts = inbuff + 34;
|
||||
int msg_type = *((unsigned char *)inbuff);
|
||||
int msg_type = *inbuff;
|
||||
unsigned char *outmsgtypep;
|
||||
void *opt;
|
||||
struct dhcp_vendor *vendor;
|
||||
@@ -259,15 +259,15 @@ static int dhcp6_maybe_relay(struct state *state, void *inbuff, size_t sz,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_t sz, int is_unicast, time_t now)
|
||||
static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbuff, size_t sz, int is_unicast, time_t now)
|
||||
{
|
||||
void *opt;
|
||||
int i, o, o1, start_opts;
|
||||
int i, o, o1, start_opts, start_msg;
|
||||
struct dhcp_opt *opt_cfg;
|
||||
struct dhcp_netid *tagif;
|
||||
struct dhcp_config *config = NULL;
|
||||
struct dhcp_netid known_id, iface_id, v6_id;
|
||||
unsigned char *outmsgtypep;
|
||||
unsigned char outmsgtype;
|
||||
struct dhcp_vendor *vendor;
|
||||
struct dhcp_context *context_tmp;
|
||||
struct dhcp_mac *mac_opt;
|
||||
@@ -296,12 +296,13 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
v6_id.next = state->tags;
|
||||
state->tags = &v6_id;
|
||||
|
||||
/* copy over transaction-id, and save pointer to message type */
|
||||
if (!(outmsgtypep = put_opt6(inbuff, 4)))
|
||||
start_msg = save_counter(-1);
|
||||
/* copy over transaction-id */
|
||||
if (!put_opt6(inbuff, 4))
|
||||
return 0;
|
||||
start_opts = save_counter(-1);
|
||||
state->xid = outmsgtypep[3] | outmsgtypep[2] << 8 | outmsgtypep[1] << 16;
|
||||
|
||||
state->xid = inbuff[3] | inbuff[2] << 8 | inbuff[1] << 16;
|
||||
|
||||
/* We're going to be linking tags from all context we use.
|
||||
mark them as unused so we don't link one twice and break the list */
|
||||
for (context_tmp = state->context; context_tmp; context_tmp = context_tmp->current)
|
||||
@@ -347,7 +348,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
(msg_type == DHCP6REQUEST || msg_type == DHCP6RENEW || msg_type == DHCP6RELEASE || msg_type == DHCP6DECLINE))
|
||||
|
||||
{
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6USEMULTI);
|
||||
put_opt6_string("Use multicast");
|
||||
@@ -619,11 +620,11 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
struct dhcp_netid *solicit_tags;
|
||||
struct dhcp_context *c;
|
||||
|
||||
*outmsgtypep = DHCP6ADVERTISE;
|
||||
outmsgtype = DHCP6ADVERTISE;
|
||||
|
||||
if (opt6_find(state->packet_options, state->end, OPTION6_RAPID_COMMIT, 0))
|
||||
{
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
state->lease_allocate = 1;
|
||||
o = new_opt6(OPTION6_RAPID_COMMIT);
|
||||
end_opt6(o);
|
||||
@@ -809,7 +810,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int start = save_counter(-1);
|
||||
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
state->lease_allocate = 1;
|
||||
|
||||
log6_quiet(state, "DHCPREQUEST", NULL, ignore ? _("ignored") : NULL);
|
||||
@@ -924,7 +925,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int address_assigned = 0;
|
||||
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, msg_type == DHCP6RENEW ? "DHCPRENEW" : "DHCPREBIND", NULL, NULL);
|
||||
|
||||
@@ -1057,7 +1058,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int good_addr = 0;
|
||||
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPCONFIRM", NULL, NULL);
|
||||
|
||||
@@ -1121,7 +1122,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
log6_quiet(state, "DHCPINFORMATION-REQUEST", NULL, ignore ? _("ignored") : state->hostname);
|
||||
if (ignore)
|
||||
return 0;
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
tagif = add_options(state, 1);
|
||||
break;
|
||||
}
|
||||
@@ -1130,7 +1131,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
case DHCP6RELEASE:
|
||||
{
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPRELEASE", NULL, NULL);
|
||||
|
||||
@@ -1195,7 +1196,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
case DHCP6DECLINE:
|
||||
{
|
||||
/* set reply message type */
|
||||
*outmsgtypep = DHCP6REPLY;
|
||||
outmsgtype = DHCP6REPLY;
|
||||
|
||||
log6_quiet(state, "DHCPDECLINE", NULL, NULL);
|
||||
|
||||
@@ -1275,7 +1276,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Fill in the message type. Note that we store the offset,
|
||||
not a direct pointer, since the packet memory may have been
|
||||
reallocated. */
|
||||
((unsigned char *)(daemon->outpacket.iov_base))[start_msg] = outmsgtype;
|
||||
|
||||
log_tags(tagif, state->xid);
|
||||
log6_opts(0, state->xid, daemon->outpacket.iov_base + start_opts, daemon->outpacket.iov_base + save_counter(-1));
|
||||
|
||||
@@ -1873,23 +1879,24 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command)
|
||||
{
|
||||
void *class_opt;
|
||||
void *opt;
|
||||
|
||||
lease->flags |= LEASE_CHANGED;
|
||||
free(lease->extradata);
|
||||
lease->extradata = NULL;
|
||||
lease->extradata_size = lease->extradata_len = 0;
|
||||
lease->vendorclass_count = 0;
|
||||
|
||||
if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
|
||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_VENDOR_CLASS, 4)))
|
||||
{
|
||||
void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
|
||||
void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
|
||||
lease->vendorclass_count++;
|
||||
/* send enterprise number first */
|
||||
sprintf(daemon->dhcp_buff2, "%u", opt6_uint(class_opt, 0, 4));
|
||||
sprintf(daemon->dhcp_buff2, "%u", opt6_uint(opt, 0, 4));
|
||||
lease_add_extradata(lease, (unsigned char *)daemon->dhcp_buff2, strlen(daemon->dhcp_buff2), 0);
|
||||
|
||||
if (opt6_len(class_opt) >= 6)
|
||||
for (enc_opt = opt6_ptr(class_opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
||||
if (opt6_len(opt) >= 6)
|
||||
for (enc_opt = opt6_ptr(opt, 4); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
||||
{
|
||||
lease->vendorclass_count++;
|
||||
lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
|
||||
@@ -1899,6 +1906,24 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
|
||||
lease_add_extradata(lease, (unsigned char *)state->client_hostname,
|
||||
state->client_hostname ? strlen(state->client_hostname) : 0, 0);
|
||||
|
||||
/* DNSMASQ_REQUESTED_OPTIONS */
|
||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_ORO, 2)))
|
||||
{
|
||||
int i, len = opt6_len(opt)/2;
|
||||
u16 *rop = opt6_ptr(opt, 0);
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
lease_add_extradata(lease, (unsigned char *)daemon->namebuff,
|
||||
sprintf(daemon->namebuff, "%u", ntohs(rop[i])), (i + 1) == len ? 0 : ',');
|
||||
}
|
||||
else
|
||||
lease_add_extradata(lease, NULL, 0, 0);
|
||||
|
||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_MUD_URL, 1)))
|
||||
lease_add_extradata(lease, opt6_ptr(opt, 0), opt6_len(opt), 0);
|
||||
else
|
||||
lease_add_extradata(lease, NULL, 0, 0);
|
||||
|
||||
/* space-concat tag set */
|
||||
if (!tagif && !context->netid.net)
|
||||
lease_add_extradata(lease, NULL, 0, 0);
|
||||
@@ -1928,10 +1953,10 @@ static void update_leases(struct state *state, struct dhcp_context *context, str
|
||||
|
||||
lease_add_extradata(lease, (unsigned char *)daemon->addrbuff, state->link_address ? strlen(daemon->addrbuff) : 0, 0);
|
||||
|
||||
if ((class_opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
|
||||
if ((opt = opt6_find(state->packet_options, state->end, OPTION6_USER_CLASS, 2)))
|
||||
{
|
||||
void *enc_opt, *enc_end = opt6_ptr(class_opt, opt6_len(class_opt));
|
||||
for (enc_opt = opt6_ptr(class_opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
||||
void *enc_opt, *enc_end = opt6_ptr(opt, opt6_len(opt));
|
||||
for (enc_opt = opt6_ptr(opt, 0); enc_opt; enc_opt = opt6_next(enc_opt, enc_end))
|
||||
lease_add_extradata(lease, opt6_ptr(enc_opt, 0), opt6_len(enc_opt), 0);
|
||||
}
|
||||
}
|
||||
@@ -2100,95 +2125,106 @@ 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, time_t now)
|
||||
int relay_upstream6(int iface_index, ssize_t sz,
|
||||
struct in6_addr *peer_address, u32 scope_id, time_t now)
|
||||
{
|
||||
/* ->local is same value for all relays on ->current chain */
|
||||
|
||||
union all_addr from;
|
||||
unsigned char *header;
|
||||
unsigned char *inbuff = daemon->dhcp_packet.iov_base;
|
||||
int msg_type = *inbuff;
|
||||
int hopcount;
|
||||
int hopcount, o;
|
||||
struct in6_addr multicast;
|
||||
unsigned int maclen, mactype;
|
||||
unsigned char mac[DHCP_CHADDR_MAX];
|
||||
struct dhcp_relay *relay;
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
break;
|
||||
|
||||
/* No relay config. */
|
||||
if (!relay)
|
||||
return 0;
|
||||
|
||||
inet_pton(AF_INET6, ALL_SERVERS, &multicast);
|
||||
get_client_mac(peer_address, scope_id, mac, &maclen, &mactype, now);
|
||||
|
||||
/* source address == relay address */
|
||||
from.addr6 = relay->local.addr6;
|
||||
|
||||
|
||||
/* Get hop count from nested relayed message */
|
||||
if (msg_type == DHCP6RELAYFORW)
|
||||
hopcount = *((unsigned char *)inbuff+1) + 1;
|
||||
else
|
||||
hopcount = 0;
|
||||
|
||||
/* RFC 3315 HOP_COUNT_LIMIT */
|
||||
if (hopcount > 32)
|
||||
return;
|
||||
|
||||
reset_counter();
|
||||
|
||||
if ((header = put_opt6(NULL, 34)))
|
||||
/* RFC 3315 HOP_COUNT_LIMIT */
|
||||
if (hopcount > 32 || !(header = put_opt6(NULL, 34)))
|
||||
return 1;
|
||||
|
||||
header[0] = DHCP6RELAYFORW;
|
||||
header[1] = hopcount;
|
||||
memcpy(&header[18], peer_address, IN6ADDRSZ);
|
||||
|
||||
/* RFC-6939 */
|
||||
if (maclen != 0)
|
||||
{
|
||||
int o;
|
||||
|
||||
header[0] = DHCP6RELAYFORW;
|
||||
header[1] = hopcount;
|
||||
memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ);
|
||||
memcpy(&header[18], peer_address, IN6ADDRSZ);
|
||||
|
||||
/* RFC-6939 */
|
||||
if (maclen != 0)
|
||||
{
|
||||
o = new_opt6(OPTION6_CLIENT_MAC);
|
||||
put_opt6_short(mactype);
|
||||
put_opt6(mac, maclen);
|
||||
end_opt6(o);
|
||||
}
|
||||
|
||||
o = new_opt6(OPTION6_RELAY_MSG);
|
||||
put_opt6(inbuff, sz);
|
||||
o = new_opt6(OPTION6_CLIENT_MAC);
|
||||
put_opt6_short(mactype);
|
||||
put_opt6(mac, maclen);
|
||||
end_opt6(o);
|
||||
|
||||
for (; relay; relay = relay->current)
|
||||
{
|
||||
union mysockaddr to;
|
||||
|
||||
to.sa.sa_family = AF_INET6;
|
||||
to.in6.sin6_addr = relay->server.addr6;
|
||||
to.in6.sin6_port = htons(DHCPV6_SERVER_PORT);
|
||||
to.in6.sin6_flowinfo = 0;
|
||||
to.in6.sin6_scope_id = 0;
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
|
||||
{
|
||||
int multicast_iface;
|
||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||
(multicast_iface = if_nametoindex(relay->interface)) == 0 ||
|
||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
|
||||
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(-1), &to, &from, 0);
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->namebuff);
|
||||
}
|
||||
|
||||
/* Save this for replies */
|
||||
relay->iface_index = scope_id;
|
||||
}
|
||||
}
|
||||
|
||||
o = new_opt6(OPTION6_RELAY_MSG);
|
||||
put_opt6(inbuff, sz);
|
||||
end_opt6(o);
|
||||
|
||||
for (; relay; relay = relay->next)
|
||||
if (relay->iface_index != 0 && relay->iface_index == iface_index)
|
||||
{
|
||||
union mysockaddr to;
|
||||
|
||||
memcpy(&header[2], &relay->local.addr6, IN6ADDRSZ);
|
||||
|
||||
to.sa.sa_family = AF_INET6;
|
||||
to.in6.sin6_addr = relay->server.addr6;
|
||||
to.in6.sin6_port = htons(relay->port);
|
||||
to.in6.sin6_flowinfo = 0;
|
||||
to.in6.sin6_scope_id = 0;
|
||||
|
||||
if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
|
||||
{
|
||||
int multicast_iface;
|
||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||
(multicast_iface = if_nametoindex(relay->interface)) == 0 ||
|
||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
|
||||
{
|
||||
my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_DHCPV6, (void *)daemon->outpacket.iov_base, save_counter(-1), NULL, &to, daemon->dhcp6fd);
|
||||
#endif
|
||||
|
||||
while (retry_send(sendto(daemon->dhcp6fd, (void *)daemon->outpacket.iov_base, save_counter(-1),
|
||||
0, (struct sockaddr *)&to, sa_len(&to))));
|
||||
|
||||
if (option_bool(OPT_LOG_OPTS))
|
||||
{
|
||||
inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||
if (IN6_ARE_ADDR_EQUAL(&relay->server.addr6, &multicast))
|
||||
snprintf(daemon->namebuff, MAXDNAME, _("multicast via %s"), relay->interface);
|
||||
else
|
||||
inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
|
||||
int relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival_interface)
|
||||
{
|
||||
struct dhcp_relay *relay;
|
||||
struct in6_addr link;
|
||||
@@ -2220,11 +2256,76 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
|
||||
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||
memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
|
||||
peer->sin6_scope_id = relay->iface_index;
|
||||
return encap_type == DHCP6RELAYREPL ? DHCPV6_SERVER_PORT : DHCPV6_CLIENT_PORT;
|
||||
}
|
||||
}
|
||||
|
||||
if (encap_type == DHCP6RELAYREPL)
|
||||
{
|
||||
peer->sin6_port = ntohs(DHCPV6_SERVER_PORT);
|
||||
return 1;
|
||||
}
|
||||
|
||||
peer->sin6_port = ntohs(DHCPV6_CLIENT_PORT);
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
if (daemon->lease_change_command && encap_type == DHCP6REPLY)
|
||||
{
|
||||
/* decapsulate relayed message */
|
||||
opts = opt6_ptr(opt, 4);
|
||||
end = opt6_ptr(opt, opt6_len(opt));
|
||||
|
||||
for (opt = opts; opt; opt = opt6_next(opt, end))
|
||||
if (opt6_type(opt) == OPTION6_IA_PD && opt6_len(opt) > 12)
|
||||
{
|
||||
void *ia_opts = opt6_ptr(opt, 12);
|
||||
void *ia_end = opt6_ptr(opt, opt6_len(opt));
|
||||
void *ia_opt;
|
||||
|
||||
for (ia_opt = ia_opts; ia_opt; ia_opt = opt6_next(ia_opt, ia_end))
|
||||
/* valid lifetime must not be zero. */
|
||||
if (opt6_type(ia_opt) == OPTION6_IAPREFIX && opt6_len(ia_opt) >= 25 && opt6_uint(ia_opt, 4, 4) != 0)
|
||||
{
|
||||
if (daemon->free_snoops ||
|
||||
(daemon->free_snoops = whine_malloc(sizeof(struct snoop_record))))
|
||||
{
|
||||
struct snoop_record *snoop = daemon->free_snoops;
|
||||
|
||||
daemon->free_snoops = snoop->next;
|
||||
snoop->client = peer->sin6_addr;
|
||||
snoop->prefix_len = opt6_uint(ia_opt, 8, 1);
|
||||
memcpy(&snoop->prefix, opt6_ptr(ia_opt, 9), IN6ADDRSZ);
|
||||
snoop->next = relay->snoop_records;
|
||||
relay->snoop_records = snoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SCRIPT
|
||||
int do_snoop_script_run(void)
|
||||
{
|
||||
struct dhcp_relay *relay;
|
||||
struct snoop_record *snoop;
|
||||
|
||||
for (relay = daemon->relay6; relay; relay = relay->next)
|
||||
if ((snoop = relay->snoop_records))
|
||||
{
|
||||
relay->snoop_records = snoop->next;
|
||||
snoop->next = daemon->free_snoops;
|
||||
daemon->free_snoops = snoop;
|
||||
|
||||
queue_relay_snoop(&snoop->client, relay->iface_index, &snoop->prefix, snoop->prefix_len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+34
-21
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -156,10 +156,10 @@ static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, i
|
||||
}
|
||||
|
||||
|
||||
/* mode is 0 to remove EDNS0, 1 to filter DNSSEC RRs */
|
||||
/* mode may be remove EDNS0 or DNSSEC RRs or remove A or AAAA from answer section. */
|
||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
||||
{
|
||||
static unsigned char **rrs;
|
||||
static unsigned char **rrs = NULL;
|
||||
static int rr_sz = 0;
|
||||
|
||||
unsigned char *p = (unsigned char *)(header+1);
|
||||
@@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
||||
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 */
|
||||
if (mode == RRFILTER_EDNS0) /* 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;
|
||||
|
||||
else if (mode == RRFILTER_DNSSEC)
|
||||
{
|
||||
if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
|
||||
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
|
||||
continue;
|
||||
|
||||
/* Don't remove the answer. */
|
||||
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only looking at answer section now. */
|
||||
if (i >= ntohs(header->ancount))
|
||||
break;
|
||||
|
||||
if (class != C_IN)
|
||||
continue;
|
||||
|
||||
if (mode == RRFILTER_A && type != T_A)
|
||||
continue;
|
||||
|
||||
if (mode == RRFILTER_AAAA && type != T_AAAA)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
|
||||
return plen;
|
||||
@@ -322,15 +339,11 @@ int expand_workspace(unsigned char ***wkspc, int *szp, int new)
|
||||
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);
|
||||
}
|
||||
|
||||
if (!(p = whine_realloc(*wkspc, new * sizeof(unsigned char *))))
|
||||
return 0;
|
||||
|
||||
memset(p+old, 0, new-old);
|
||||
|
||||
*wkspc = p;
|
||||
*szp = new;
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
|
||||
+33
-18
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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,9 +19,9 @@
|
||||
#ifdef HAVE_TFTP
|
||||
|
||||
static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len);
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix);
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *client);
|
||||
static void free_transfer(struct tftp_transfer *transfer);
|
||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file);
|
||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file, char *arg2);
|
||||
static ssize_t tftp_err_oops(char *packet, const char *file);
|
||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
||||
static char *next(char **p, char *end);
|
||||
@@ -95,6 +95,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
|
||||
if ((len = recvmsg(listen->tftpfd, &msg, 0)) < 2)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_TFTP, (void *)packet, len, (union mysockaddr *)&peer, NULL, listen->tftpfd);
|
||||
#endif
|
||||
|
||||
/* Can always get recvd interface for IPv6 */
|
||||
if (!check_dest)
|
||||
@@ -362,7 +366,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
!(mode = next(&p, end)) ||
|
||||
(strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
|
||||
{
|
||||
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff);
|
||||
len = tftp_err(ERR_ILL, packet, _("unsupported request from %s"), daemon->addrbuff, NULL);
|
||||
is_err = 1;
|
||||
}
|
||||
else
|
||||
@@ -472,7 +476,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||
|
||||
/* check permissions and open file */
|
||||
if ((transfer->file = check_tftp_fileperm(&len, prefix)))
|
||||
if ((transfer->file = check_tftp_fileperm(&len, prefix, daemon->addrbuff)))
|
||||
{
|
||||
if ((len = get_block(packet, transfer)) == -1)
|
||||
len = tftp_err_oops(packet, daemon->namebuff);
|
||||
@@ -482,6 +486,10 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
}
|
||||
|
||||
send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), packet, len, &peer, &addra, if_index);
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_TFTP, (void *)packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
|
||||
#endif
|
||||
|
||||
if (is_err)
|
||||
free_transfer(transfer);
|
||||
@@ -492,7 +500,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
}
|
||||
}
|
||||
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix, char *client)
|
||||
{
|
||||
char *packet = daemon->packet, *namebuff = daemon->namebuff;
|
||||
struct tftp_file *file;
|
||||
@@ -509,7 +517,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
{
|
||||
if (errno == ENOENT)
|
||||
{
|
||||
*len = tftp_err(ERR_FNF, packet, _("file %s not found"), namebuff);
|
||||
*len = tftp_err(ERR_FNF, packet, _("file %s not found for %s"), namebuff, client);
|
||||
return NULL;
|
||||
}
|
||||
else if (errno == EACCES)
|
||||
@@ -562,8 +570,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
||||
return file;
|
||||
|
||||
perm:
|
||||
errno = EACCES;
|
||||
*len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
|
||||
*len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff, strerror(EACCES));
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return NULL;
|
||||
@@ -599,8 +606,12 @@ void check_tftp_listeners(time_t now)
|
||||
{
|
||||
/* Wrong source address. See rfc1350 para 4. */
|
||||
prettyprint_addr(&peer, daemon->addrbuff);
|
||||
len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff);
|
||||
len = tftp_err(ERR_TID, daemon->packet, _("ignoring packet from %s (TID mismatch)"), daemon->addrbuff, NULL);
|
||||
while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer))));
|
||||
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&peer, transfer->sockfd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -635,9 +646,14 @@ void check_tftp_listeners(time_t now)
|
||||
}
|
||||
|
||||
if (len != 0)
|
||||
send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len,
|
||||
&transfer->peer, &transfer->source, transfer->if_index);
|
||||
|
||||
{
|
||||
send_from(transfer->sockfd, !option_bool(OPT_SINGLE_PORT), daemon->packet, len,
|
||||
&transfer->peer, &transfer->source, transfer->if_index);
|
||||
#ifdef HAVE_DUMPFILE
|
||||
dump_packet_udp(DUMP_TFTP, (void *)daemon->packet, len, NULL, (union mysockaddr *)&transfer->peer, transfer->sockfd);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (endcon || len == 0)
|
||||
{
|
||||
strcpy(daemon->namebuff, transfer->file->filename);
|
||||
@@ -743,22 +759,21 @@ 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)
|
||||
static ssize_t tftp_err(int err, char *packet, char *message, char *file, char *arg2)
|
||||
{
|
||||
struct errmess {
|
||||
unsigned short op, err;
|
||||
char message[];
|
||||
} *mess = (struct errmess *)packet;
|
||||
ssize_t len, ret = 4;
|
||||
char *errstr = strerror(errno);
|
||||
|
||||
|
||||
memset(packet, 0, daemon->packet_buff_sz);
|
||||
if (file)
|
||||
sanitise(file);
|
||||
|
||||
mess->op = htons(OP_ERR);
|
||||
mess->err = htons(err);
|
||||
len = snprintf(mess->message, MAXMESSAGE, message, file, errstr);
|
||||
len = snprintf(mess->message, MAXMESSAGE, message, file, arg2);
|
||||
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
|
||||
|
||||
if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
|
||||
@@ -772,7 +787,7 @@ static ssize_t tftp_err_oops(char *packet, const char *file)
|
||||
/* May have >1 refs to file, so potentially mangle a copy of the name */
|
||||
if (file != daemon->namebuff)
|
||||
strcpy(daemon->namebuff, file);
|
||||
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff);
|
||||
return tftp_err(ERR_NOTDEF, packet, _("cannot read %s: %s"), daemon->namebuff, strerror(errno));
|
||||
}
|
||||
|
||||
/* return -1 for error, zero for done. */
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
||||
+23
-7
@@ -1,4 +1,4 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||
/* dnsmasq is Copyright (c) 2000-2022 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
|
||||
@@ -233,8 +233,6 @@ char *canonicalise(char *in, int *nomem)
|
||||
{
|
||||
# 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
|
||||
@@ -338,6 +336,16 @@ void *whine_malloc(size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *whine_realloc(void *ptr, size_t size)
|
||||
{
|
||||
void *ret = realloc(ptr, size);
|
||||
|
||||
if (!ret)
|
||||
my_syslog(LOG_ERR, _("failed to reallocate %d bytes"), (int) size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2)
|
||||
{
|
||||
if (s1->sa.sa_family == s2->sa.sa_family)
|
||||
@@ -369,7 +377,7 @@ int sa_len(union mysockaddr *addr)
|
||||
}
|
||||
|
||||
/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
|
||||
int hostname_isequal(const char *a, const char *b)
|
||||
int hostname_order(const char *a, const char *b)
|
||||
{
|
||||
unsigned int c1, c2;
|
||||
|
||||
@@ -382,11 +390,19 @@ int hostname_isequal(const char *a, const char *b)
|
||||
if (c2 >= 'A' && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
|
||||
if (c1 != c2)
|
||||
return 0;
|
||||
if (c1 < c2)
|
||||
return -1;
|
||||
else if (c1 > c2)
|
||||
return 1;
|
||||
|
||||
} while (c1);
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hostname_isequal(const char *a, const char *b)
|
||||
{
|
||||
return hostname_order(a, b) == 0;
|
||||
}
|
||||
|
||||
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
|
||||
|
||||
Reference in new issue
Block a user