mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-13 17:00:49 +00:00
Compare commits
61
Commits
v2.87test1
...
v2.87test5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
553c4c99cc | ||
|
|
4165c1331b | ||
|
|
b2690415bf | ||
|
|
011f8cf1d0 | ||
|
|
2748fb81e2 | ||
|
|
46312909d9 | ||
|
|
41adecad14 | ||
|
|
ea5d8c56a0 | ||
|
|
d242cbffa4 | ||
|
|
1c8855ed10 | ||
|
|
ea33a01303 | ||
|
|
18b1d1424e | ||
|
|
1176cd58c9 | ||
|
|
44a4643b62 | ||
|
|
ed96efd865 | ||
|
|
e3093b532c | ||
|
|
9560658c5b | ||
|
|
37a70d39e0 | ||
|
|
72fac0810c | ||
|
|
c166c07a93 | ||
|
|
39a625ff72 | ||
|
|
ad32ca18a7 | ||
|
|
efea282396 | ||
|
|
33d6a01cd3 | ||
|
|
d290630d31 | ||
|
|
d2ad5dc073 | ||
|
|
68ab5127af | ||
|
|
089a11f340 | ||
|
|
de1d04eb66 | ||
|
|
ed4e7defd7 | ||
|
|
267ab619c4 | ||
|
|
0140454ba2 | ||
|
|
2c60441239 | ||
|
|
cbbd56c965 | ||
|
|
2561f9fe0e | ||
|
|
47aefca5e4 | ||
|
|
981fb03710 | ||
|
|
ef2f8d70d2 | ||
|
|
d9995a1add | ||
|
|
ea7a05ad43 | ||
|
|
26bbf5a314 | ||
|
|
c147329823 | ||
|
|
eb88eed1fc | ||
|
|
8312a3ba4f | ||
|
|
35f93081dc | ||
|
|
de372d6914 | ||
|
|
4ac517e4ac | ||
|
|
e3651367b3 | ||
|
|
02ea41ddd1 | ||
|
|
51ffae4eab | ||
|
|
afe84f37f8 | ||
|
|
0afeef0e00 | ||
|
|
94a17fd97f | ||
|
|
5b5ec55445 | ||
|
|
1e6565c1a5 | ||
|
|
fc522515b9 | ||
|
|
9881b0736d | ||
|
|
e52b4b1466 | ||
|
|
2f45670951 | ||
|
|
50d75ae514 | ||
|
|
dea69a12aa |
No files matched your search
@@ -1,3 +1,37 @@
|
|||||||
|
version 2.87
|
||||||
|
Allow arbitrary prefix lengths in --rev-server and
|
||||||
|
--domain=....,local
|
||||||
|
|
||||||
|
Replace --address=/#/..... functionality which got
|
||||||
|
missed in the 2.86 domain search rewrite.
|
||||||
|
|
||||||
|
Add --nftset option, like --ipset but for the newer nftables.
|
||||||
|
Thanks to Chen Zhenge for the patch.
|
||||||
|
|
||||||
|
Add --filter-A and --filter-AAAA options, to remove IPv4 or IPv6
|
||||||
|
addresses from DNS answers.
|
||||||
|
|
||||||
|
Fix crash doing netbooting when --port is set to zero
|
||||||
|
to disable the DNS server. Thanks to Drexl Johannes
|
||||||
|
for the bug report.
|
||||||
|
|
||||||
|
Generalise --dhcp-relay. Sending via broadcast/multicast is
|
||||||
|
now supported for both IPv4 and IPv6 and the configuration
|
||||||
|
syntax made easier (but backwards compatible).
|
||||||
|
|
||||||
|
Add snooping of IPv6 prefix-delegations to the DHCP-relay system.
|
||||||
|
|
||||||
|
Finesse parsing of --dhcp-remoteid and --dhcp-subscrid. To be treated
|
||||||
|
as hex, the pattern must consist of only hex digits AND contain
|
||||||
|
at least one ':'. Thanks to Bengt-Erik Sandstrom who tripped
|
||||||
|
over a pattern consisting of a decimal number which was interpreted
|
||||||
|
surprisingly.
|
||||||
|
|
||||||
|
Include client address in TFTP file-not-found error reports.
|
||||||
|
Thanks to Stefan Rink for the initial patch, which has been
|
||||||
|
re-worked by me (srk). All bugs mine.
|
||||||
|
|
||||||
|
|
||||||
version 2.86
|
version 2.86
|
||||||
Handle DHCPREBIND requests in the DHCPv6 server code.
|
Handle DHCPREBIND requests in the DHCPv6 server code.
|
||||||
Thanks to Aichun Li for spotting this omission, and the initial
|
Thanks to Aichun Li for spotting this omission, and the initial
|
||||||
@@ -92,6 +126,9 @@ version 2.86
|
|||||||
of filename). Thanks to Ed Wildgoose for the initial patch
|
of filename). Thanks to Ed Wildgoose for the initial patch
|
||||||
and motivation for this.
|
and motivation for this.
|
||||||
|
|
||||||
|
Allow adding IP address to nftables set in addition to
|
||||||
|
ipset.
|
||||||
|
|
||||||
|
|
||||||
version 2.85
|
version 2.85
|
||||||
Fix problem with DNS retries in 2.83/2.84.
|
Fix problem with DNS retries in 2.83/2.84.
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CO
|
|||||||
HAVE_NETTLEHASH $(PKG_CONFIG) --libs nettle`
|
HAVE_NETTLEHASH $(PKG_CONFIG) --libs nettle`
|
||||||
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
|
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
|
||||||
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
|
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
|
||||||
|
nft_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_NFTSET $(PKG_CONFIG) --cflags libnftables`
|
||||||
|
nft_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_NFTSET $(PKG_CONFIG) --libs libnftables`
|
||||||
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
|
||||||
|
|
||||||
sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
|
sum?=$(shell $(CC) -DDNSMASQ_COMPILE_OPTS $(COPTS) -E $(top)/$(SRC)/dnsmasq.h | ( md5sum 2>/dev/null || md5 ) | cut -f 1 -d ' ')
|
||||||
@@ -82,7 +84,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
|||||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o pattern.o \
|
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o pattern.o \
|
||||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||||
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o \
|
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o \
|
||||||
metrics.o hash-questions.o domain-match.o
|
metrics.o hash-questions.o domain-match.o nftset.o
|
||||||
|
|
||||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||||
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
|
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
|
||||||
@@ -90,8 +92,8 @@ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
|||||||
all : $(BUILDDIR)
|
all : $(BUILDDIR)
|
||||||
@cd $(BUILDDIR) && $(MAKE) \
|
@cd $(BUILDDIR) && $(MAKE) \
|
||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
|
||||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
|
||||||
-f $(top)/Makefile dnsmasq
|
-f $(top)/Makefile dnsmasq
|
||||||
|
|
||||||
mostly_clean :
|
mostly_clean :
|
||||||
@@ -115,8 +117,8 @@ all-i18n : $(BUILDDIR)
|
|||||||
@cd $(BUILDDIR) && $(MAKE) \
|
@cd $(BUILDDIR) && $(MAKE) \
|
||||||
top="$(top)" \
|
top="$(top)" \
|
||||||
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
i18n=-DLOCALEDIR=\'\"$(LOCALEDIR)\"\' \
|
||||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags) $(nft_cflags)" \
|
||||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs) $(nft_libs)" \
|
||||||
-f $(top)/Makefile dnsmasq
|
-f $(top)/Makefile dnsmasq
|
||||||
for f in `cd $(PO); echo *.po`; do \
|
for f in `cd $(PO); echo *.po`; do \
|
||||||
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
cd $(top) && cd $(BUILDDIR) && $(MAKE) top="$(top)" -f $(top)/Makefile $${f%.po}.mo; \
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
This packaging is now unmaintained in the dnsmasq source: dnsmasq is
|
|
||||||
included in Suse proper, and up-to-date packages are now available
|
|
||||||
from
|
|
||||||
|
|
||||||
ftp://ftp.suse.com/pub/people/ug/
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
This is a patch against SuSEfirewall2-3.1-206 (SuSE 9.x and older)
|
|
||||||
It fixes the dependency from the dns daemon name 'named'
|
|
||||||
After appending the patch, the SuSEfirewall is again able to autodetect
|
|
||||||
the dnsmasq named service.
|
|
||||||
This is a very old bug in the SuSEfirewall script.
|
|
||||||
The SuSE people think the name of the dns server will always 'named'
|
|
||||||
|
|
||||||
|
|
||||||
--- /sbin/SuSEfirewall2.orig 2004-01-23 13:30:09.000000000 +0100
|
|
||||||
+++ /sbin/SuSEfirewall2 2004-01-23 13:31:56.000000000 +0100
|
|
||||||
@@ -764,7 +764,7 @@
|
|
||||||
echo 'FW_ALLOW_INCOMING_HIGHPORTS_UDP should be set to yes, if you are running a DNS server!'
|
|
||||||
|
|
||||||
test "$FW_SERVICE_AUTODETECT" = yes -o "$FW_SERVICE_AUTODETECT" = dmz -o "$FW_SERVICE_AUTODETECT" = ext && {
|
|
||||||
- test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv named && {
|
|
||||||
+ test "$FW_SERVICE_DNS" = no -a '!' "$START_NAMED" = no && check_srv dnsmasq && {
|
|
||||||
echo -e 'Warning: detected activated named, enabling FW_SERVICE_DNS!
|
|
||||||
You still have to allow tcp/udp port 53 on internal, dmz and/or external.'
|
|
||||||
FW_SERVICE_DNS=$FW_SERVICE_AUTODETECT
|
|
||||||
@@ -878,7 +878,7 @@
|
|
||||||
test -e /etc/resolv.conf || echo "Warning: /etc/resolv.conf not found"
|
|
||||||
# Get ports/IP bindings of NAMED/SQUID
|
|
||||||
test "$FW_SERVICE_DNS" = yes -o "$FW_SERVICE_DNS" = dmz -o "$FW_SERVICE_DNS" = ext -o "$START_NAMED" = yes && DNS_PORT=`$LSOF -i -n -P | \
|
|
||||||
- $AWK -F: '/^named .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
|
||||||
+ $AWK -F: '/^dnsmasq .* UDP / {print $2}'| $GREP -vw 53 | $SORT -un`
|
|
||||||
test "$FW_SERVICE_SQUID" = yes -o "$FW_SERVICE_SQUID" = dmz -o "$FW_SERVICE_SQUID" = ext -o "$START_SQUID" = yes && SQUID_PORT=`$LSOF -i -n -P | \
|
|
||||||
$AWK -F: '/^squid .* UDP/ {print $2}'| $SORT -un`
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
--- man/dnsmasq.8 2004-08-08 20:57:56.000000000 +0200
|
|
||||||
+++ man/dnsmasq.8 2004-08-12 00:40:01.000000000 +0200
|
|
||||||
@@ -69,7 +69,7 @@
|
|
||||||
.TP
|
|
||||||
.B \-g, --group=<groupname>
|
|
||||||
Specify the group which dnsmasq will run
|
|
||||||
-as. The defaults to "dip", if available, to facilitate access to
|
|
||||||
+as. The defaults to "dialout", if available, to facilitate access to
|
|
||||||
/etc/ppp/resolv.conf which is not normally world readable.
|
|
||||||
.TP
|
|
||||||
.B \-v, --version
|
|
||||||
--- src/config.h 2004-08-11 11:39:18.000000000 +0200
|
|
||||||
+++ src/config.h 2004-08-12 00:40:01.000000000 +0200
|
|
||||||
@@ -44,7 +44,7 @@
|
|
||||||
#endif
|
|
||||||
#define DEFLEASE 3600 /* default lease time, 1 hour */
|
|
||||||
#define CHUSER "nobody"
|
|
||||||
-#define CHGRP "dip"
|
|
||||||
+#define CHGRP "dialout"
|
|
||||||
#define DHCP_SERVER_PORT 67
|
|
||||||
#define DHCP_CLIENT_PORT 68
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# General
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Name: dnsmasq
|
|
||||||
Version: 2.33
|
|
||||||
Release: 1
|
|
||||||
Copyright: GPL
|
|
||||||
Group: Productivity/Networking/DNS/Servers
|
|
||||||
Vendor: Simon Kelley
|
|
||||||
Packager: Simon Kelley
|
|
||||||
URL: http://www.thekelleys.org.uk/dnsmasq
|
|
||||||
Provides: dns_daemon
|
|
||||||
Conflicts: bind bind8 bind9
|
|
||||||
PreReq: %fillup_prereq %insserv_prereq
|
|
||||||
Autoreqprov: on
|
|
||||||
Source0: %{name}-%{version}.tar.bz2
|
|
||||||
BuildRoot: /var/tmp/%{name}-%{version}
|
|
||||||
Summary: A lightweight caching nameserver
|
|
||||||
|
|
||||||
%description
|
|
||||||
Dnsmasq is lightweight, easy to configure DNS forwarder and DHCP server. It
|
|
||||||
is designed to provide DNS and, optionally, DHCP, to a small network. It can
|
|
||||||
serve the names of local machines which are not in the global DNS. The DHCP
|
|
||||||
server integrates with the DNS server and allows machines with DHCP-allocated
|
|
||||||
addresses to appear in the DNS with names configured either in each host or
|
|
||||||
in a central configuration file. Dnsmasq supports static and dynamic DHCP
|
|
||||||
leases and BOOTP for network booting of diskless machines.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Build
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup -q
|
|
||||||
patch -p0 <rpm/%{name}-SuSE.patch
|
|
||||||
|
|
||||||
%build
|
|
||||||
%{?suse_update_config:%{suse_update_config -f}}
|
|
||||||
make all-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Install
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%install
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
mkdir -p ${RPM_BUILD_ROOT}/etc/init.d
|
|
||||||
make install-i18n DESTDIR=$RPM_BUILD_ROOT PREFIX=/usr
|
|
||||||
install -o root -g root -m 755 rpm/rc.dnsmasq-suse $RPM_BUILD_ROOT/etc/init.d/dnsmasq
|
|
||||||
install -o root -g root -m 644 dnsmasq.conf.example $RPM_BUILD_ROOT/etc/dnsmasq.conf
|
|
||||||
strip $RPM_BUILD_ROOT/usr/sbin/dnsmasq
|
|
||||||
ln -sf ../../etc/init.d/dnsmasq $RPM_BUILD_ROOT/usr/sbin/rcdnsmasq
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Clean up
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%clean
|
|
||||||
rm -rf $RPM_BUILD_ROOT
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Post-install scriptlet
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%post
|
|
||||||
%{fillup_and_insserv dnsmasq}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Post-uninstall scriptlet
|
|
||||||
#
|
|
||||||
# The %postun script executes after the package has been removed. It is the
|
|
||||||
# last chance for a package to clean up after itself.
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%postun
|
|
||||||
%{insserv_cleanup}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# File list
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root)
|
|
||||||
%doc CHANGELOG COPYING FAQ doc.html setup.html UPGRADING_to_2.0 rpm/README.susefirewall
|
|
||||||
%doc contrib
|
|
||||||
%config /etc/init.d/dnsmasq
|
|
||||||
%config /etc/dnsmasq.conf
|
|
||||||
/usr/sbin/rcdnsmasq
|
|
||||||
/usr/sbin/dnsmasq
|
|
||||||
/usr/share/locale/*/LC_MESSAGES/*
|
|
||||||
%doc %{_mandir}/man8/dnsmasq.8.gz
|
|
||||||
%doc %{_mandir}/*/man8/dnsmasq.8.gz
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
#! /bin/sh
|
|
||||||
#
|
|
||||||
# init.d/dnsmasq
|
|
||||||
#
|
|
||||||
### BEGIN INIT INFO
|
|
||||||
# Provides: dnsmasq
|
|
||||||
# Required-Start: $network $remote_fs $syslog
|
|
||||||
# Required-Stop:
|
|
||||||
# Default-Start: 3 5
|
|
||||||
# Default-Stop:
|
|
||||||
# Description: Starts internet name service masq caching server (DNS)
|
|
||||||
### END INIT INFO
|
|
||||||
|
|
||||||
NAMED_BIN=/usr/sbin/dnsmasq
|
|
||||||
NAMED_PID=/var/run/dnsmasq.pid
|
|
||||||
NAMED_CONF=/etc/dnsmasq.conf
|
|
||||||
|
|
||||||
if [ ! -x $NAMED_BIN ] ; then
|
|
||||||
echo -n "dnsmasq not installed ! "
|
|
||||||
exit 5
|
|
||||||
fi
|
|
||||||
|
|
||||||
. /etc/rc.status
|
|
||||||
rc_reset
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
start)
|
|
||||||
echo -n "Starting name service masq caching server "
|
|
||||||
checkproc -p $NAMED_PID $NAMED_BIN
|
|
||||||
if [ $? -eq 0 ] ; then
|
|
||||||
echo -n "- Warning: dnsmasq already running ! "
|
|
||||||
else
|
|
||||||
[ -e $NAMED_PID ] && echo -n "- Warning: $NAMED_PID exists ! "
|
|
||||||
fi
|
|
||||||
startproc -p $NAMED_PID $NAMED_BIN -u nobody
|
|
||||||
rc_status -v
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
echo -n "Shutting name service masq caching server "
|
|
||||||
checkproc -p $NAMED_PID $NAMED_BIN
|
|
||||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
|
||||||
killproc -p $NAMED_PID -TERM $NAMED_BIN
|
|
||||||
rc_status -v
|
|
||||||
;;
|
|
||||||
try-restart)
|
|
||||||
$0 stop && $0 start
|
|
||||||
rc_status
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
$0 stop
|
|
||||||
$0 start
|
|
||||||
rc_status
|
|
||||||
;;
|
|
||||||
force-reload)
|
|
||||||
$0 reload
|
|
||||||
rc_status
|
|
||||||
;;
|
|
||||||
reload)
|
|
||||||
echo -n "Reloading name service masq caching server "
|
|
||||||
checkproc -p $NAMED_PID $NAMED_BIN
|
|
||||||
[ $? -ne 0 ] && echo -n "- Warning: dnsmasq not running ! "
|
|
||||||
killproc -p $NAMED_PID -HUP $NAMED_BIN
|
|
||||||
rc_status -v
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
echo -n "Checking for name service masq caching server "
|
|
||||||
checkproc -p $NAMED_PID $NAMED_BIN
|
|
||||||
rc_status -v
|
|
||||||
;;
|
|
||||||
probe)
|
|
||||||
test $NAMED_CONF -nt $NAMED_PID && echo reload
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
rc_exit
|
|
||||||
|
|
||||||
@@ -280,6 +280,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
||||||
a DHCP server */
|
a DHCP server */
|
||||||
|
memset(&ifr, 0, sizeof(ifr));
|
||||||
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
||||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||||
|
|||||||
@@ -318,6 +318,12 @@ void usage(const char* arg, FILE* stream)
|
|||||||
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
fprintf (stream, "Usage: %s %s\n", arg, usage_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fail_fatal(const char *errstr, int exitcode)
|
||||||
|
{
|
||||||
|
perror(errstr);
|
||||||
|
exit(exitcode);
|
||||||
|
}
|
||||||
|
|
||||||
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||||
{
|
{
|
||||||
struct sockaddr_in6 server_addr, client_addr;
|
struct sockaddr_in6 server_addr, client_addr;
|
||||||
@@ -343,18 +349,19 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
|||||||
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
|
client_addr.sin6_port = htons(DHCP6_CLIENT_PORT);
|
||||||
client_addr.sin6_flowinfo = 0;
|
client_addr.sin6_flowinfo = 0;
|
||||||
client_addr.sin6_scope_id =0;
|
client_addr.sin6_scope_id =0;
|
||||||
inet_pton(AF_INET6, "::", &client_addr.sin6_addr);
|
if (inet_pton(AF_INET6, "::", &client_addr.sin6_addr) <= 0)
|
||||||
bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6));
|
fail_fatal("inet_pton", 5);
|
||||||
inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr);
|
if (bind(sock, (struct sockaddr*)&client_addr, sizeof(struct sockaddr_in6)) != 0)
|
||||||
|
perror("bind"); /* continue on bind error */
|
||||||
|
if (inet_pton(AF_INET6, DHCP6_MULTICAST_ADDRESS, &server_addr.sin6_addr) <= 0)
|
||||||
|
fail_fatal("inet_pton", 5);
|
||||||
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
server_addr.sin6_port = htons(DHCP6_SERVER_PORT);
|
||||||
int16_t recv_size = 0;
|
ssize_t recv_size = 0;
|
||||||
|
int result;
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
if (sendto(sock, packet->buf, packet->len, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
|
||||||
{
|
fail_fatal("sendto failed", 4);
|
||||||
perror("sendto failed");
|
|
||||||
exit(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
recv_size = recvfrom(sock, response, sizeof(response), MSG_DONTWAIT, NULL, 0);
|
||||||
if (recv_size == -1)
|
if (recv_size == -1)
|
||||||
@@ -367,16 +374,18 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
perror("recvfrom");
|
perror("recvfrom");
|
||||||
|
result = UNSPEC_FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
int16_t result = parse_packet(response, recv_size);
|
{
|
||||||
|
result = parse_packet(response, recv_size);
|
||||||
if (result == NOT_REPLY_CODE)
|
if (result == NOT_REPLY_CODE)
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
close(sock);
|
close(sock);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+2
@@ -1,6 +1,8 @@
|
|||||||
dnsmasq (2.87-1) unstable; urgency=low
|
dnsmasq (2.87-1) unstable; urgency=low
|
||||||
|
|
||||||
* New upstream.
|
* New upstream.
|
||||||
|
* Include new NFTset support in the build.
|
||||||
|
* Fix crash on netboot with DNS server disabled. (closes: #996332)
|
||||||
|
|
||||||
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 08 Sep 2021 23:11:25 +0000
|
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 08 Sep 2021 23:11:25 +0000
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -5,7 +5,7 @@ Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
|
|||||||
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
|
||||||
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
|
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
|
||||||
liblua5.2-dev, dh-runit, debhelper-compat (= 10),
|
liblua5.2-dev, dh-runit, debhelper-compat (= 10),
|
||||||
pkg-config
|
pkg-config, libnftables-dev
|
||||||
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
|
||||||
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
|
||||||
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
|
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
|
||||||
|
|||||||
Vendored
+1
@@ -60,6 +60,7 @@ Notes on configuring dnsmasq as packaged for Debian.
|
|||||||
nodbus : omit DBus support.
|
nodbus : omit DBus support.
|
||||||
noconntrack : omit connection tracking support.
|
noconntrack : omit connection tracking support.
|
||||||
noipset : omit IPset support.
|
noipset : omit IPset support.
|
||||||
|
nonftset : omit nftset support.
|
||||||
nortc : compile alternate mode suitable for systems without an RTC.
|
nortc : compile alternate mode suitable for systems without an RTC.
|
||||||
noi18n : omit translations and internationalisation support.
|
noi18n : omit translations and internationalisation support.
|
||||||
noidn : omit international domain name support, must be
|
noidn : omit international domain name support, must be
|
||||||
|
|||||||
Vendored
+4
@@ -52,6 +52,10 @@ ifeq (,$(filter noidn, $(DEB_BUILD_OPTIONS)))
|
|||||||
DEB_COPTS += -DHAVE_LIBIDN2
|
DEB_COPTS += -DHAVE_LIBIDN2
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (,$(filter nonftset, $(DEB_BUILD_OPTIONS)))
|
||||||
|
DEB_COPTS += -DHAVE_NFTSET
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
ifeq (,$(filter noconntrack,$(DEB_BUILD_OPTIONS)))
|
||||||
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
ifeq ($(DEB_HOST_ARCH_OS),linux)
|
||||||
DEB_COPTS += -DHAVE_CONNTRACK
|
DEB_COPTS += -DHAVE_CONNTRACK
|
||||||
|
|||||||
@@ -85,6 +85,16 @@
|
|||||||
# subdomains to the vpn and search ipsets:
|
# subdomains to the vpn and search ipsets:
|
||||||
#ipset=/yahoo.com/google.com/vpn,search
|
#ipset=/yahoo.com/google.com/vpn,search
|
||||||
|
|
||||||
|
# Add the IPs of all queries to yahoo.com, google.com, and their
|
||||||
|
# subdomains to netfilters sets, which is equivalent to
|
||||||
|
# 'nft add element ip test vpn { ... }; nft add element ip test search { ... }'
|
||||||
|
#nftset=/yahoo.com/google.com/ip#test#vpn,ip#test#search
|
||||||
|
|
||||||
|
# Use netfilters sets for both IPv4 and IPv6:
|
||||||
|
# This adds all addresses in *.yahoo.com to vpn4 and vpn6 for IPv4 and IPv6 addresses.
|
||||||
|
#nftset=/yahoo.com/4#ip#test#vpn4
|
||||||
|
#nftset=/yahoo.com/6#ip#test#vpn6
|
||||||
|
|
||||||
# You can control how dnsmasq talks to a server: this forces
|
# You can control how dnsmasq talks to a server: this forces
|
||||||
# queries to 10.1.2.3 to be routed via eth1
|
# queries to 10.1.2.3 to be routed via eth1
|
||||||
# server=10.1.2.3@eth1
|
# server=10.1.2.3@eth1
|
||||||
|
|||||||
+49
-18
@@ -348,6 +348,12 @@ the public DNS and can cause problems by triggering dial-on-demand links. This f
|
|||||||
to filter such requests. The requests blocked are for records of types SOA and SRV, and type ANY where the
|
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.
|
requested name has underscores, to catch LDAP requests.
|
||||||
.TP
|
.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>
|
.B \-r, --resolv-file=<file>
|
||||||
Read the IP addresses of the upstream nameservers from <file>, instead of
|
Read the IP addresses of the upstream nameservers from <file>, instead of
|
||||||
/etc/resolv.conf. For the format of this file see
|
/etc/resolv.conf. For the format of this file see
|
||||||
@@ -505,21 +511,20 @@ source address specified but the port may be specified directly as
|
|||||||
part of the source address. Forcing queries to an interface is not
|
part of the source address. Forcing queries to an interface is not
|
||||||
implemented on all platforms supported by dnsmasq.
|
implemented on all platforms supported by dnsmasq.
|
||||||
.TP
|
.TP
|
||||||
.B --rev-server=<ip-address>/<prefix-len>[,<ipaddr>][#<port>][@<interface>][@<source-ip>[#<port>]]
|
.B --rev-server=<ip-address>[/<prefix-len>][,<ipaddr>][#<port>][@<interface>][@<source-ip>[#<port>]]
|
||||||
This is functionally the same as
|
This is functionally the same as
|
||||||
.B --server,
|
.B --server,
|
||||||
but provides some syntactic sugar to make specifying address-to-name queries easier. For example
|
but provides some syntactic sugar to make specifying address-to-name queries easier. For example
|
||||||
.B --rev-server=1.2.3.0/24,192.168.0.1
|
.B --rev-server=1.2.3.0/24,192.168.0.1
|
||||||
is exactly equivalent to
|
is exactly equivalent to
|
||||||
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
|
.B --server=/3.2.1.in-addr.arpa/192.168.0.1
|
||||||
|
Allowed prefix lengths are 1-32 (IPv4) and 1-128 (IPv6). If the prefix length is omitted, dnsmasq substitutes either 32 (IPv4) or 128 (IPv6).
|
||||||
.TP
|
.TP
|
||||||
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
|
.B \-A, --address=/<domain>[/<domain>...]/[<ipaddr>]
|
||||||
Specify an IP address to return for any host in the given domains.
|
Specify an IP address to return for any host in the given domains.
|
||||||
Queries in the domains are never forwarded and always replied to
|
Queries in the domains are never forwarded and always replied to
|
||||||
with the specified IP address which may be IPv4 or IPv6. To give
|
with the specified IP address which may be IPv4 or IPv6. To give
|
||||||
both IPv4 and IPv6 addresses for a domain, use repeated \fB--address\fP flags.
|
multiple addresses or 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.
|
|
||||||
Note that /etc/hosts and DHCP leases override this for individual
|
Note that /etc/hosts and DHCP leases override this for individual
|
||||||
names. A common use of this is to redirect the entire doubleclick.net
|
names. A common use of this is to redirect the entire doubleclick.net
|
||||||
domain to some friendly local web server to avoid banner ads. The
|
domain to some friendly local web server to avoid banner ads. The
|
||||||
@@ -549,6 +554,15 @@ These IP sets must already exist. See
|
|||||||
.BR ipset (8)
|
.BR ipset (8)
|
||||||
for more details.
|
for more details.
|
||||||
.TP
|
.TP
|
||||||
|
.B --nftset=/<domain>[/<domain>...]/[(6|4)#[<family>#]<table>#<set>[,[(6|4)#[<family>#]<table>#<set>]...]
|
||||||
|
Similar to the \fB--ipset\fP option, but accepts one or more nftables
|
||||||
|
sets to add IP addresses into.
|
||||||
|
These sets must already exist. See
|
||||||
|
.BR nft (8)
|
||||||
|
for more details. The family, table and set are passed directly to the nft. If the spec starts with 4# or 6# then
|
||||||
|
only A or AAAA records respectively are added to the set. Since an nftset can hold only IPv4 or IPv6 addresses, this
|
||||||
|
avoids errors being logged for addresses of the wrong type.
|
||||||
|
.TP
|
||||||
.B --connmark-allowlist-enable[=<mask>]
|
.B --connmark-allowlist-enable[=<mask>]
|
||||||
Enables filtering of incoming DNS queries with associated Linux connection track marks
|
Enables filtering of incoming DNS queries with associated Linux connection track marks
|
||||||
according to individual allowlists configured via a series of \fB--connmark-allowlist\fP
|
according to individual allowlists configured via a series of \fB--connmark-allowlist\fP
|
||||||
@@ -752,12 +766,13 @@ 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
|
.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.
|
will add 1.2.3.0/24 for both IPv4 and IPv6 requestors.
|
||||||
.TP
|
.TP
|
||||||
.B --umbrella[=deviceid:<deviceid>[,orgid:<orgid>]]
|
.B --umbrella[=[deviceid:<deviceid>][,orgid:<orgid>][,assetid:<id>]]
|
||||||
Embeds the requestor's IP address in DNS queries forwarded upstream.
|
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
|
included in the forwarded queries and may be able to be used in
|
||||||
filtering policies and reporting. The order of the deviceid and orgid
|
filtering policies and reporting. The order of the id
|
||||||
attributes is irrelevant, but must be separated by a comma.
|
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
|
.TP
|
||||||
.B \-c, --cache-size=<cachesize>
|
.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.
|
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.
|
||||||
@@ -1036,7 +1051,7 @@ is also included, as described in RFC-3775 section 7.3.
|
|||||||
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
|
tells dnsmasq to advertise the prefix without the on-link (aka L) bit set.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][tag:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
.B \-G, --dhcp-host=[<hwaddr>][,id:<client_id>|*][,set:<tag>][,tag:<tag>][,<ipaddr>][,<hostname>][,<lease_time>][,ignore]
|
||||||
Specify per host parameters for the DHCP server. This allows a machine
|
Specify per host parameters for the DHCP server. This allows a machine
|
||||||
with a particular hardware address to be always allocated the same
|
with a particular hardware address to be always allocated the same
|
||||||
hostname, IP address and lease time. A hostname specified like this
|
hostname, IP address and lease time. A hostname specified like this
|
||||||
@@ -1135,7 +1150,10 @@ ignore requests from unknown machines using
|
|||||||
If the host matches only a \fB--dhcp-host\fP directive which cannot
|
If the host matches only a \fB--dhcp-host\fP directive which cannot
|
||||||
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
|
be used because it specifies an address on different subnet, the tag "known-othernet" is set.
|
||||||
|
|
||||||
The tag:<tag> construct filters which dhcp-host directives are used. Tagged directives are used in preference to untagged ones.
|
The tag:<tag> construct filters which dhcp-host directives are used; more than
|
||||||
|
one can be provided, in this case the request must match all of them. Tagged
|
||||||
|
directives are used in preference to untagged ones. Note that one of <hwaddr>,
|
||||||
|
<client_id> or <hostname> still needs to be specified (can be a wildcard).
|
||||||
|
|
||||||
Ethernet addresses (but not client-ids) may have
|
Ethernet addresses (but not client-ids) may have
|
||||||
wildcard bytes, so for example
|
wildcard bytes, so for example
|
||||||
@@ -1309,7 +1327,7 @@ DHCP options. This make extra space available in the DHCP packet for
|
|||||||
options but can, rarely, confuse old or broken clients. This flag
|
options but can, rarely, confuse old or broken clients. This flag
|
||||||
forces "simple and safe" behaviour to avoid problems in such a case.
|
forces "simple and safe" behaviour to avoid problems in such a case.
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-relay=<local address>,<server address>[,<interface]
|
.B --dhcp-relay=<local address>[,<server address>][,<interface]
|
||||||
Configure dnsmasq to do DHCP relay. The local address is an address
|
Configure dnsmasq to do DHCP relay. The local address is an address
|
||||||
allocated to an interface on the host running dnsmasq. All DHCP
|
allocated to an interface on the host running dnsmasq. All DHCP
|
||||||
requests arriving on that interface will we relayed to a remote DHCP
|
requests arriving on that interface will we relayed to a remote DHCP
|
||||||
@@ -1317,10 +1335,9 @@ 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
|
address to multiple remote servers by using multiple \fB--dhcp-relay\fP
|
||||||
configs with the same local address and different server
|
configs with the same local address and different server
|
||||||
addresses. A server address must be an IP literal address, not a
|
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
|
domain name. If the server address is ommitted, the request will be
|
||||||
ALL_SERVERS multicast address, ff05::1:3. In this case the interface
|
forwarded by broadcast (IPv4) or multicast (IPv6). In this case the interface
|
||||||
must be given, not be wildcard, and is used to direct the multicast to the
|
must be given and not be wildcard.
|
||||||
correct interface to reach the DHCP server.
|
|
||||||
|
|
||||||
Access control for DHCP clients has the same rules as for the DHCP
|
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
|
server, see \fB--interface\fP, \fB--except-interface\fP, etc. The optional
|
||||||
@@ -1340,6 +1357,11 @@ supported: the relay function will take precedence.
|
|||||||
|
|
||||||
Both DHCPv4 and DHCPv6 relay is supported. It's not possible to relay
|
Both DHCPv4 and DHCPv6 relay is supported. It's not possible to relay
|
||||||
DHCPv4 to a DHCPv6 server or vice-versa.
|
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
|
.TP
|
||||||
.B \-U, --dhcp-vendorclass=set:<tag>,[enterprise:<IANA-enterprise number>,]<vendor-class>
|
.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
|
Map from a vendor-class string to a tag. Most DHCP clients provide a
|
||||||
@@ -1750,15 +1772,25 @@ receives a HUP signal, the script will be invoked for existing leases
|
|||||||
with an "old" event.
|
with an "old" event.
|
||||||
|
|
||||||
|
|
||||||
There are four further actions which may appear as the first argument
|
There are five 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
|
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
|
scripts should be written to ignore unknown actions. "init" is
|
||||||
described below in
|
described below in
|
||||||
.B --leasefile-ro
|
.B --leasefile-ro
|
||||||
|
|
||||||
The "tftp" action is invoked when a TFTP file transfer completes: the
|
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
|
arguments are the file size in bytes, the address to which the file
|
||||||
was sent, and the complete pathname of 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
|
The "arp-add" and "arp-del" actions are only called if enabled with
|
||||||
.B --script-arp
|
.B --script-arp
|
||||||
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
|
They are are supplied with a MAC address and IP address as arguments. "arp-add" indicates
|
||||||
@@ -1923,7 +1955,6 @@ additional flag "local" may be supplied which has the effect of adding
|
|||||||
is identical to
|
is identical to
|
||||||
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
.B --domain=thekelleys.org.uk,192.168.0.0/24
|
||||||
.B --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
.B --local=/thekelleys.org.uk/ --local=/0.168.192.in-addr.arpa/
|
||||||
The network size must be 8, 16 or 24 for this to be legal.
|
|
||||||
.TP
|
.TP
|
||||||
.B --dhcp-fqdn
|
.B --dhcp-fqdn
|
||||||
In the default mode, dnsmasq inserts the unqualified names of
|
In the default mode, dnsmasq inserts the unqualified names of
|
||||||
|
|||||||
@@ -2145,8 +2145,8 @@ msgstr "nicht unterstützte Anfrage von %s"
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "Datei %s nicht gefunden"
|
msgstr "Datei %s nicht gefunden für %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
@@ -2213,8 +2213,8 @@ msgstr "pedido no-soportado desde %s"
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "archivo %s no encontrado"
|
msgstr "archivo %s no encontrado por %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
@@ -2114,7 +2114,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
|
|||||||
@@ -2197,8 +2197,8 @@ msgstr "requ
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "fichier %s non trouvé"
|
msgstr "fichier %s non trouvé pour %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
@@ -2460,8 +2460,8 @@ msgstr ""
|
|||||||
# OK
|
# OK
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "lease tak ditemukan"
|
msgstr "file %s tidak ditemukan untuk %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
@@ -2114,7 +2114,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
|
|||||||
@@ -2194,8 +2194,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "leie ikke funnet"
|
msgstr "fil %s ikke funnet for %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
@@ -2149,8 +2149,8 @@ msgstr "nieobsługiwane żądanie od komputera %s"
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "plik %s nie został znaleziony"
|
msgstr "plik %s nie został znaleziony dla %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
+1
-1
@@ -2114,7 +2114,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
|
|||||||
@@ -2195,8 +2195,8 @@ msgstr ""
|
|||||||
|
|
||||||
#: tftp.c:512
|
#: tftp.c:512
|
||||||
#, fuzzy, c-format
|
#, fuzzy, c-format
|
||||||
msgid "file %s not found"
|
msgid "file %s not found for %s"
|
||||||
msgstr "împrumutul nu a fost găsit"
|
msgstr "fișier %s nu a fost găsit pentru %s"
|
||||||
|
|
||||||
#: tftp.c:602
|
#: tftp.c:602
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|||||||
+2
-8
@@ -417,7 +417,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
if (!found && is_name_synthetic(flag, name, &addr) )
|
if (!found && is_name_synthetic(flag, name, &addr) )
|
||||||
{
|
{
|
||||||
found = 1;
|
|
||||||
nxdomain = 0;
|
nxdomain = 0;
|
||||||
|
|
||||||
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
log_query(F_FORWARD | F_CONFIG | flag, name, &addr, NULL, 0);
|
||||||
@@ -433,7 +432,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (qtype == T_SOA)
|
if (qtype == T_SOA)
|
||||||
{
|
{
|
||||||
auth = soa = 1; /* inhibits auth section */
|
auth = soa = 1; /* inhibits auth section */
|
||||||
found = 1;
|
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<SOA>", 0);
|
||||||
}
|
}
|
||||||
else if (qtype == T_AXFR)
|
else if (qtype == T_AXFR)
|
||||||
@@ -469,7 +467,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
soa = 1; /* inhibits auth section */
|
soa = 1; /* inhibits auth section */
|
||||||
ns = 1; /* ensure we include NS records! */
|
ns = 1; /* ensure we include NS records! */
|
||||||
axfr = 1;
|
axfr = 1;
|
||||||
found = 1;
|
|
||||||
axfroffset = nameoffset;
|
axfroffset = nameoffset;
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<AXFR>", 0);
|
||||||
}
|
}
|
||||||
@@ -477,7 +474,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
{
|
{
|
||||||
auth = 1;
|
auth = 1;
|
||||||
ns = 1; /* inhibits auth section */
|
ns = 1; /* inhibits auth section */
|
||||||
found = 1;
|
|
||||||
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
|
log_query(F_RRNAME | F_AUTH, zone->domain, NULL, "<NS>", 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -498,7 +494,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
*cut = '.'; /* restore domain part */
|
*cut = '.'; /* restore domain part */
|
||||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
||||||
*cut = 0; /* remove domain part */
|
*cut = 0; /* remove domain part */
|
||||||
found = 1;
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
qtype == T_A ? "4" : "6", &crecp->addr))
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
@@ -519,7 +514,6 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
|
if ((crecp->flags & flag) && (local_query || filter_zone(zone, flag, &(crecp->addr))))
|
||||||
{
|
{
|
||||||
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
log_query(crecp->flags, name, &crecp->addr, record_source(crecp->uid), 0);
|
||||||
found = 1;
|
|
||||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
daemon->auth_ttl, NULL, qtype, C_IN,
|
daemon->auth_ttl, NULL, qtype, C_IN,
|
||||||
qtype == T_A ? "4" : "6", &crecp->addr))
|
qtype == T_A ? "4" : "6", &crecp->addr))
|
||||||
@@ -614,7 +608,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
if (subnet->prefixlen >= 16 )
|
if (subnet->prefixlen >= 16 )
|
||||||
p += sprintf(p, "%u.", a & 0xff);
|
p += sprintf(p, "%u.", a & 0xff);
|
||||||
a = a >> 8;
|
a = a >> 8;
|
||||||
p += sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
sprintf(p, "%u.in-addr.arpa", a & 0xff);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -627,7 +621,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
|
int dig = ((unsigned char *)&subnet->addr.addr6)[i>>3];
|
||||||
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
p += sprintf(p, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
||||||
}
|
}
|
||||||
p += sprintf(p, "ip6.arpa");
|
sprintf(p, "ip6.arpa");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -52,7 +52,7 @@ void blockdata_init(void)
|
|||||||
|
|
||||||
void blockdata_report(void)
|
void blockdata_report(void)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
|
my_syslog(LOG_INFO, _("pool memory in use %zu, max %zu, allocated %zu"),
|
||||||
blockdata_count * sizeof(struct blockdata),
|
blockdata_count * sizeof(struct blockdata),
|
||||||
blockdata_hwm * sizeof(struct blockdata),
|
blockdata_hwm * sizeof(struct blockdata),
|
||||||
blockdata_alloced * sizeof(struct blockdata));
|
blockdata_alloced * sizeof(struct blockdata));
|
||||||
|
|||||||
+7
-4
@@ -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))
|
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 */
|
/* 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))))
|
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
||||||
{
|
{
|
||||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||||
@@ -483,7 +483,7 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
|
|||||||
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
|
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
|
||||||
(flags & crecp->flags & F_REVERSE) &&
|
(flags & crecp->flags & F_REVERSE) &&
|
||||||
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
|
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
|
||||||
memcmp(&crecp->addr, addr, addrlen) == 0)
|
addr && memcmp(&crecp->addr, addr, addrlen) == 0)
|
||||||
{
|
{
|
||||||
*up = crecp->hash_next;
|
*up = crecp->hash_next;
|
||||||
cache_unlink(crecp);
|
cache_unlink(crecp);
|
||||||
@@ -1399,6 +1399,8 @@ struct in_addr a_record_from_hosts(char *name, time_t now)
|
|||||||
struct crec *crecp = NULL;
|
struct crec *crecp = NULL;
|
||||||
struct in_addr ret;
|
struct in_addr ret;
|
||||||
|
|
||||||
|
/* If no DNS service, cache not initialised. */
|
||||||
|
if (daemon->port != 0)
|
||||||
while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
|
while ((crecp = cache_find_by_name(crecp, name, now, F_IPV4)))
|
||||||
if (crecp->flags & F_HOSTS)
|
if (crecp->flags & F_HOSTS)
|
||||||
return crecp->addr.addr4;
|
return crecp->addr.addr4;
|
||||||
@@ -1597,6 +1599,7 @@ static void make_non_terminals(struct crec *source)
|
|||||||
if (crecp)
|
if (crecp)
|
||||||
{
|
{
|
||||||
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE);
|
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_SRV | F_DNSKEY | F_DS | F_REVERSE);
|
||||||
|
if (!(crecp->flags & F_IMMORTAL))
|
||||||
crecp->ttd = source->ttd;
|
crecp->ttd = source->ttd;
|
||||||
crecp->name.namep = name;
|
crecp->name.namep = name;
|
||||||
|
|
||||||
@@ -2059,7 +2062,7 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||||||
}
|
}
|
||||||
else if (flags & F_IPSET)
|
else if (flags & F_IPSET)
|
||||||
{
|
{
|
||||||
source = "ipset add";
|
source = type ? "ipset add" : "nftset add";
|
||||||
dest = name;
|
dest = name;
|
||||||
name = arg;
|
name = arg;
|
||||||
verb = daemon->addrbuff;
|
verb = daemon->addrbuff;
|
||||||
@@ -2067,7 +2070,7 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg,
|
|||||||
else
|
else
|
||||||
source = "cached";
|
source = "cached";
|
||||||
|
|
||||||
if (strlen(name) == 0)
|
if (name && !name[0])
|
||||||
name = ".";
|
name = ".";
|
||||||
|
|
||||||
if (option_bool(OPT_EXTRALOG))
|
if (option_bool(OPT_EXTRALOG))
|
||||||
|
|||||||
+9
-1
@@ -115,6 +115,10 @@ HAVE_IPSET
|
|||||||
define this to include the ability to selectively add resolved ip addresses
|
define this to include the ability to selectively add resolved ip addresses
|
||||||
to given ipsets.
|
to given ipsets.
|
||||||
|
|
||||||
|
HAVE_NFTSET
|
||||||
|
define this to include the ability to selectively add resolved ip addresses
|
||||||
|
to given nftables sets.
|
||||||
|
|
||||||
HAVE_AUTH
|
HAVE_AUTH
|
||||||
define this to include the facility to act as an authoritative DNS
|
define this to include the facility to act as an authoritative DNS
|
||||||
server for one or more zones.
|
server for one or more zones.
|
||||||
@@ -192,7 +196,7 @@ RESOLVFILE
|
|||||||
/* #define HAVE_CONNTRACK */
|
/* #define HAVE_CONNTRACK */
|
||||||
/* #define HAVE_CRYPTOHASH */
|
/* #define HAVE_CRYPTOHASH */
|
||||||
/* #define HAVE_DNSSEC */
|
/* #define HAVE_DNSSEC */
|
||||||
|
/* #define HAVE_NFTSET */
|
||||||
|
|
||||||
/* Default locations for important system files. */
|
/* Default locations for important system files. */
|
||||||
|
|
||||||
@@ -420,6 +424,10 @@ static char *compile_opts =
|
|||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
"ipset "
|
"ipset "
|
||||||
|
#ifndef HAVE_NFTSET
|
||||||
|
"no-"
|
||||||
|
#endif
|
||||||
|
"nftset "
|
||||||
#ifndef HAVE_AUTH
|
#ifndef HAVE_AUTH
|
||||||
"no-"
|
"no-"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+15
-6
@@ -114,7 +114,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|||||||
w->next = daemon->watches;
|
w->next = daemon->watches;
|
||||||
daemon->watches = w;
|
daemon->watches = w;
|
||||||
|
|
||||||
w = data; /* no warning */
|
(void)data; /* no warning */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,16 +134,20 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|||||||
up = &(w->next);
|
up = &(w->next);
|
||||||
}
|
}
|
||||||
|
|
||||||
w = data; /* no warning */
|
(void)data; /* no warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dbus_read_servers(DBusMessage *message)
|
static DBusMessage* dbus_read_servers(DBusMessage *message)
|
||||||
{
|
{
|
||||||
DBusMessageIter iter;
|
DBusMessageIter iter;
|
||||||
union mysockaddr addr, source_addr;
|
union mysockaddr addr, source_addr;
|
||||||
char *domain;
|
char *domain;
|
||||||
|
|
||||||
dbus_message_iter_init(message, &iter);
|
if (!dbus_message_iter_init(message, &iter))
|
||||||
|
{
|
||||||
|
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Failed to initialize dbus message iter");
|
||||||
|
}
|
||||||
|
|
||||||
mark_servers(SERV_FROM_DBUS);
|
mark_servers(SERV_FROM_DBUS);
|
||||||
|
|
||||||
@@ -222,6 +226,7 @@ static void dbus_read_servers(DBusMessage *message)
|
|||||||
|
|
||||||
/* unlink and free anything still marked. */
|
/* unlink and free anything still marked. */
|
||||||
cleanup_servers();
|
cleanup_servers();
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
@@ -545,6 +550,10 @@ static DBusMessage *dbus_add_lease(DBusMessage* message)
|
|||||||
"Invalid IP address '%s'", ipaddr);
|
"Invalid IP address '%s'", ipaddr);
|
||||||
|
|
||||||
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
hw_len = parse_hex((char*)hwaddr, dhcp_chaddr, DHCP_CHADDR_MAX, NULL, &hw_type);
|
||||||
|
if (hw_len < 0)
|
||||||
|
return dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid HW address '%s'", hwaddr);
|
||||||
|
|
||||||
if (hw_type == 0 && hw_len != 0)
|
if (hw_type == 0 && hw_len != 0)
|
||||||
hw_type = ARPHRD_ETHER;
|
hw_type = ARPHRD_ETHER;
|
||||||
|
|
||||||
@@ -668,7 +677,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
#endif
|
#endif
|
||||||
else if (strcmp(method, "SetServers") == 0)
|
else if (strcmp(method, "SetServers") == 0)
|
||||||
{
|
{
|
||||||
dbus_read_servers(message);
|
reply = dbus_read_servers(message);
|
||||||
new_servers = 1;
|
new_servers = 1;
|
||||||
}
|
}
|
||||||
else if (strcmp(method, "SetServersEx") == 0)
|
else if (strcmp(method, "SetServersEx") == 0)
|
||||||
@@ -719,7 +728,7 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
|||||||
if (clear_cache)
|
if (clear_cache)
|
||||||
clear_cache_and_reload(dnsmasq_time());
|
clear_cache_and_reload(dnsmasq_time());
|
||||||
|
|
||||||
method = user_data; /* no warning */
|
(void)user_data; /* no warning */
|
||||||
|
|
||||||
/* If no reply or no error, return nothing */
|
/* If no reply or no error, return nothing */
|
||||||
if (!reply)
|
if (!reply)
|
||||||
|
|||||||
+17
-1
@@ -88,7 +88,7 @@ int match_netid_wild(struct dhcp_netid *check, struct dhcp_netid *pool)
|
|||||||
for (; check; check = check->next)
|
for (; check; check = check->next)
|
||||||
{
|
{
|
||||||
const int check_len = strlen(check->net);
|
const int check_len = strlen(check->net);
|
||||||
const int is_wc = (check->net[check_len - 1] == '*');
|
const int is_wc = (check_len > 0 && check->net[check_len - 1] == '*');
|
||||||
|
|
||||||
/* '#' for not is for backwards compat. */
|
/* '#' for not is for backwards compat. */
|
||||||
if (check->net[0] != '!' && check->net[0] != '#')
|
if (check->net[0] != '!' && check->net[0] != '#')
|
||||||
@@ -985,11 +985,27 @@ void log_context(int family, struct dhcp_context *context)
|
|||||||
|
|
||||||
void log_relay(int family, struct dhcp_relay *relay)
|
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->local, daemon->addrbuff, ADDRSTRLEN);
|
||||||
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
inet_ntop(family, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||||
|
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (relay->interface)
|
if (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);
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s via %s"), daemon->addrbuff, daemon->namebuff, relay->interface);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay from %s to %s"), daemon->addrbuff, daemon->namebuff);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-1
@@ -1096,13 +1096,34 @@ static int relay_upstream4(struct dhcp_relay *relay, struct dhcp_packet *mess,
|
|||||||
to.in.sin_addr = relay->server.addr4;
|
to.in.sin_addr = relay->server.addr4;
|
||||||
to.in.sin_port = htons(daemon->dhcp_server_port);
|
to.in.sin_port = htons(daemon->dhcp_server_port);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
to.in.sin_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
|
||||||
|
}
|
||||||
|
|
||||||
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
send_from(daemon->dhcpfd, 0, (char *)mess, sz, &to, &from, 0);
|
||||||
|
|
||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
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);
|
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);
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->dhcp_buff2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save this for replies */
|
/* Save this for replies */
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
#define OPTION6_RECONF_ACCEPT 20
|
#define OPTION6_RECONF_ACCEPT 20
|
||||||
#define OPTION6_DNS_SERVER 23
|
#define OPTION6_DNS_SERVER 23
|
||||||
#define OPTION6_DOMAIN_SEARCH 24
|
#define OPTION6_DOMAIN_SEARCH 24
|
||||||
|
#define OPTION6_IA_PD 25
|
||||||
|
#define OPTION6_IAPREFIX 26
|
||||||
#define OPTION6_REFRESH_TIME 32
|
#define OPTION6_REFRESH_TIME 32
|
||||||
#define OPTION6_REMOTE_ID 37
|
#define OPTION6_REMOTE_ID 37
|
||||||
#define OPTION6_SUBSCRIBER_ID 38
|
#define OPTION6_SUBSCRIBER_ID 38
|
||||||
|
|||||||
+2
-3
@@ -135,9 +135,8 @@ void dhcp6_packet(time_t now)
|
|||||||
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
if (!indextoname(daemon->dhcp6fd, if_index, ifr.ifr_name))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((port = relay_reply6(&from, sz, ifr.ifr_name)) != 0)
|
if (relay_reply6(&from, sz, ifr.ifr_name))
|
||||||
{
|
{
|
||||||
from.sin6_port = htons(port);
|
|
||||||
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
|
||||||
save_counter(-1), 0, (struct sockaddr *)&from,
|
save_counter(-1), 0, (struct sockaddr *)&from,
|
||||||
sizeof(from))));
|
sizeof(from))));
|
||||||
@@ -292,7 +291,7 @@ void get_client_mac(struct in6_addr *client, int iface, unsigned char *mac, unsi
|
|||||||
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
|
if ((maclen = find_mac(&addr, mac, 0, now)) != 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr));
|
while(retry_send(sendto(daemon->icmp6fd, &neigh, sizeof(neigh), 0, &addr.sa, sizeof(addr))));
|
||||||
|
|
||||||
ts.tv_sec = 0;
|
ts.tv_sec = 0;
|
||||||
ts.tv_nsec = 100000000; /* 100ms */
|
ts.tv_nsec = 100000000; /* 100ms */
|
||||||
|
|||||||
+39
-6
@@ -17,8 +17,13 @@
|
|||||||
/* Declare static char *compiler_opts in config.h */
|
/* Declare static char *compiler_opts in config.h */
|
||||||
#define DNSMASQ_COMPILE_OPTS
|
#define DNSMASQ_COMPILE_OPTS
|
||||||
|
|
||||||
|
/* dnsmasq.h has to be included first as it sources config.h */
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||||
|
#include <locale.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
struct daemon *daemon;
|
struct daemon *daemon;
|
||||||
|
|
||||||
static volatile pid_t pid = 0;
|
static volatile pid_t pid = 0;
|
||||||
@@ -34,7 +39,6 @@ static void poll_resolv(int force, int do_reload, time_t now);
|
|||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
int bind_fallback = 0;
|
|
||||||
time_t now;
|
time_t now;
|
||||||
struct sigaction sigact;
|
struct sigaction sigact;
|
||||||
struct iname *if_tmp;
|
struct iname *if_tmp;
|
||||||
@@ -59,6 +63,8 @@ int main (int argc, char **argv)
|
|||||||
int did_bind = 0;
|
int did_bind = 0;
|
||||||
struct server *serv;
|
struct server *serv;
|
||||||
char *netlink_warn;
|
char *netlink_warn;
|
||||||
|
#else
|
||||||
|
int bind_fallback = 0;
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
|
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
|
||||||
struct dhcp_context *context;
|
struct dhcp_context *context;
|
||||||
@@ -68,8 +74,10 @@ int main (int argc, char **argv)
|
|||||||
int tftp_prefix_missing = 0;
|
int tftp_prefix_missing = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOCALEDIR
|
#if defined(HAVE_IDN) || defined(HAVE_LIBIDN2) || defined(LOCALEDIR)
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
#endif
|
||||||
|
#ifdef LOCALEDIR
|
||||||
bindtextdomain("dnsmasq", LOCALEDIR);
|
bindtextdomain("dnsmasq", LOCALEDIR);
|
||||||
textdomain("dnsmasq");
|
textdomain("dnsmasq");
|
||||||
#endif
|
#endif
|
||||||
@@ -345,6 +353,16 @@ int main (int argc, char **argv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_NFTSET
|
||||||
|
if (daemon->nftsets)
|
||||||
|
{
|
||||||
|
nftset_init();
|
||||||
|
# ifdef HAVE_LINUX_NETWORK
|
||||||
|
need_cap_net_admin = 1;
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_LINUX_NETWORK)
|
#if defined(HAVE_LINUX_NETWORK)
|
||||||
netlink_warn = netlink_init();
|
netlink_warn = netlink_init();
|
||||||
#elif defined(HAVE_BSD_NETWORK)
|
#elif defined(HAVE_BSD_NETWORK)
|
||||||
@@ -377,7 +395,7 @@ int main (int argc, char **argv)
|
|||||||
bindtodevice(bound_device, daemon->dhcpfd);
|
bindtodevice(bound_device, daemon->dhcpfd);
|
||||||
did_bind = 1;
|
did_bind = 1;
|
||||||
}
|
}
|
||||||
if (daemon->enable_pxe && bound_device)
|
if (daemon->enable_pxe && bound_device && daemon->pxefd != -1)
|
||||||
{
|
{
|
||||||
bindtodevice(bound_device, daemon->pxefd);
|
bindtodevice(bound_device, daemon->pxefd);
|
||||||
did_bind = 1;
|
did_bind = 1;
|
||||||
@@ -716,7 +734,11 @@ int main (int argc, char **argv)
|
|||||||
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
/* if we are to run scripts, we need to fork a helper before dropping root. */
|
||||||
daemon->helperfd = -1;
|
daemon->helperfd = -1;
|
||||||
#ifdef HAVE_SCRIPT
|
#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->lease_change_command || daemon->luascript))
|
||||||
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
|
||||||
#endif
|
#endif
|
||||||
@@ -920,8 +942,10 @@ int main (int argc, char **argv)
|
|||||||
my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
|
my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
|
||||||
daemon->log_file, strerror(log_err));
|
daemon->log_file, strerror(log_err));
|
||||||
|
|
||||||
|
#ifndef HAVE_LINUX_NETWORK
|
||||||
if (bind_fallback)
|
if (bind_fallback)
|
||||||
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
|
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
|
||||||
|
#endif
|
||||||
|
|
||||||
if (option_bool(OPT_NOWILD))
|
if (option_bool(OPT_NOWILD))
|
||||||
warn_bound_listeners();
|
warn_bound_listeners();
|
||||||
@@ -1119,6 +1143,10 @@ int main (int argc, char **argv)
|
|||||||
while (helper_buf_empty() && do_tftp_script_run());
|
while (helper_buf_empty() && do_tftp_script_run());
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# ifdef HAVE_DHCP6
|
||||||
|
while (helper_buf_empty() && do_snoop_script_run());
|
||||||
|
# endif
|
||||||
|
|
||||||
if (!helper_buf_empty())
|
if (!helper_buf_empty())
|
||||||
poll_listen(daemon->helperfd, POLLOUT);
|
poll_listen(daemon->helperfd, POLLOUT);
|
||||||
#else
|
#else
|
||||||
@@ -1575,7 +1603,7 @@ static void async_event(int pipe, time_t now)
|
|||||||
{
|
{
|
||||||
/* block in writes until all done */
|
/* block in writes until all done */
|
||||||
if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
|
if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
|
||||||
fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
|
while(retry_send(fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK)));
|
||||||
do {
|
do {
|
||||||
helper_write();
|
helper_write();
|
||||||
} while (!helper_buf_empty() || do_script_run(now));
|
} while (!helper_buf_empty() || do_script_run(now));
|
||||||
@@ -1669,6 +1697,11 @@ static void poll_resolv(int force, int do_reload, time_t now)
|
|||||||
}
|
}
|
||||||
else
|
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;
|
latest->mtime = 0;
|
||||||
if (!warned)
|
if (!warned)
|
||||||
{
|
{
|
||||||
@@ -1984,7 +2017,7 @@ static void check_dns_listeners(time_t now)
|
|||||||
attribute from the listening socket.
|
attribute from the listening socket.
|
||||||
Reset that here. */
|
Reset that here. */
|
||||||
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
|
||||||
fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
|
while(retry_send(fcntl(confd, F_SETFL, flags & ~O_NONBLOCK)));
|
||||||
|
|
||||||
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
|
||||||
|
|
||||||
|
|||||||
+61
-20
@@ -275,7 +275,9 @@ struct event_desc {
|
|||||||
#define OPT_UMBRELLA_DEVID 64
|
#define OPT_UMBRELLA_DEVID 64
|
||||||
#define OPT_CMARK_ALST_EN 65
|
#define OPT_CMARK_ALST_EN 65
|
||||||
#define OPT_QUIET_TFTP 66
|
#define OPT_QUIET_TFTP 66
|
||||||
#define OPT_LAST 67
|
#define OPT_FILTER_A 67
|
||||||
|
#define OPT_FILTER_AAAA 68
|
||||||
|
#define OPT_LAST 69
|
||||||
|
|
||||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||||
@@ -530,18 +532,18 @@ union mysockaddr {
|
|||||||
|
|
||||||
|
|
||||||
/* The actual values here matter, since we sort on them to get records in the order
|
/* The actual values here matter, since we sort on them to get records in the order
|
||||||
IPv6 addr, IPv4 addr, all zero return, no-data return, send upstream. */
|
IPv6 addr, IPv4 addr, all zero return, resolvconf servers, upstream server, no-data return */
|
||||||
#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next three flags */
|
#define SERV_LITERAL_ADDRESS 1 /* addr is the answer, or NoDATA is the answer, depending on the next four flags */
|
||||||
#define SERV_ALL_ZEROS 2 /* return all zeros for A and AAAA */
|
#define SERV_USE_RESOLV 2 /* forward this domain in the normal way */
|
||||||
#define SERV_4ADDR 4 /* addr is IPv4 */
|
#define SERV_ALL_ZEROS 4 /* return all zeros for A and AAAA */
|
||||||
#define SERV_6ADDR 8 /* addr is IPv6 */
|
#define SERV_4ADDR 8 /* addr is IPv4 */
|
||||||
#define SERV_HAS_SOURCE 16 /* source address defined */
|
#define SERV_6ADDR 16 /* addr is IPv6 */
|
||||||
#define SERV_FOR_NODOTS 32 /* server for names with no domain part only */
|
#define SERV_HAS_SOURCE 32 /* source address defined */
|
||||||
#define SERV_WARNED_RECURSIVE 64 /* avoid warning spam */
|
#define SERV_FOR_NODOTS 64 /* server for names with no domain part only */
|
||||||
#define SERV_FROM_DBUS 128 /* 1 if source is DBus */
|
#define SERV_WARNED_RECURSIVE 128 /* avoid warning spam */
|
||||||
#define SERV_MARK 256 /* for mark-and-delete and log code */
|
#define SERV_FROM_DBUS 256 /* 1 if source is DBus */
|
||||||
#define SERV_WILDCARD 512 /* domain has leading '*' */
|
#define SERV_MARK 512 /* for mark-and-delete and log code */
|
||||||
#define SERV_USE_RESOLV 1024 /* forward this domain in the normal way */
|
#define SERV_WILDCARD 1024 /* domain has leading '*' */
|
||||||
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
#define SERV_FROM_RESOLV 2048 /* 1 for servers from resolv, 0 for command line. */
|
||||||
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
#define SERV_FROM_FILE 4096 /* read from --servers-file */
|
||||||
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
#define SERV_LOOP 8192 /* server causes forwarding loop */
|
||||||
@@ -609,6 +611,11 @@ struct serv_local {
|
|||||||
struct server *next;
|
struct server *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rebind_domain {
|
||||||
|
char *domain;
|
||||||
|
struct rebind_domain *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct ipsets {
|
struct ipsets {
|
||||||
char **sets;
|
char **sets;
|
||||||
char *domain;
|
char *domain;
|
||||||
@@ -771,6 +778,7 @@ struct frec {
|
|||||||
#define ACTION_TFTP 5
|
#define ACTION_TFTP 5
|
||||||
#define ACTION_ARP 6
|
#define ACTION_ARP 6
|
||||||
#define ACTION_ARP_DEL 7
|
#define ACTION_ARP_DEL 7
|
||||||
|
#define ACTION_RELAY_SNOOP 8
|
||||||
|
|
||||||
#define LEASE_NEW 1 /* newly created */
|
#define LEASE_NEW 1 /* newly created */
|
||||||
#define LEASE_CHANGED 2 /* modified */
|
#define LEASE_CHANGED 2 /* modified */
|
||||||
@@ -1069,6 +1077,13 @@ struct dhcp_relay {
|
|||||||
union all_addr local, server;
|
union all_addr local, server;
|
||||||
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
|
char *interface; /* Allowable interface for replies from server, and dest for IPv6 multicast */
|
||||||
int iface_index; /* working - interface in which requests arrived, for return */
|
int iface_index; /* working - interface in which requests arrived, for return */
|
||||||
|
#ifdef HAVE_SCRIPT
|
||||||
|
struct snoop_record {
|
||||||
|
struct in6_addr client, prefix;
|
||||||
|
int prefix_len;
|
||||||
|
struct snoop_record *next;
|
||||||
|
} *snoop_records;
|
||||||
|
#endif
|
||||||
struct dhcp_relay *current, *next;
|
struct dhcp_relay *current, *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1105,10 +1120,11 @@ extern struct daemon {
|
|||||||
char *lease_change_command;
|
char *lease_change_command;
|
||||||
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
struct iname *if_names, *if_addrs, *if_except, *dhcp_except, *auth_peers, *tftp_interfaces;
|
||||||
struct bogus_addr *bogus_addr, *ignore_addr;
|
struct bogus_addr *bogus_addr, *ignore_addr;
|
||||||
struct server *servers, *local_domains, **serverarray, *no_rebind;
|
struct server *servers, *servers_tail, *local_domains, **serverarray;
|
||||||
|
struct rebind_domain *no_rebind;
|
||||||
int server_has_wildcard;
|
int server_has_wildcard;
|
||||||
int serverarraysz, serverarrayhwm;
|
int serverarraysz, serverarrayhwm;
|
||||||
struct ipsets *ipsets;
|
struct ipsets *ipsets, *nftsets;
|
||||||
u32 allowlist_mask;
|
u32 allowlist_mask;
|
||||||
struct allowlist *allowlists;
|
struct allowlist *allowlists;
|
||||||
int log_fac; /* log facility */
|
int log_fac; /* log facility */
|
||||||
@@ -1167,9 +1183,12 @@ extern struct daemon {
|
|||||||
char *packet; /* packet buffer */
|
char *packet; /* packet buffer */
|
||||||
int packet_buff_sz; /* size of above */
|
int packet_buff_sz; /* size of above */
|
||||||
char *namebuff; /* MAXDNAME size buffer */
|
char *namebuff; /* MAXDNAME size buffer */
|
||||||
|
#if (defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)) || defined(HAVE_DNSSEC)
|
||||||
|
/* CONNTRACK UBUS code uses this buffer, as well as DNSSEC code. */
|
||||||
|
char *workspacename;
|
||||||
|
#endif
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
char *keyname; /* MAXDNAME size buffer */
|
char *keyname; /* MAXDNAME size buffer */
|
||||||
char *workspacename; /* ditto */
|
|
||||||
unsigned long *rr_status; /* ceiling in TTL from DNSSEC or zero for insecure */
|
unsigned long *rr_status; /* ceiling in TTL from DNSSEC or zero for insecure */
|
||||||
int rr_status_sz;
|
int rr_status_sz;
|
||||||
int dnssec_no_time_check;
|
int dnssec_no_time_check;
|
||||||
@@ -1216,13 +1235,18 @@ extern struct daemon {
|
|||||||
unsigned char *duid;
|
unsigned char *duid;
|
||||||
struct iovec outpacket;
|
struct iovec outpacket;
|
||||||
int dhcp6fd, icmp6fd;
|
int dhcp6fd, icmp6fd;
|
||||||
|
# ifdef HAVE_SCRIPT
|
||||||
|
struct snoop_record *free_snoops;
|
||||||
# endif
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* DBus stuff */
|
/* DBus stuff */
|
||||||
/* void * here to avoid depending on dbus headers outside dbus.c */
|
/* void * here to avoid depending on dbus headers outside dbus.c */
|
||||||
void *dbus;
|
void *dbus;
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
struct watch *watches;
|
struct watch *watches;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* UBus stuff */
|
/* UBus stuff */
|
||||||
#ifdef HAVE_UBUS
|
#ifdef HAVE_UBUS
|
||||||
/* void * here to avoid depending on ubus headers outside ubus.c */
|
/* void * here to avoid depending on ubus headers outside ubus.c */
|
||||||
@@ -1297,8 +1321,8 @@ unsigned int extract_request(struct dns_header *header, size_t qlen,
|
|||||||
char *name, unsigned short *typep);
|
char *name, unsigned short *typep);
|
||||||
void setup_reply(struct dns_header *header, unsigned int flags, int ede);
|
void setup_reply(struct dns_header *header, unsigned int flags, int ede);
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name,
|
||||||
time_t now, char **ipsets, int is_sign, int check_rebind,
|
time_t now, struct ipsets *ipsets, struct ipsets *nftsets, int is_sign,
|
||||||
int no_cache_dnssec, int secure, int *doctored);
|
int check_rebind, int no_cache_dnssec, int secure, int *doctored);
|
||||||
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
#if defined(HAVE_CONNTRACK) && defined(HAVE_UBUS)
|
||||||
void report_addresses(struct dns_header *header, size_t len, u32 mark);
|
void report_addresses(struct dns_header *header, size_t len, u32 mark);
|
||||||
#endif
|
#endif
|
||||||
@@ -1365,6 +1389,7 @@ void safe_pipe(int *fd, int read_noblock);
|
|||||||
void *whine_malloc(size_t size);
|
void *whine_malloc(size_t size);
|
||||||
int sa_len(union mysockaddr *addr);
|
int sa_len(union mysockaddr *addr);
|
||||||
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
|
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_isequal(const char *a, const char *b);
|
||||||
int hostname_issubdomain(char *a, char *b);
|
int hostname_issubdomain(char *a, char *b);
|
||||||
time_t dnsmasq_time(void);
|
time_t dnsmasq_time(void);
|
||||||
@@ -1582,6 +1607,12 @@ void ipset_init(void);
|
|||||||
int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove);
|
int add_to_ipset(const char *setname, const union all_addr *ipaddr, int flags, int remove);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* nftset.c */
|
||||||
|
#ifdef HAVE_NFTSET
|
||||||
|
void nftset_init(void);
|
||||||
|
int add_to_nftset(const char *setpath, const union all_addr *ipaddr, int flags, int remove);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* pattern.c */
|
/* pattern.c */
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
int is_valid_dns_name(const char *value);
|
int is_valid_dns_name(const char *value);
|
||||||
@@ -1601,6 +1632,9 @@ void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer);
|
|||||||
void queue_arp(int action, unsigned char *mac, int maclen,
|
void queue_arp(int action, unsigned char *mac, int maclen,
|
||||||
int family, union all_addr *addr);
|
int family, union all_addr *addr);
|
||||||
int helper_buf_empty(void);
|
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
|
#endif
|
||||||
|
|
||||||
/* tftp.c */
|
/* tftp.c */
|
||||||
@@ -1646,7 +1680,10 @@ unsigned short dhcp6_reply(struct dhcp_context *context, int interface, char *if
|
|||||||
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
|
void relay_upstream6(struct dhcp_relay *relay, ssize_t sz, struct in6_addr *peer_address,
|
||||||
u32 scope_id, time_t now);
|
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
|
#endif
|
||||||
|
|
||||||
/* dhcp-common.c */
|
/* dhcp-common.c */
|
||||||
@@ -1734,7 +1771,11 @@ int do_poll(int timeout);
|
|||||||
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
|
size_t rrfilter(struct dns_header *header, size_t plen, int mode);
|
||||||
u16 *rrfilter_desc(int type);
|
u16 *rrfilter_desc(int type);
|
||||||
int expand_workspace(unsigned char ***wkspc, int *szp, int new);
|
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 */
|
/* edns0.c */
|
||||||
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
unsigned char *find_pseudoheader(struct dns_header *header, size_t plen,
|
||||||
size_t *len, unsigned char **p, int *is_sign, int *is_last);
|
size_t *len, unsigned char **p, int *is_sign, int *is_last);
|
||||||
|
|||||||
+5
-2
@@ -724,7 +724,8 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
|
|||||||
|
|
||||||
/* namebuff used for workspace above, restore to leave unchanged on exit */
|
/* namebuff used for workspace above, restore to leave unchanged on exit */
|
||||||
p = (unsigned char*)(rrset[0]);
|
p = (unsigned char*)(rrset[0]);
|
||||||
extract_name(header, plen, &p, name, 1, 0);
|
if (!extract_name(header, plen, &p, name, 1, 0))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
if (key)
|
if (key)
|
||||||
{
|
{
|
||||||
@@ -1017,7 +1018,9 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
p = (unsigned char *)(header+1);
|
p = (unsigned char *)(header+1);
|
||||||
extract_name(header, plen, &p, name, 1, 4);
|
if (!extract_name(header, plen, &p, name, 1, 4))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
p += 4; /* qtype, qclass */
|
p += 4; /* qtype, qclass */
|
||||||
|
|
||||||
/* If the key needed to validate the DS is on the same domain as the DS, we'll
|
/* If the key needed to validate the DS is on the same domain as the DS, we'll
|
||||||
|
|||||||
+113
-85
@@ -207,16 +207,16 @@ int lookup_domain(char *domain, int flags, int *lowout, int *highout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found && filter_servers(try, flags, &nlow, &nhigh))
|
||||||
{
|
|
||||||
/* We've matched a setting which says to use servers without a domain.
|
|
||||||
Continue the search with empty query */
|
|
||||||
if (daemon->serverarray[try]->flags & SERV_USE_RESOLV)
|
|
||||||
crop_query = qlen;
|
|
||||||
else if (filter_servers(try, flags, &nlow, &nhigh))
|
|
||||||
/* We have a match, but it may only be (say) an IPv6 address, and
|
/* We have a match, but it may only be (say) an IPv6 address, and
|
||||||
if the query wasn't for an AAAA record, it's no good, and we need
|
if the query wasn't for an AAAA record, it's no good, and we need
|
||||||
to continue generalising */
|
to continue generalising */
|
||||||
|
{
|
||||||
|
/* We've matched a setting which says to use servers without a domain.
|
||||||
|
Continue the search with empty query */
|
||||||
|
if (daemon->serverarray[nlow]->flags & SERV_USE_RESOLV)
|
||||||
|
crop_query = qlen;
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +293,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Now the servers are on order between low and high, in the order
|
/* Now the servers are on order between low and high, in the order
|
||||||
IPv6 addr, IPv4 addr, return zero for both, send upstream, no-data return.
|
IPv6 addr, IPv4 addr, return zero for both, resolvconf servers, send upstream, no-data return.
|
||||||
|
|
||||||
See which of those match our query in that priority order and narrow (low, high) */
|
See which of those match our query in that priority order and narrow (low, high) */
|
||||||
|
|
||||||
@@ -321,6 +321,13 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
|||||||
{
|
{
|
||||||
nlow = i;
|
nlow = i;
|
||||||
|
|
||||||
|
/* Short to resolv.conf servers */
|
||||||
|
for (i = nlow; i < nhigh && (daemon->serverarray[i]->flags & SERV_USE_RESOLV); i++);
|
||||||
|
|
||||||
|
if (i != nlow)
|
||||||
|
nhigh = i;
|
||||||
|
else
|
||||||
|
{
|
||||||
/* now look for a server */
|
/* now look for a server */
|
||||||
for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
for (i = nlow; i < nhigh && !(daemon->serverarray[i]->flags & SERV_LITERAL_ADDRESS); i++);
|
||||||
|
|
||||||
@@ -346,6 +353,7 @@ int filter_servers(int seed, int flags, int *lowout, int *highout)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
*lowout = nlow;
|
*lowout = nlow;
|
||||||
*highout = nhigh;
|
*highout = nhigh;
|
||||||
@@ -387,7 +395,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)
|
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;
|
unsigned char *p;
|
||||||
int start;
|
int start;
|
||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
@@ -410,8 +418,8 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
else
|
else
|
||||||
addr.addr4 = srv->addr;
|
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))
|
||||||
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);
|
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, name, (union all_addr *)&addr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,13 +433,14 @@ size_t make_local_answer(int flags, int gotname, size_t size, struct dns_header
|
|||||||
else
|
else
|
||||||
addr.addr6 = srv->addr;
|
addr.addr6 = 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_AAAA, C_IN, "6", &addr))
|
||||||
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);
|
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, name, (union all_addr *)&addr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trunc)
|
if (trunc)
|
||||||
header->hb3 |= HB3_TC;
|
header->hb3 |= HB3_TC;
|
||||||
|
header->ancount = htons(anscount);
|
||||||
|
|
||||||
return p - (unsigned char *)header;
|
return p - (unsigned char *)header;
|
||||||
}
|
}
|
||||||
@@ -485,7 +494,7 @@ static int order(char *qdomain, size_t qlen, struct server *serv)
|
|||||||
if (qlen > dlen)
|
if (qlen > dlen)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return strcmp(qdomain, serv->domain);
|
return hostname_order(qdomain, serv->domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int order_servers(struct server *s1, struct server *s2)
|
static int order_servers(struct server *s1, struct server *s2)
|
||||||
@@ -520,10 +529,10 @@ static int order_qsort(const void *a, const void *b)
|
|||||||
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
|
/* Sort all literal NODATA and local IPV4 or IPV6 responses together,
|
||||||
in a very specific order. We flip the SERV_LITERAL_ADDRESS bit
|
in a very specific order. We flip the SERV_LITERAL_ADDRESS bit
|
||||||
so the order is IPv6 literal, IPv4 literal, all-zero literal,
|
so the order is IPv6 literal, IPv4 literal, all-zero literal,
|
||||||
upstream server, NXDOMAIN literal. */
|
unqualified servers, upstream server, NXDOMAIN literal. */
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
|
rc = ((s2->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS) -
|
||||||
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
|
((s1->flags & (SERV_LITERAL_ADDRESS | SERV_4ADDR | SERV_6ADDR | SERV_USE_RESOLV | SERV_ALL_ZEROS)) ^ SERV_LITERAL_ADDRESS);
|
||||||
|
|
||||||
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
|
/* Finally, order by appearance in /etc/resolv.conf etc, for --strict-order */
|
||||||
if (rc == 0)
|
if (rc == 0)
|
||||||
@@ -533,22 +542,39 @@ static int order_qsort(const void *a, const void *b)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||||
void mark_servers(int flag)
|
void mark_servers(int flag)
|
||||||
{
|
{
|
||||||
struct server *serv;
|
struct server *serv, **up;
|
||||||
|
|
||||||
|
daemon->servers_tail = NULL;
|
||||||
|
|
||||||
/* mark everything with argument flag */
|
/* mark everything with argument flag */
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
|
{
|
||||||
if (serv->flags & flag)
|
if (serv->flags & flag)
|
||||||
serv->flags |= SERV_MARK;
|
serv->flags |= SERV_MARK;
|
||||||
else
|
else
|
||||||
serv->flags &= ~SERV_MARK;
|
serv->flags &= ~SERV_MARK;
|
||||||
|
|
||||||
for (serv = daemon->local_domains; serv; serv = serv->next)
|
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)
|
if (serv->flags & flag)
|
||||||
serv->flags |= SERV_MARK;
|
{
|
||||||
|
*up = serv->next;
|
||||||
|
free(serv->domain);
|
||||||
|
free(serv);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
serv->flags &= ~SERV_MARK;
|
up = &serv->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cleanup_servers(void)
|
void cleanup_servers(void)
|
||||||
@@ -556,7 +582,7 @@ void cleanup_servers(void)
|
|||||||
struct server *serv, *tmp, **up;
|
struct server *serv, *tmp, **up;
|
||||||
|
|
||||||
/* unlink and free anything still marked. */
|
/* 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;
|
tmp = serv->next;
|
||||||
if (serv->flags & SERV_MARK)
|
if (serv->flags & SERV_MARK)
|
||||||
@@ -567,20 +593,10 @@ void cleanup_servers(void)
|
|||||||
free(serv);
|
free(serv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
up = &serv->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
up = &serv->next;
|
||||||
|
daemon->servers_tail = serv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -609,17 +625,62 @@ int add_update_server(int flags,
|
|||||||
|
|
||||||
if (*domain == 0)
|
if (*domain == 0)
|
||||||
alloc_domain = whine_malloc(1);
|
alloc_domain = whine_malloc(1);
|
||||||
else if (!(alloc_domain = canonicalise((char *)domain, NULL)))
|
else
|
||||||
|
alloc_domain = canonicalise((char *)domain, NULL);
|
||||||
|
|
||||||
|
if (!alloc_domain)
|
||||||
return 0;
|
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)
|
if (flags & SERV_IS_LOCAL)
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
{
|
||||||
|
size_t size;
|
||||||
|
|
||||||
|
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 (!(serv = whine_malloc(size)))
|
||||||
|
{
|
||||||
|
free(alloc_domain);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
serv->next = daemon->local_domains;
|
||||||
|
daemon->local_domains = serv;
|
||||||
|
|
||||||
|
if (flags & SERV_4ADDR)
|
||||||
|
((struct serv_addr4*)serv)->addr = local_addr->addr4;
|
||||||
|
|
||||||
|
if (flags & SERV_6ADDR)
|
||||||
|
((struct serv_addr6*)serv)->addr = local_addr->addr6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Upstream servers. See if there is a suitable candidate, if so unmark
|
||||||
|
and move to the end of the list, for order. The entry found may already
|
||||||
|
be at the end. */
|
||||||
|
struct server **up, *tmp;
|
||||||
|
|
||||||
|
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||||
|
{
|
||||||
|
tmp = serv->next;
|
||||||
if ((serv->flags & SERV_MARK) &&
|
if ((serv->flags & SERV_MARK) &&
|
||||||
hostname_isequal(alloc_domain, serv->domain))
|
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;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (serv)
|
if (serv)
|
||||||
{
|
{
|
||||||
@@ -628,59 +689,22 @@ int add_update_server(int flags,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
size_t size;
|
if (!(serv = whine_malloc(sizeof(struct server))))
|
||||||
|
|
||||||
if (flags & SERV_LITERAL_ADDRESS)
|
|
||||||
{
|
{
|
||||||
if (flags & SERV_6ADDR)
|
free(alloc_domain);
|
||||||
size = sizeof(struct serv_addr6);
|
|
||||||
else if (flags & SERV_4ADDR)
|
|
||||||
size = sizeof(struct serv_addr4);
|
|
||||||
else
|
|
||||||
size = sizeof(struct serv_local);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
size = sizeof(struct server);
|
|
||||||
|
|
||||||
if (!(serv = whine_malloc(size)))
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (flags & SERV_IS_LOCAL)
|
|
||||||
{
|
|
||||||
serv->next = daemon->local_domains;
|
|
||||||
daemon->local_domains = serv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct server *s;
|
|
||||||
/* Add to the end of the chain, for order */
|
|
||||||
if (!daemon->servers)
|
|
||||||
daemon->servers = serv;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (s = daemon->servers; s->next; s = s->next);
|
|
||||||
s->next = serv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
serv->next = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(flags & SERV_IS_LOCAL))
|
|
||||||
memset(serv, 0, sizeof(struct server));
|
memset(serv, 0, sizeof(struct server));
|
||||||
|
|
||||||
serv->flags = flags;
|
/* Add to the end of the chain, for order */
|
||||||
serv->domain = alloc_domain;
|
if (daemon->servers_tail)
|
||||||
serv->domain_len = strlen(alloc_domain);
|
daemon->servers_tail->next = serv;
|
||||||
|
else
|
||||||
|
daemon->servers = serv;
|
||||||
|
daemon->servers_tail = 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;
|
|
||||||
|
|
||||||
if (!(flags & SERV_IS_LOCAL))
|
|
||||||
{
|
|
||||||
#ifdef HAVE_LOOP
|
#ifdef HAVE_LOOP
|
||||||
serv->uid = rand32();
|
serv->uid = rand32();
|
||||||
#endif
|
#endif
|
||||||
@@ -693,6 +717,10 @@ int add_update_server(int flags,
|
|||||||
serv->source_addr = *source_addr;
|
serv->source_addr = *source_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serv->flags = flags;
|
||||||
|
serv->domain = alloc_domain;
|
||||||
|
serv->domain_len = strlen(alloc_domain);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
+10
-8
@@ -178,7 +178,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
|
|||||||
memcpy(buff, datap, rdlen);
|
memcpy(buff, datap, rdlen);
|
||||||
|
|
||||||
/* now, delete OPT RR */
|
/* now, delete OPT RR */
|
||||||
plen = rrfilter(header, plen, 0);
|
plen = rrfilter(header, plen, RRFILTER_EDNS0);
|
||||||
|
|
||||||
/* Now, force addition of a new one */
|
/* Now, force addition of a new one */
|
||||||
p = NULL;
|
p = NULL;
|
||||||
@@ -460,31 +460,33 @@ static size_t add_umbrella_opt(struct dns_header *header, size_t plen, unsigned
|
|||||||
|
|
||||||
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
|
struct umbrella_opt opt = {{"ODNS"}, UMBRELLA_VERSION, 0, {}};
|
||||||
u8 *u = &opt.fields[0];
|
u8 *u = &opt.fields[0];
|
||||||
|
int family = source->sa.sa_family;
|
||||||
|
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
|
||||||
|
|
||||||
if (daemon->umbrella_org) {
|
if (daemon->umbrella_org)
|
||||||
|
{
|
||||||
PUTSHORT(UMBRELLA_ORG, u);
|
PUTSHORT(UMBRELLA_ORG, u);
|
||||||
PUTLONG(daemon->umbrella_org, u);
|
PUTLONG(daemon->umbrella_org, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
int family = source->sa.sa_family;
|
|
||||||
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
PUTSHORT(family == AF_INET ? UMBRELLA_IPV4 : UMBRELLA_IPV6, u);
|
||||||
int size = family == AF_INET ? INADDRSZ : IN6ADDRSZ;
|
|
||||||
memcpy(u, get_addrp(source, family), size);
|
memcpy(u, get_addrp(source, family), size);
|
||||||
u += size;
|
u += size;
|
||||||
|
|
||||||
if (option_bool(OPT_UMBRELLA_DEVID)) {
|
if (option_bool(OPT_UMBRELLA_DEVID))
|
||||||
|
{
|
||||||
PUTSHORT(UMBRELLA_DEVICE, u);
|
PUTSHORT(UMBRELLA_DEVICE, u);
|
||||||
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
memcpy(u, (char *)&daemon->umbrella_device, UMBRELLA_DEVICESZ);
|
||||||
u += UMBRELLA_DEVICESZ;
|
u += UMBRELLA_DEVICESZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemon->umbrella_asset) {
|
if (daemon->umbrella_asset)
|
||||||
|
{
|
||||||
PUTSHORT(UMBRELLA_ASSET, u);
|
PUTSHORT(UMBRELLA_ASSET, u);
|
||||||
PUTLONG(daemon->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, u - (u8 *)&opt, 0, 1);
|
||||||
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_UMBRELLA, (unsigned char *)&opt, len, 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set *check_subnet if we add a client subnet option, which needs to checked
|
/* Set *check_subnet if we add a client subnet option, which needs to checked
|
||||||
|
|||||||
+79
-35
@@ -151,13 +151,22 @@ static void server_send_log(struct server *server, int fd,
|
|||||||
|
|
||||||
static int domain_no_rebind(char *domain)
|
static int domain_no_rebind(char *domain)
|
||||||
{
|
{
|
||||||
struct server *serv;
|
struct rebind_domain *rbd;
|
||||||
int dlen = (int)strlen(domain);
|
size_t tlen, dlen = strlen(domain);
|
||||||
|
char *dots = strchr(domain, '.');
|
||||||
|
|
||||||
for (serv = daemon->no_rebind; serv; serv = serv->next)
|
/* Match whole labels only. Empty domain matches no dots (any single label) */
|
||||||
if (dlen >= serv->domain_len && strcmp(serv->domain, &domain[dlen - serv->domain_len]) == 0)
|
for (rbd = daemon->no_rebind; rbd; rbd = rbd->next)
|
||||||
|
{
|
||||||
|
if (dlen >= (tlen = strlen(rbd->domain)) &&
|
||||||
|
hostname_isequal(rbd->domain, &domain[dlen - tlen]) &&
|
||||||
|
(dlen == tlen || domain[dlen - tlen - 1] == '.'))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (tlen == 0 && !dots)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,10 +179,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
unsigned int fwd_flags = 0;
|
unsigned int fwd_flags = 0;
|
||||||
int is_dnssec = forward && (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY));
|
int is_dnssec = forward && (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY));
|
||||||
struct server *master;
|
struct server *master;
|
||||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
|
||||||
void *hash = hash_questions(header, plen, daemon->namebuff);
|
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);
|
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||||
int old_src = 0;
|
int old_src = 0, old_reply = 0;
|
||||||
int first, last, start = 0;
|
int first, last, start = 0;
|
||||||
int subnet, cacheable, forwarded = 0;
|
int subnet, cacheable, forwarded = 0;
|
||||||
size_t edns0_len;
|
size_t edns0_len;
|
||||||
@@ -199,7 +208,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
Similarly FREC_NO_CACHE is never set in flags, so a query which is
|
Similarly FREC_NO_CACHE is never set in flags, so a query which is
|
||||||
contigent on a particular source address EDNS0 option will never be matched. */
|
contigent on a particular source address EDNS0 option will never be matched. */
|
||||||
if (forward)
|
if (forward)
|
||||||
|
{
|
||||||
old_src = 1;
|
old_src = 1;
|
||||||
|
old_reply = 1;
|
||||||
|
}
|
||||||
else if ((forward = lookup_frec_by_query(hash, fwd_flags,
|
else if ((forward = lookup_frec_by_query(hash, fwd_flags,
|
||||||
FREC_CHECKING_DISABLED | FREC_AD_QUESTION | FREC_DO_QUESTION |
|
FREC_CHECKING_DISABLED | FREC_AD_QUESTION | FREC_DO_QUESTION |
|
||||||
FREC_HAS_PHEADER | FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_NO_CACHE)))
|
FREC_HAS_PHEADER | FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_NO_CACHE)))
|
||||||
@@ -212,7 +224,11 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (src)
|
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
|
else
|
||||||
{
|
{
|
||||||
/* Existing query, but from new source, just add this
|
/* Existing query, but from new source, just add this
|
||||||
@@ -283,6 +299,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
goto reply;
|
goto reply;
|
||||||
/* table full - flags == 0, return REFUSED */
|
/* table full - flags == 0, return REFUSED */
|
||||||
|
|
||||||
|
forward->frec_src.log_id = daemon->log_id;
|
||||||
forward->frec_src.source = *udpaddr;
|
forward->frec_src.source = *udpaddr;
|
||||||
forward->frec_src.orig_id = ntohs(header->id);
|
forward->frec_src.orig_id = ntohs(header->id);
|
||||||
forward->frec_src.dest = *dst_addr;
|
forward->frec_src.dest = *dst_addr;
|
||||||
@@ -326,7 +343,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* retry on existing query, from original source. Send to all available servers */
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
/* If we've already got an answer to this query, but we're awaiting keys for validation,
|
/* 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...... */
|
there's no point retrying the query, retry the key query instead...... */
|
||||||
@@ -338,6 +354,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
while (forward->blocking_query)
|
while (forward->blocking_query)
|
||||||
forward = 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);
|
blockdata_retrieve(forward->stash, forward->stash_len, (void *)header);
|
||||||
plen = forward->stash_len;
|
plen = forward->stash_len;
|
||||||
/* get query for logging. */
|
/* get query for logging. */
|
||||||
@@ -376,9 +395,18 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
/* In strict order mode, there must be a server later in the list
|
/* In strict order mode, there must be a server later in the list
|
||||||
left to send to, otherwise without the forwardall mechanism,
|
left to send to, otherwise without the forwardall mechanism,
|
||||||
code further on will cycle around the list forwever if they
|
code further on will cycle around the list forwever if they
|
||||||
all return REFUSED. If at the last, give up. */
|
all return REFUSED. If at the last, give up.
|
||||||
|
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 trying the last server.. */
|
||||||
if (++start == last)
|
if (++start == last)
|
||||||
|
{
|
||||||
|
if (old_reply)
|
||||||
goto reply;
|
goto reply;
|
||||||
|
else
|
||||||
|
start--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -390,9 +418,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
forward->flags |= FREC_TEST_PKTSZ;
|
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. */
|
/* We may be resending a DNSSEC query here, for which the below processing is not necessary. */
|
||||||
if (!is_dnssec)
|
if (!is_dnssec)
|
||||||
{
|
{
|
||||||
@@ -556,12 +581,33 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ipsets *domain_find_sets(struct ipsets *setlist, const char *domain) {
|
||||||
|
/* Similar algorithm to search_servers. */
|
||||||
|
struct ipsets *ipset_pos, *ret = NULL;
|
||||||
|
unsigned int namelen = strlen(domain);
|
||||||
|
unsigned int matchlen = 0;
|
||||||
|
for (ipset_pos = setlist; ipset_pos; ipset_pos = ipset_pos->next)
|
||||||
|
{
|
||||||
|
unsigned int domainlen = strlen(ipset_pos->domain);
|
||||||
|
const char *matchstart = domain + namelen - domainlen;
|
||||||
|
if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
|
||||||
|
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
|
||||||
|
domainlen >= matchlen)
|
||||||
|
{
|
||||||
|
matchlen = domainlen;
|
||||||
|
ret = ipset_pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static size_t process_reply(struct dns_header *header, time_t now, struct server *server, size_t n, int check_rebind,
|
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 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)
|
int check_subnet, union mysockaddr *query_source, unsigned char *limit, int ede)
|
||||||
{
|
{
|
||||||
unsigned char *pheader, *sizep;
|
unsigned char *pheader, *sizep;
|
||||||
char **sets = 0;
|
struct ipsets *ipsets = NULL, *nftsets = NULL;
|
||||||
int munged = 0, is_sign;
|
int munged = 0, is_sign;
|
||||||
unsigned int rcode = RCODE(header);
|
unsigned int rcode = RCODE(header);
|
||||||
size_t plen;
|
size_t plen;
|
||||||
@@ -572,24 +618,12 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
|
if (daemon->ipsets && extract_request(header, n, daemon->namebuff, NULL))
|
||||||
{
|
ipsets = domain_find_sets(daemon->ipsets, daemon->namebuff);
|
||||||
/* Similar algorithm to search_servers. */
|
#endif
|
||||||
struct ipsets *ipset_pos;
|
|
||||||
unsigned int namelen = strlen(daemon->namebuff);
|
#ifdef HAVE_NFTSET
|
||||||
unsigned int matchlen = 0;
|
if (daemon->nftsets && extract_request(header, n, daemon->namebuff, NULL))
|
||||||
for (ipset_pos = daemon->ipsets; ipset_pos; ipset_pos = ipset_pos->next)
|
nftsets = domain_find_sets(daemon->nftsets, daemon->namebuff);
|
||||||
{
|
|
||||||
unsigned int domainlen = strlen(ipset_pos->domain);
|
|
||||||
char *matchstart = daemon->namebuff + namelen - domainlen;
|
|
||||||
if (namelen >= domainlen && hostname_isequal(matchstart, ipset_pos->domain) &&
|
|
||||||
(domainlen == 0 || namelen == domainlen || *(matchstart - 1) == '.' ) &&
|
|
||||||
domainlen >= matchlen)
|
|
||||||
{
|
|
||||||
matchlen = domainlen;
|
|
||||||
sets = ipset_pos->sets;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
|
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
|
||||||
@@ -608,7 +642,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
if (added_pheader)
|
if (added_pheader)
|
||||||
{
|
{
|
||||||
/* client didn't send EDNS0, we added one, strip it off before returning answer. */
|
/* 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;
|
pheader = NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -698,7 +732,17 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extract_addresses(header, n, daemon->namebuff, now, sets, is_sign, check_rebind, no_cache, cache_secure, &doctored))
|
/* 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);
|
my_syslog(LOG_WARNING, _("possible DNS-rebind attack detected: %s"), daemon->namebuff);
|
||||||
munged = 1;
|
munged = 1;
|
||||||
@@ -727,7 +771,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 the requestor didn't set the DO bit, don't return DNSSEC info. */
|
||||||
if (!do_bit)
|
if (!do_bit)
|
||||||
n = rrfilter(header, n, 1);
|
n = rrfilter(header, n, RRFILTER_DNSSEC);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1863,7 +1907,7 @@ unsigned char *tcp_request(int confd, time_t now,
|
|||||||
int first, last;
|
int first, last;
|
||||||
unsigned int flags = 0;
|
unsigned int flags = 0;
|
||||||
|
|
||||||
if (getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
|
if (!packet || getpeername(confd, (struct sockaddr *)&peer_addr, &peer_len) == -1)
|
||||||
return packet;
|
return packet;
|
||||||
|
|
||||||
#ifdef HAVE_CONNTRACK
|
#ifdef HAVE_CONNTRACK
|
||||||
@@ -2274,7 +2318,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (j == daemon->numrrand)
|
if (!rfd) /* should be when j == daemon->numrrand */
|
||||||
{
|
{
|
||||||
struct randfd_list *rfl_poll;
|
struct randfd_list *rfl_poll;
|
||||||
|
|
||||||
|
|||||||
+54
-5
@@ -233,6 +233,11 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
is6 = (data.flags != AF_INET);
|
is6 = (data.flags != AF_INET);
|
||||||
data.action = ACTION_ARP;
|
data.action = ACTION_ARP;
|
||||||
}
|
}
|
||||||
|
else if (data.action == ACTION_RELAY_SNOOP)
|
||||||
|
{
|
||||||
|
is6 = 1;
|
||||||
|
action_str = "relay-snoop";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -286,7 +291,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
char *dot;
|
char *dot;
|
||||||
hostname = (char *)buf;
|
hostname = (char *)buf;
|
||||||
hostname[data.hostname_len - 1] = 0;
|
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))
|
if (!legal_hostname(hostname))
|
||||||
hostname = NULL;
|
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 */
|
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)
|
else if (data.action == ACTION_ARP)
|
||||||
{
|
{
|
||||||
lua_getglobal(lua, "arp");
|
lua_getglobal(lua, "arp");
|
||||||
@@ -432,8 +455,8 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
buf = grab_extradata_lua(buf, end, "relay_address");
|
buf = grab_extradata_lua(buf, end, "relay_address");
|
||||||
else if (data.giaddr.s_addr != 0)
|
else if (data.giaddr.s_addr != 0)
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET, &data.giaddr, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &data.giaddr, daemon->dhcp_buff2, ADDRSTRLEN);
|
||||||
lua_pushstring(lua, daemon->addrbuff);
|
lua_pushstring(lua, daemon->dhcp_buff2);
|
||||||
lua_setfield(lua, -2, "relay_address");
|
lua_setfield(lua, -2, "relay_address");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,7 +576,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
close(pipeout[1]);
|
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
|
#ifdef HAVE_DHCP6
|
||||||
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
|
my_setenv("DNSMASQ_IAID", is6 ? daemon->dhcp_buff3 : NULL, &err);
|
||||||
@@ -615,7 +638,7 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
|
|||||||
{
|
{
|
||||||
const char *giaddr = NULL;
|
const char *giaddr = NULL;
|
||||||
if (data.giaddr.s_addr != 0)
|
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);
|
my_setenv("DNSMASQ_RELAY_ADDRESS", giaddr, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -640,6 +663,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);
|
fcntl(event_fd, F_SETFD, i | FD_CLOEXEC);
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
|
|
||||||
|
if (data.action == ACTION_RELAY_SNOOP)
|
||||||
|
strcpy(daemon->packet, data.interface);
|
||||||
|
|
||||||
p = strrchr(daemon->lease_change_command, '/');
|
p = strrchr(daemon->lease_change_command, '/');
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
{
|
{
|
||||||
@@ -810,6 +836,29 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
|
|||||||
bytes_in_buf = p - (unsigned char *)buf;
|
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
|
#ifdef HAVE_TFTP
|
||||||
/* This nastily re-uses DHCP-fields for TFTP stuff */
|
/* This nastily re-uses DHCP-fields for TFTP stuff */
|
||||||
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
void queue_tftp(off_t file_len, char *filename, union mysockaddr *peer)
|
||||||
|
|||||||
+8
-1
@@ -148,13 +148,20 @@ void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revh
|
|||||||
if (!(ah->flags & flag))
|
if (!(ah->flags & flag))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (stat(ah->fname, &buf) == -1 || !(S_ISDIR(buf.st_mode)))
|
if (stat(ah->fname, &buf) == -1)
|
||||||
{
|
{
|
||||||
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
||||||
ah->fname, strerror(errno));
|
ah->fname, strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(S_ISDIR(buf.st_mode)))
|
||||||
|
{
|
||||||
|
my_syslog(LOG_ERR, _("bad dynamic directory %s: %s"),
|
||||||
|
ah->fname, _("not a directory"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(ah->flags & AH_WD_DONE))
|
if (!(ah->flags & AH_WD_DONE))
|
||||||
{
|
{
|
||||||
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
|
ah->wd = inotify_add_watch(daemon->inotifyfd, ah->fname, IN_CLOSE_WRITE | IN_MOVED_TO);
|
||||||
|
|||||||
+5
-1
@@ -1586,6 +1586,9 @@ void check_servers(int no_loop_check)
|
|||||||
if (serv->sfd)
|
if (serv->sfd)
|
||||||
serv->sfd->used = 1;
|
serv->sfd->used = 1;
|
||||||
|
|
||||||
|
if (count == SERVERS_LOGGED)
|
||||||
|
my_syslog(LOG_INFO, _("more servers are defined but not logged"));
|
||||||
|
|
||||||
if (++count > SERVERS_LOGGED)
|
if (++count > SERVERS_LOGGED)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -1623,7 +1626,8 @@ void check_servers(int no_loop_check)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ((serv->flags & SERV_LITERAL_ADDRESS) &&
|
if ((serv->flags & SERV_LITERAL_ADDRESS) &&
|
||||||
!(serv->flags & (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)))
|
!(serv->flags & (SERV_6ADDR | SERV_4ADDR | SERV_ALL_ZEROS)) &&
|
||||||
|
strlen(serv->domain))
|
||||||
{
|
{
|
||||||
count--;
|
count--;
|
||||||
if (++locals <= LOCALS_LOGGED)
|
if (++locals <= LOCALS_LOGGED)
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2 dated June, 1991, or
|
||||||
|
(at your option) version 3 dated 29 June, 2007.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
|
#if defined (HAVE_NFTSET) && defined (HAVE_LINUX_NETWORK)
|
||||||
|
|
||||||
|
#include <nftables/libnftables.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
|
static struct nft_ctx *ctx = NULL;
|
||||||
|
static const char *cmd_add = "add element %s { %s }";
|
||||||
|
static const char *cmd_del = "delete element %s { %s }";
|
||||||
|
|
||||||
|
void nftset_init()
|
||||||
|
{
|
||||||
|
ctx = nft_ctx_new(NFT_CTX_DEFAULT);
|
||||||
|
if (ctx == NULL)
|
||||||
|
die(_("failed to create nftset context"), NULL, EC_MISC);
|
||||||
|
|
||||||
|
/* disable libnftables output */
|
||||||
|
nft_ctx_buffer_error(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int add_to_nftset(const char *setname, const union all_addr *ipaddr, int flags, int remove)
|
||||||
|
{
|
||||||
|
const char *cmd = remove ? cmd_del : cmd_add;
|
||||||
|
int ret, af = (flags & F_IPV4) ? AF_INET : AF_INET6;
|
||||||
|
size_t new_sz;
|
||||||
|
char *new, *err, *nl;
|
||||||
|
static char *cmd_buf = NULL;
|
||||||
|
static size_t cmd_buf_sz = 0;
|
||||||
|
|
||||||
|
inet_ntop(af, ipaddr, daemon->addrbuff, ADDRSTRLEN);
|
||||||
|
|
||||||
|
if (setname[1] == ' ' && (setname[0] == '4' || setname[0] == '6'))
|
||||||
|
{
|
||||||
|
if (setname[0] == '4' && !(flags & F_IPV4))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (setname[0] == '6' && !(flags & F_IPV6))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
setname += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd_buf_sz == 0)
|
||||||
|
new_sz = 150; /* initial allocation */
|
||||||
|
else
|
||||||
|
new_sz = snprintf(cmd_buf, cmd_buf_sz, cmd, setname, daemon->addrbuff);
|
||||||
|
|
||||||
|
if (new_sz > cmd_buf_sz)
|
||||||
|
{
|
||||||
|
if (!(new = whine_malloc(new_sz + 10)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (cmd_buf)
|
||||||
|
free(cmd_buf);
|
||||||
|
cmd_buf = new;
|
||||||
|
cmd_buf_sz = new_sz + 10;
|
||||||
|
snprintf(cmd_buf, cmd_buf_sz, cmd, setname, daemon->addrbuff);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nft_run_cmd_from_buffer(ctx, cmd_buf);
|
||||||
|
err = (char *)nft_ctx_get_error_buffer(ctx);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
/* Log only first line of error return. */
|
||||||
|
if ((nl = strchr(err, '\n')))
|
||||||
|
*nl = 0;
|
||||||
|
my_syslog(LOG_ERR, "nftset %s %s", setname, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
+246
-102
@@ -174,6 +174,9 @@ struct myoption {
|
|||||||
#define LOPT_CMARK_ALST_EN 365
|
#define LOPT_CMARK_ALST_EN 365
|
||||||
#define LOPT_CMARK_ALST 366
|
#define LOPT_CMARK_ALST 366
|
||||||
#define LOPT_QUIET_TFTP 367
|
#define LOPT_QUIET_TFTP 367
|
||||||
|
#define LOPT_NFTSET 368
|
||||||
|
#define LOPT_FILTER_A 369
|
||||||
|
#define LOPT_FILTER_AAAA 370
|
||||||
|
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
static const struct option opts[] =
|
static const struct option opts[] =
|
||||||
@@ -211,6 +214,8 @@ static const struct myoption opts[] =
|
|||||||
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
|
{ "ignore-address", 1, 0, LOPT_IGNORE_ADDR },
|
||||||
{ "selfmx", 0, 0, 'e' },
|
{ "selfmx", 0, 0, 'e' },
|
||||||
{ "filterwin2k", 0, 0, 'f' },
|
{ "filterwin2k", 0, 0, 'f' },
|
||||||
|
{ "filter-A", 0, 0, LOPT_FILTER_A },
|
||||||
|
{ "filter-AAAA", 0, 0, LOPT_FILTER_AAAA },
|
||||||
{ "pid-file", 2, 0, 'x' },
|
{ "pid-file", 2, 0, 'x' },
|
||||||
{ "strict-order", 0, 0, 'o' },
|
{ "strict-order", 0, 0, 'o' },
|
||||||
{ "server", 1, 0, 'S' },
|
{ "server", 1, 0, 'S' },
|
||||||
@@ -327,6 +332,7 @@ static const struct myoption opts[] =
|
|||||||
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
|
{ "auth-sec-servers", 1, 0, LOPT_AUTHSFS },
|
||||||
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
|
{ "auth-peer", 1, 0, LOPT_AUTHPEER },
|
||||||
{ "ipset", 1, 0, LOPT_IPSET },
|
{ "ipset", 1, 0, LOPT_IPSET },
|
||||||
|
{ "nftset", 1, 0, LOPT_NFTSET },
|
||||||
{ "connmark-allowlist-enable", 2, 0, LOPT_CMARK_ALST_EN },
|
{ "connmark-allowlist-enable", 2, 0, LOPT_CMARK_ALST_EN },
|
||||||
{ "connmark-allowlist", 1, 0, LOPT_CMARK_ALST },
|
{ "connmark-allowlist", 1, 0, LOPT_CMARK_ALST },
|
||||||
{ "synth-domain", 1, 0, LOPT_SYNTH },
|
{ "synth-domain", 1, 0, LOPT_SYNTH },
|
||||||
@@ -380,6 +386,8 @@ static struct {
|
|||||||
{ 'e', OPT_SELFMX, NULL, gettext_noop("Return self-pointing MX records for local hosts."), NULL },
|
{ '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 },
|
{ '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 },
|
{ '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 },
|
{ '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_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 },
|
{ 'G', ARG_DUP, "<hostspec>", gettext_noop("Set address or hostname for a specified machine."), NULL },
|
||||||
@@ -514,6 +522,7 @@ static struct {
|
|||||||
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
{ LOPT_AUTHSFS, ARG_DUP, "<NS>[,<NS>...]", gettext_noop("Secondary authoritative nameservers for forward domains"), NULL },
|
||||||
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
|
{ LOPT_AUTHPEER, ARG_DUP, "<ipaddr>[,<ipaddr>...]", gettext_noop("Peers which are allowed to do zone transfer"), NULL },
|
||||||
{ LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
{ LOPT_IPSET, ARG_DUP, "/<domain>[/<domain>...]/<ipset>...", gettext_noop("Specify ipsets to which matching domains should be added"), NULL },
|
||||||
|
{ LOPT_NFTSET, ARG_DUP, "/<domain>[/<domain>...]/<nftset>...", gettext_noop("Specify nftables sets to which matching domains should be added"), NULL },
|
||||||
{ LOPT_CMARK_ALST_EN, ARG_ONE, "[=<mask>]", gettext_noop("Enable filtering of DNS queries with connection-track marks."), NULL },
|
{ LOPT_CMARK_ALST_EN, ARG_ONE, "[=<mask>]", gettext_noop("Enable filtering of DNS queries with connection-track marks."), NULL },
|
||||||
{ LOPT_CMARK_ALST, ARG_DUP, "<connmark>[/<mask>][,<pattern>[/<pattern>...]]", gettext_noop("Set allowed DNS patterns for a connection-track mark."), NULL },
|
{ LOPT_CMARK_ALST, ARG_DUP, "<connmark>[/<mask>][,<pattern>[/<pattern>...]]", gettext_noop("Set allowed DNS patterns for a connection-track mark."), NULL },
|
||||||
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
|
{ LOPT_SYNTH, ARG_DUP, "<domain>,<range>,[<prefix>]", gettext_noop("Specify a domain and address range for synthesised names"), NULL },
|
||||||
@@ -654,7 +663,7 @@ static char *canonicalise_opt(char *s)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strlen(s) == 0)
|
if (strlen(s) == 0)
|
||||||
return opt_string_alloc("");
|
return opt_malloc(1); /* Heap-allocated empty string */
|
||||||
|
|
||||||
unhide_metas(s);
|
unhide_metas(s);
|
||||||
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
if (!(ret = canonicalise(s, &nomem)) && nomem)
|
||||||
@@ -798,7 +807,7 @@ static void do_usage(void)
|
|||||||
|
|
||||||
if (usage[i].arg)
|
if (usage[i].arg)
|
||||||
{
|
{
|
||||||
strcpy(buff, usage[i].arg);
|
safe_strncpy(buff, usage[i].arg, sizeof(buff));
|
||||||
for (j = 0; tab[j].handle; j++)
|
for (j = 0; tab[j].handle; j++)
|
||||||
if (tab[j].handle == *(usage[i].arg))
|
if (tab[j].handle == *(usage[i].arg))
|
||||||
sprintf(buff, "%d", tab[j].val);
|
sprintf(buff, "%d", tab[j].val);
|
||||||
@@ -935,52 +944,124 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int domain_rev4(char *domain, struct in_addr addr, int msize)
|
static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int size)
|
||||||
{
|
{
|
||||||
in_addr_t a = ntohl(addr.s_addr);
|
int i, j;
|
||||||
|
char *string;
|
||||||
|
int msize;
|
||||||
|
u16 flags = 0;
|
||||||
|
char domain[29]; /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
|
||||||
|
union mysockaddr serv_addr, source_addr;
|
||||||
|
char interface[IF_NAMESIZE+1];
|
||||||
|
int count = 1, rem, addrbytes, addrbits;
|
||||||
|
|
||||||
|
if (!server)
|
||||||
|
flags = SERV_LITERAL_ADDRESS;
|
||||||
|
else if ((string = parse_server(server, &serv_addr, &source_addr, interface, &flags)))
|
||||||
|
return string;
|
||||||
|
|
||||||
|
if (from_file)
|
||||||
|
flags |= SERV_FROM_FILE;
|
||||||
|
|
||||||
|
rem = size & 0x7;
|
||||||
|
addrbytes = (32 - size) >> 3;
|
||||||
|
addrbits = (32 - size) & 7;
|
||||||
|
|
||||||
|
if (size > 32 || size < 1)
|
||||||
|
return _("bad IPv4 prefix length");
|
||||||
|
|
||||||
|
/* Zero out last address bits according to CIDR mask */
|
||||||
|
((u8 *)addr4)[3-addrbytes] &= ~((1 << addrbits)-1);
|
||||||
|
|
||||||
|
size = size & ~0x7;
|
||||||
|
|
||||||
|
if (rem != 0)
|
||||||
|
count = 1 << (8 - rem);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
*domain = 0;
|
*domain = 0;
|
||||||
|
string = domain;
|
||||||
|
msize = size/8;
|
||||||
|
|
||||||
switch (msize)
|
for (j = (rem == 0) ? msize-1 : msize; j >= 0; j--)
|
||||||
{
|
{
|
||||||
case 32:
|
int dig = ((unsigned char *)addr4)[j];
|
||||||
domain += sprintf(domain, "%u.", a & 0xff);
|
|
||||||
/* fall through */
|
if (j == msize)
|
||||||
case 24:
|
dig += i;
|
||||||
domain += sprintf(domain, "%d.", (a >> 8) & 0xff);
|
|
||||||
/* fall through */
|
string += sprintf(string, "%d.", dig);
|
||||||
case 16:
|
|
||||||
domain += sprintf(domain, "%d.", (a >> 16) & 0xff);
|
|
||||||
/* fall through */
|
|
||||||
case 8:
|
|
||||||
domain += sprintf(domain, "%d.", (a >> 24) & 0xff);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
domain += sprintf(domain, "in-addr.arpa");
|
sprintf(string, "in-addr.arpa");
|
||||||
|
|
||||||
return 1;
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
||||||
|
return _("error");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int domain_rev6(char *domain, struct in6_addr *addr, int msize)
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, int size)
|
||||||
{
|
{
|
||||||
int i;
|
int i, j;
|
||||||
|
char *string;
|
||||||
|
int msize;
|
||||||
|
u16 flags = 0;
|
||||||
|
char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
|
||||||
|
union mysockaddr serv_addr, source_addr;
|
||||||
|
char interface[IF_NAMESIZE+1];
|
||||||
|
int count = 1, rem, addrbytes, addrbits;
|
||||||
|
|
||||||
if (msize > 128 || msize%4)
|
if (!server)
|
||||||
return 0;
|
flags = SERV_LITERAL_ADDRESS;
|
||||||
|
else if ((string = parse_server(server, &serv_addr, &source_addr, interface, &flags)))
|
||||||
|
return string;
|
||||||
|
|
||||||
|
if (from_file)
|
||||||
|
flags |= SERV_FROM_FILE;
|
||||||
|
|
||||||
|
rem = size & 0x3;
|
||||||
|
addrbytes = (128 - size) >> 3;
|
||||||
|
addrbits = (128 - size) & 7;
|
||||||
|
|
||||||
|
if (size > 128 || size < 1)
|
||||||
|
return _("bad IPv6 prefix length");
|
||||||
|
|
||||||
|
/* Zero out last address bits according to CIDR mask */
|
||||||
|
addr6->s6_addr[15-addrbytes] &= ~((1 << addrbits) - 1);
|
||||||
|
|
||||||
|
size = size & ~0x3;
|
||||||
|
|
||||||
|
if (rem != 0)
|
||||||
|
count = 1 << (4 - rem);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
*domain = 0;
|
*domain = 0;
|
||||||
|
string = domain;
|
||||||
|
msize = size/4;
|
||||||
|
|
||||||
for (i = msize-1; i >= 0; i -= 4)
|
for (j = (rem == 0) ? msize-1 : msize; j >= 0; j--)
|
||||||
{
|
{
|
||||||
int dig = ((unsigned char *)addr)[i>>3];
|
int dig = ((unsigned char *)addr6)[j>>1];
|
||||||
domain += sprintf(domain, "%.1x.", (i>>2) & 1 ? dig & 15 : dig >> 4);
|
|
||||||
}
|
|
||||||
domain += sprintf(domain, "ip6.arpa");
|
|
||||||
|
|
||||||
return 1;
|
dig = j & 1 ? dig & 15 : dig >> 4;
|
||||||
|
|
||||||
|
if (j == msize)
|
||||||
|
dig += i;
|
||||||
|
|
||||||
|
string += sprintf(string, "%.1x.", dig);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(string, "ip6.arpa");
|
||||||
|
|
||||||
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
||||||
|
return _("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DHCP
|
#ifdef HAVE_DHCP
|
||||||
@@ -1829,6 +1910,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
new->next = li;
|
new->next = li;
|
||||||
*up = new;
|
*up = new;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
free(path);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1995,7 +2078,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
if (!(name = canonicalise_opt(arg)) ||
|
if (!(name = canonicalise_opt(arg)) ||
|
||||||
(comma && !(target = canonicalise_opt(comma))))
|
(comma && !(target = canonicalise_opt(comma))))
|
||||||
|
{
|
||||||
|
free(name);
|
||||||
|
free(target);
|
||||||
ret_err(_("bad MX name"));
|
ret_err(_("bad MX name"));
|
||||||
|
}
|
||||||
|
|
||||||
new = opt_malloc(sizeof(struct mx_srv_record));
|
new = opt_malloc(sizeof(struct mx_srv_record));
|
||||||
new->next = daemon->mxnames;
|
new->next = daemon->mxnames;
|
||||||
@@ -2146,7 +2233,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
|
|
||||||
new = opt_malloc(sizeof(struct auth_zone));
|
new = opt_malloc(sizeof(struct auth_zone));
|
||||||
new->domain = opt_string_alloc(arg);
|
new->domain = canonicalise_opt(arg);
|
||||||
|
if (!new->domain)
|
||||||
|
ret_err_free(_("invalid auth-zone"), new);
|
||||||
new->subnet = NULL;
|
new->subnet = NULL;
|
||||||
new->exclude = NULL;
|
new->exclude = NULL;
|
||||||
new->interface_names = NULL;
|
new->interface_names = NULL;
|
||||||
@@ -2302,16 +2391,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
strlen(new->prefix) > MAXLABEL - INET_ADDRSTRLEN)
|
||||||
ret_err_free(_("bad prefix"), new);
|
ret_err_free(_("bad prefix"), new);
|
||||||
}
|
}
|
||||||
else if (strcmp(arg, "local") != 0 ||
|
else if (strcmp(arg, "local") != 0)
|
||||||
(msize != 8 && msize != 16 && msize != 24))
|
|
||||||
ret_err_free(gen_err, new);
|
ret_err_free(gen_err, new);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char domain[29]; /* strlen("xxx.yyy.zzz.ttt.in-addr.arpa")+1 */
|
|
||||||
/* local=/xxx.yyy.zzz.in-addr.arpa/ */
|
/* local=/xxx.yyy.zzz.in-addr.arpa/ */
|
||||||
/* domain_rev4 can't fail here, msize checked above. */
|
domain_rev4(0, NULL, &new->start, msize);
|
||||||
domain_rev4(domain, new->start, msize);
|
|
||||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, domain, NULL);
|
|
||||||
|
|
||||||
/* local=/<domain>/ */
|
/* local=/<domain>/ */
|
||||||
/* d_raw can't failed to canonicalise here, checked above. */
|
/* d_raw can't failed to canonicalise here, checked above. */
|
||||||
@@ -2347,15 +2432,13 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
strlen(new->prefix) > MAXLABEL - INET6_ADDRSTRLEN)
|
||||||
ret_err_free(_("bad prefix"), new);
|
ret_err_free(_("bad prefix"), new);
|
||||||
}
|
}
|
||||||
else if (strcmp(arg, "local") != 0 || ((msize & 4) != 0))
|
else if (strcmp(arg, "local") != 0)
|
||||||
ret_err_free(gen_err, new);
|
ret_err_free(gen_err, new);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
|
|
||||||
/* generate the equivalent of
|
/* generate the equivalent of
|
||||||
local=/xxx.yyy.zzz.ip6.arpa/ */
|
local=/xxx.yyy.zzz.ip6.arpa/ */
|
||||||
domain_rev6(domain, &new->start6, msize);
|
domain_rev6(0, NULL, &new->start6, msize);
|
||||||
add_update_server(SERV_LITERAL_ADDRESS, NULL, NULL, NULL, domain, NULL);
|
|
||||||
|
|
||||||
/* local=/<domain>/ */
|
/* local=/<domain>/ */
|
||||||
/* d_raw can't failed to canonicalise here, checked above. */
|
/* d_raw can't failed to canonicalise here, checked above. */
|
||||||
@@ -2436,35 +2519,44 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
case LOPT_UMBRELLA: /* --umbrella */
|
case LOPT_UMBRELLA: /* --umbrella */
|
||||||
set_option_bool(OPT_UMBRELLA);
|
set_option_bool(OPT_UMBRELLA);
|
||||||
while (arg) {
|
while (arg)
|
||||||
|
{
|
||||||
comma = split(arg);
|
comma = split(arg);
|
||||||
if (strstr(arg, "deviceid:")) {
|
if (strstr(arg, "deviceid:"))
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
u8 *u = daemon->umbrella_device;
|
||||||
|
char word[3];
|
||||||
|
|
||||||
arg += 9;
|
arg += 9;
|
||||||
if (strlen(arg) != 16)
|
if (strlen(arg) != 16)
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
for (char *p = arg; *p; p++) {
|
|
||||||
|
for (p = arg; *p; p++)
|
||||||
if (!isxdigit((int)*p))
|
if (!isxdigit((int)*p))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
}
|
|
||||||
set_option_bool(OPT_UMBRELLA_DEVID);
|
set_option_bool(OPT_UMBRELLA_DEVID);
|
||||||
|
|
||||||
u8 *u = daemon->umbrella_device;
|
for (i = 0; i < (int)sizeof(daemon->umbrella_device); i++, arg+=2)
|
||||||
char word[3];
|
{
|
||||||
for (u8 i = 0; i < sizeof(daemon->umbrella_device); i++, arg+=2) {
|
|
||||||
memcpy(word, &(arg[0]), 2);
|
memcpy(word, &(arg[0]), 2);
|
||||||
*u++ = strtoul(word, NULL, 16);
|
*u++ = strtoul(word, NULL, 16);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (strstr(arg, "orgid:")) {
|
else if (strstr(arg, "orgid:"))
|
||||||
if (!strtoul_check(arg+6, &daemon->umbrella_org)) {
|
{
|
||||||
|
if (!strtoul_check(arg+6, &daemon->umbrella_org))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
}
|
else if (strstr(arg, "assetid:"))
|
||||||
else if (strstr(arg, "assetid:")) {
|
{
|
||||||
if (!strtoul_check(arg+8, &daemon->umbrella_asset)) {
|
if (!strtoul_check(arg+8, &daemon->umbrella_asset))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
ret_err(gen_err);
|
||||||
|
|
||||||
arg = comma;
|
arg = comma;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2635,7 +2727,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
case LOPT_NO_REBIND: /* --rebind-domain-ok */
|
case LOPT_NO_REBIND: /* --rebind-domain-ok */
|
||||||
{
|
{
|
||||||
struct server *new;
|
struct rebind_domain *new;
|
||||||
|
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
|
|
||||||
@@ -2644,9 +2736,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
comma = split_chr(arg, '/');
|
comma = split_chr(arg, '/');
|
||||||
new = opt_malloc(sizeof(struct serv_local));
|
new = opt_malloc(sizeof(struct rebind_domain));
|
||||||
new->domain = opt_string_alloc(arg);
|
new->domain = canonicalise_opt(arg);
|
||||||
new->domain_len = strlen(arg);
|
|
||||||
new->next = daemon->no_rebind;
|
new->next = daemon->no_rebind;
|
||||||
daemon->no_rebind = new;
|
daemon->no_rebind = new;
|
||||||
arg = comma;
|
arg = comma;
|
||||||
@@ -2708,11 +2799,18 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
/* server=//1.2.3.4 is special. */
|
/* server=//1.2.3.4 is special. */
|
||||||
if (strlen(domain) == 0 && lastdomain)
|
if (lastdomain)
|
||||||
|
{
|
||||||
|
if (strlen(domain) == 0)
|
||||||
flags |= SERV_FOR_NODOTS;
|
flags |= SERV_FOR_NODOTS;
|
||||||
else
|
else
|
||||||
flags &= ~SERV_FOR_NODOTS;
|
flags &= ~SERV_FOR_NODOTS;
|
||||||
|
|
||||||
|
/* address=/#/ matches the same as without domain */
|
||||||
|
if (option == 'A' && domain[0] == '#' && domain[1] == 0)
|
||||||
|
domain[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr))
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, &addr))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
@@ -2729,12 +2827,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
char *string;
|
char *string;
|
||||||
int size;
|
int size;
|
||||||
u16 flags = 0;
|
|
||||||
char domain[73]; /* strlen("32*<n.>ip6.arpa")+1 */
|
|
||||||
struct in_addr addr4;
|
struct in_addr addr4;
|
||||||
struct in6_addr addr6;
|
struct in6_addr addr6;
|
||||||
union mysockaddr serv_addr, source_addr;
|
|
||||||
char interface[IF_NAMESIZE+1];
|
|
||||||
|
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
if (!arg)
|
if (!arg)
|
||||||
@@ -2743,43 +2837,52 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
comma=split(arg);
|
comma=split(arg);
|
||||||
|
|
||||||
if (!(string = split_chr(arg, '/')) || !atoi_check(string, &size))
|
if (!(string = split_chr(arg, '/')) || !atoi_check(string, &size))
|
||||||
ret_err(gen_err);
|
size = -1;
|
||||||
|
|
||||||
if (inet_pton(AF_INET, arg, &addr4))
|
if (inet_pton(AF_INET, arg, &addr4))
|
||||||
{
|
{
|
||||||
if (!domain_rev4(domain, addr4, size))
|
if (size == -1)
|
||||||
ret_err(_("bad IPv4 prefix"));
|
size = 32;
|
||||||
|
|
||||||
|
if ((string = domain_rev4(servers_only, comma, &addr4, size)))
|
||||||
|
ret_err(string);
|
||||||
}
|
}
|
||||||
else if (inet_pton(AF_INET6, arg, &addr6))
|
else if (inet_pton(AF_INET6, arg, &addr6))
|
||||||
{
|
{
|
||||||
if (!domain_rev6(domain, &addr6, size))
|
if (size == -1)
|
||||||
ret_err(_("bad IPv6 prefix"));
|
size = 128;
|
||||||
|
|
||||||
|
if ((string = domain_rev6(servers_only, comma, &addr6, size)))
|
||||||
|
ret_err(string);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
if (!comma)
|
|
||||||
flags |= SERV_LITERAL_ADDRESS;
|
|
||||||
else if ((string = parse_server(comma, &serv_addr, &source_addr, interface, &flags)))
|
|
||||||
ret_err(string);
|
|
||||||
|
|
||||||
if (servers_only)
|
|
||||||
flags |= SERV_FROM_FILE;
|
|
||||||
|
|
||||||
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
|
||||||
ret_err(gen_err);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case LOPT_IPSET: /* --ipset */
|
case LOPT_IPSET: /* --ipset */
|
||||||
|
case LOPT_NFTSET: /* --nftset */
|
||||||
#ifndef HAVE_IPSET
|
#ifndef HAVE_IPSET
|
||||||
|
if (option == LOPT_IPSET)
|
||||||
|
{
|
||||||
ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
|
ret_err(_("recompile with HAVE_IPSET defined to enable ipset directives"));
|
||||||
break;
|
break;
|
||||||
#else
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef HAVE_NFTSET
|
||||||
|
if (option == LOPT_NFTSET)
|
||||||
|
{
|
||||||
|
ret_err(_("recompile with HAVE_NFTSET defined to enable nftset directives"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
struct ipsets ipsets_head;
|
struct ipsets ipsets_head;
|
||||||
struct ipsets *ipsets = &ipsets_head;
|
struct ipsets *ipsets = &ipsets_head;
|
||||||
|
struct ipsets **daemon_sets =
|
||||||
|
(option == LOPT_IPSET) ? &daemon->ipsets : &daemon->nftsets;
|
||||||
int size;
|
int size;
|
||||||
char *end;
|
char *end;
|
||||||
char **sets, **sets_pos;
|
char **sets, **sets_pos;
|
||||||
@@ -2824,19 +2927,24 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
sets = sets_pos = opt_malloc(sizeof(char *) * size);
|
sets = sets_pos = opt_malloc(sizeof(char *) * size);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
char *p;
|
||||||
end = split(arg);
|
end = split(arg);
|
||||||
*sets_pos++ = opt_string_alloc(arg);
|
*sets_pos = opt_string_alloc(arg);
|
||||||
|
/* Use '#' to delimit table and set */
|
||||||
|
if (option == LOPT_NFTSET)
|
||||||
|
while ((p = strchr(*sets_pos, '#')))
|
||||||
|
*p = ' ';
|
||||||
|
sets_pos++;
|
||||||
arg = end;
|
arg = end;
|
||||||
} while (end);
|
} while (end);
|
||||||
*sets_pos = 0;
|
*sets_pos = 0;
|
||||||
for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
|
for (ipsets = &ipsets_head; ipsets->next; ipsets = ipsets->next)
|
||||||
ipsets->next->sets = sets;
|
ipsets->next->sets = sets;
|
||||||
ipsets->next = daemon->ipsets;
|
ipsets->next = *daemon_sets;
|
||||||
daemon->ipsets = ipsets_head.next;
|
*daemon_sets = ipsets_head.next;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
case LOPT_CMARK_ALST_EN: /* --connmark-allowlist-enable */
|
case LOPT_CMARK_ALST_EN: /* --connmark-allowlist-enable */
|
||||||
#ifndef HAVE_CONNTRACK
|
#ifndef HAVE_CONNTRACK
|
||||||
@@ -3616,6 +3724,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
inet_ntop(AF_INET, &in, daemon->addrbuff, ADDRSTRLEN);
|
inet_ntop(AF_INET, &in, daemon->addrbuff, ADDRSTRLEN);
|
||||||
sprintf(errstr, _("duplicate dhcp-host IP address %s"),
|
sprintf(errstr, _("duplicate dhcp-host IP address %s"),
|
||||||
daemon->addrbuff);
|
daemon->addrbuff);
|
||||||
|
dhcp_config_free(new);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3779,16 +3888,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
case LOPT_NAME_MATCH: /* --dhcp-name-match */
|
case LOPT_NAME_MATCH: /* --dhcp-name-match */
|
||||||
{
|
{
|
||||||
struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
|
struct dhcp_match_name *new;
|
||||||
struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
|
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
|
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
|
new = opt_malloc(sizeof(struct dhcp_match_name));
|
||||||
new->wildcard = 0;
|
new->wildcard = 0;
|
||||||
new->netid = id;
|
new->netid = opt_malloc(sizeof(struct dhcp_netid));
|
||||||
id->net = opt_string_alloc(set_prefix(arg));
|
new->netid->net = opt_string_alloc(set_prefix(arg));
|
||||||
|
|
||||||
if (comma[len-1] == '*')
|
if (comma[len-1] == '*')
|
||||||
{
|
{
|
||||||
@@ -3992,6 +4101,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dhcp_netid_free(new->netid);
|
||||||
|
free(new);
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4026,7 +4137,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case LOPT_SUBSCR: /* --dhcp-subscrid */
|
case LOPT_SUBSCR: /* --dhcp-subscrid */
|
||||||
{
|
{
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int dig = 0;
|
int dig, colon;
|
||||||
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
|
struct dhcp_vendor *new = opt_malloc(sizeof(struct dhcp_vendor));
|
||||||
|
|
||||||
if (!(comma = split(arg)))
|
if (!(comma = split(arg)))
|
||||||
@@ -4050,13 +4161,16 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
else
|
else
|
||||||
comma = arg;
|
comma = arg;
|
||||||
|
|
||||||
for (p = (unsigned char *)comma; *p; p++)
|
for (dig = 0, colon = 0, p = (unsigned char *)comma; *p; p++)
|
||||||
if (isxdigit(*p))
|
if (isxdigit(*p))
|
||||||
dig = 1;
|
dig = 1;
|
||||||
else if (*p != ':')
|
else if (*p == ':')
|
||||||
|
colon = 1;
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
|
|
||||||
unhide_metas(comma);
|
unhide_metas(comma);
|
||||||
if (option == 'U' || option == 'j' || *p || !dig)
|
if (option == 'U' || option == 'j' || *p || !dig || !colon)
|
||||||
{
|
{
|
||||||
new->len = strlen(comma);
|
new->len = strlen(comma);
|
||||||
new->data = opt_malloc(new->len);
|
new->data = opt_malloc(new->len);
|
||||||
@@ -4183,22 +4297,52 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case LOPT_RELAY: /* --dhcp-relay */
|
case LOPT_RELAY: /* --dhcp-relay */
|
||||||
{
|
{
|
||||||
struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
|
struct dhcp_relay *new = opt_malloc(sizeof(struct dhcp_relay));
|
||||||
comma = split(arg);
|
char *two = split(arg);
|
||||||
new->interface = opt_string_alloc(split(comma));
|
char *three = split(two);
|
||||||
|
|
||||||
new->iface_index = 0;
|
new->iface_index = 0;
|
||||||
if (comma && inet_pton(AF_INET, arg, &new->local) && inet_pton(AF_INET, comma, &new->server))
|
|
||||||
|
if (two)
|
||||||
{
|
{
|
||||||
|
if (inet_pton(AF_INET, arg, &new->local))
|
||||||
|
{
|
||||||
|
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;
|
new->next = daemon->relay4;
|
||||||
daemon->relay4 = new;
|
daemon->relay4 = new;
|
||||||
}
|
}
|
||||||
#ifdef HAVE_DHCP6
|
#ifdef HAVE_DHCP6
|
||||||
else if (comma && inet_pton(AF_INET6, arg, &new->local) && inet_pton(AF_INET6, comma, &new->server))
|
else if (inet_pton(AF_INET6, arg, &new->local))
|
||||||
{
|
{
|
||||||
|
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;
|
new->next = daemon->relay6;
|
||||||
daemon->relay6 = new;
|
daemon->relay6 = new;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
else
|
|
||||||
|
new->interface = opt_string_alloc(three);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!two)
|
||||||
{
|
{
|
||||||
free(new->interface);
|
free(new->interface);
|
||||||
ret_err_free(_("Bad dhcp-relay"), new);
|
ret_err_free(_("Bad dhcp-relay"), new);
|
||||||
@@ -4367,7 +4511,7 @@ err:
|
|||||||
case LOPT_CNAME: /* --cname */
|
case LOPT_CNAME: /* --cname */
|
||||||
{
|
{
|
||||||
struct cname *new;
|
struct cname *new;
|
||||||
char *alias, *target, *last, *pen;
|
char *alias, *target=NULL, *last, *pen;
|
||||||
int ttl = -1;
|
int ttl = -1;
|
||||||
|
|
||||||
for (last = pen = NULL, comma = arg; comma; comma = split(comma))
|
for (last = pen = NULL, comma = arg; comma; comma = split(comma))
|
||||||
@@ -4382,13 +4526,13 @@ err:
|
|||||||
if (pen != arg && atoi_check(last, &ttl))
|
if (pen != arg && atoi_check(last, &ttl))
|
||||||
last = pen;
|
last = pen;
|
||||||
|
|
||||||
target = canonicalise_opt(last);
|
|
||||||
|
|
||||||
while (arg != last)
|
while (arg != last)
|
||||||
{
|
{
|
||||||
int arglen = strlen(arg);
|
int arglen = strlen(arg);
|
||||||
alias = canonicalise_opt(arg);
|
alias = canonicalise_opt(arg);
|
||||||
|
|
||||||
|
if (!target)
|
||||||
|
target = canonicalise_opt(last);
|
||||||
if (!alias || !target)
|
if (!alias || !target)
|
||||||
{
|
{
|
||||||
free(target);
|
free(target);
|
||||||
@@ -4691,7 +4835,7 @@ err:
|
|||||||
struct name_list *nl;
|
struct name_list *nl;
|
||||||
if (!canon)
|
if (!canon)
|
||||||
{
|
{
|
||||||
struct name_list *tmp = new->names, *next;
|
struct name_list *tmp, *next;
|
||||||
for (tmp = new->names; tmp; tmp = next)
|
for (tmp = new->names; tmp; tmp = next)
|
||||||
{
|
{
|
||||||
next = tmp->next;
|
next = tmp->next;
|
||||||
|
|||||||
+4
-4
@@ -129,9 +129,9 @@ int is_valid_dns_name(const char *value)
|
|||||||
|
|
||||||
size_t num_bytes = 0;
|
size_t num_bytes = 0;
|
||||||
size_t num_labels = 0;
|
size_t num_labels = 0;
|
||||||
const char *label = NULL;
|
const char *c, *label = NULL;
|
||||||
int is_label_numeric = 1;
|
int is_label_numeric = 1;
|
||||||
for (const char *c = value;; c++)
|
for (c = value;; c++)
|
||||||
{
|
{
|
||||||
if (*c &&
|
if (*c &&
|
||||||
*c != '-' && *c != '.' &&
|
*c != '-' && *c != '.' &&
|
||||||
@@ -242,11 +242,11 @@ int is_valid_dns_name_pattern(const char *value)
|
|||||||
|
|
||||||
size_t num_bytes = 0;
|
size_t num_bytes = 0;
|
||||||
size_t num_labels = 0;
|
size_t num_labels = 0;
|
||||||
const char *label = NULL;
|
const char *c, *label = NULL;
|
||||||
int is_label_numeric = 1;
|
int is_label_numeric = 1;
|
||||||
size_t num_wildcards = 0;
|
size_t num_wildcards = 0;
|
||||||
int previous_label_has_wildcard = 1;
|
int previous_label_has_wildcard = 1;
|
||||||
for (const char *c = value;; c++)
|
for (c = value;; c++)
|
||||||
{
|
{
|
||||||
if (*c &&
|
if (*c &&
|
||||||
*c != '*' && /* Wildcard. */
|
*c != '*' && /* Wildcard. */
|
||||||
|
|||||||
@@ -746,6 +746,8 @@ static int add_lla(int index, unsigned int type, char *mac, size_t maclen, void
|
|||||||
add 7 to round up */
|
add 7 to round up */
|
||||||
int len = (maclen + 9) >> 3;
|
int len = (maclen + 9) >> 3;
|
||||||
unsigned char *p = expand(len << 3);
|
unsigned char *p = expand(len << 3);
|
||||||
|
if (!p)
|
||||||
|
return 1;
|
||||||
memset(p, 0, len << 3);
|
memset(p, 0, len << 3);
|
||||||
*p++ = ICMP6_OPT_SOURCE_MAC;
|
*p++ = ICMP6_OPT_SOURCE_MAC;
|
||||||
*p++ = len;
|
*p++ = len;
|
||||||
|
|||||||
+16
-10
@@ -540,8 +540,8 @@ static int print_txt(struct dns_header *header, const size_t qlen, char *name,
|
|||||||
expired and cleaned out that way.
|
expired and cleaned out that way.
|
||||||
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
|
Return 1 if we reject an address because it look like part of dns-rebinding attack. */
|
||||||
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
|
int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t now,
|
||||||
char **ipsets, int is_sign, int check_rebind, int no_cache_dnssec,
|
struct ipsets *ipsets, struct ipsets *nftsets, int is_sign, int check_rebind,
|
||||||
int secure, int *doctored)
|
int no_cache_dnssec, int secure, int *doctored)
|
||||||
{
|
{
|
||||||
unsigned char *p, *p1, *endrr, *namep;
|
unsigned char *p, *p1, *endrr, *namep;
|
||||||
int j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
int j, qtype, qclass, aqtype, aqclass, ardlen, res, searched_soa = 0;
|
||||||
@@ -551,6 +551,11 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
char **ipsets_cur;
|
char **ipsets_cur;
|
||||||
#else
|
#else
|
||||||
(void)ipsets; /* unused */
|
(void)ipsets; /* unused */
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NFTSET
|
||||||
|
char **nftsets_cur;
|
||||||
|
#else
|
||||||
|
(void)nftsets; /* unused */
|
||||||
#endif
|
#endif
|
||||||
int found = 0, cname_count = CNAME_CHAIN;
|
int found = 0, cname_count = CNAME_CHAIN;
|
||||||
struct crec *cpp = NULL;
|
struct crec *cpp = NULL;
|
||||||
@@ -843,14 +848,15 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
|
|
||||||
#ifdef HAVE_IPSET
|
#ifdef HAVE_IPSET
|
||||||
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
|
||||||
{
|
for (ipsets_cur = ipsets->sets; *ipsets_cur; ipsets_cur++)
|
||||||
ipsets_cur = ipsets;
|
if (add_to_ipset(*ipsets_cur, &addr, flags, 0) == 0)
|
||||||
while (*ipsets_cur)
|
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, ipsets->domain, &addr, *ipsets_cur, 1);
|
||||||
{
|
#endif
|
||||||
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, name, &addr, *ipsets_cur, 0);
|
#ifdef HAVE_NFTSET
|
||||||
add_to_ipset(*ipsets_cur++, &addr, flags, 0);
|
if (nftsets && (flags & (F_IPV4 | F_IPV6)))
|
||||||
}
|
for (nftsets_cur = nftsets->sets; *nftsets_cur; nftsets_cur++)
|
||||||
}
|
if (add_to_nftset(*nftsets_cur, &addr, flags, 0) == 0)
|
||||||
|
log_query((flags & (F_IPV4 | F_IPV6)) | F_IPSET, nftsets->domain, &addr, *nftsets_cur, 0);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+75
-4
@@ -2170,7 +2170,10 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
if (!relay->interface || strchr(relay->interface, '*') ||
|
if (!relay->interface || strchr(relay->interface, '*') ||
|
||||||
(multicast_iface = if_nametoindex(relay->interface)) == 0 ||
|
(multicast_iface = if_nametoindex(relay->interface)) == 0 ||
|
||||||
setsockopt(daemon->dhcp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &multicast_iface, sizeof(multicast_iface)) == -1)
|
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"));
|
{
|
||||||
|
my_syslog(MS_DHCP | LOG_ERR, _("Cannot multicast DHCP relay via interface %s"), relay->interface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
|
send_from(daemon->dhcp6fd, 0, daemon->outpacket.iov_base, save_counter(-1), &to, &from, 0);
|
||||||
@@ -2178,8 +2181,11 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
if (option_bool(OPT_LOG_OPTS))
|
if (option_bool(OPT_LOG_OPTS))
|
||||||
{
|
{
|
||||||
inet_ntop(AF_INET6, &relay->local, daemon->addrbuff, ADDRSTRLEN);
|
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);
|
inet_ntop(AF_INET6, &relay->server, daemon->namebuff, ADDRSTRLEN);
|
||||||
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay %s -> %s"), daemon->addrbuff, daemon->namebuff);
|
my_syslog(MS_DHCP | LOG_INFO, _("DHCP relay at %s -> %s"), daemon->addrbuff, daemon->namebuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save this for replies */
|
/* Save this for replies */
|
||||||
@@ -2188,7 +2194,7 @@ void relay_upstream6(struct dhcp_relay *relay, ssize_t sz,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 dhcp_relay *relay;
|
||||||
struct in6_addr link;
|
struct in6_addr link;
|
||||||
@@ -2220,11 +2226,76 @@ unsigned short relay_reply6(struct sockaddr_in6 *peer, ssize_t sz, char *arrival
|
|||||||
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
put_opt6(opt6_ptr(opt, 0), opt6_len(opt));
|
||||||
memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
|
memcpy(&peer->sin6_addr, &inbuff[18], IN6ADDRSZ);
|
||||||
peer->sin6_scope_id = relay->iface_index;
|
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;
|
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
|
#endif
|
||||||
+24
-7
@@ -156,7 +156,7 @@ 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)
|
size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
||||||
{
|
{
|
||||||
static unsigned char **rrs;
|
static unsigned char **rrs;
|
||||||
@@ -192,20 +192,37 @@ size_t rrfilter(struct dns_header *header, size_t plen, int mode)
|
|||||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||||
return plen;
|
return plen;
|
||||||
|
|
||||||
/* Don't remove the answer. */
|
if (mode == RRFILTER_EDNS0) /* EDNS */
|
||||||
if (i < ntohs(header->ancount) && type == qtype && class == qclass)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (mode == 0) /* EDNS */
|
|
||||||
{
|
{
|
||||||
/* EDNS mode, remove T_OPT from additional section only */
|
/* EDNS mode, remove T_OPT from additional section only */
|
||||||
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
|
if (i < (ntohs(header->nscount) + ntohs(header->ancount)) || type != T_OPT)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
|
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. */
|
/* DNSSEC mode, remove SIGs and NSECs from all three sections. */
|
||||||
continue;
|
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))
|
if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
|
||||||
return plen;
|
return plen;
|
||||||
|
|||||||
+12
-14
@@ -19,9 +19,9 @@
|
|||||||
#ifdef HAVE_TFTP
|
#ifdef HAVE_TFTP
|
||||||
|
|
||||||
static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len);
|
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 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 tftp_err_oops(char *packet, const char *file);
|
||||||
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
static ssize_t get_block(char *packet, struct tftp_transfer *transfer);
|
||||||
static char *next(char **p, char *end);
|
static char *next(char **p, char *end);
|
||||||
@@ -362,7 +362,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
!(mode = next(&p, end)) ||
|
!(mode = next(&p, end)) ||
|
||||||
(strcasecmp(mode, "octet") != 0 && strcasecmp(mode, "netascii") != 0))
|
(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;
|
is_err = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -472,7 +472,7 @@ void tftp_request(struct listener *listen, time_t now)
|
|||||||
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
strncat(daemon->namebuff, filename, (MAXDNAME-1) - strlen(daemon->namebuff));
|
||||||
|
|
||||||
/* check permissions and open file */
|
/* 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)
|
if ((len = get_block(packet, transfer)) == -1)
|
||||||
len = tftp_err_oops(packet, daemon->namebuff);
|
len = tftp_err_oops(packet, daemon->namebuff);
|
||||||
@@ -492,7 +492,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;
|
char *packet = daemon->packet, *namebuff = daemon->namebuff;
|
||||||
struct tftp_file *file;
|
struct tftp_file *file;
|
||||||
@@ -509,7 +509,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
|||||||
{
|
{
|
||||||
if (errno == ENOENT)
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (errno == EACCES)
|
else if (errno == EACCES)
|
||||||
@@ -562,8 +562,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
|
|||||||
return file;
|
return file;
|
||||||
|
|
||||||
perm:
|
perm:
|
||||||
errno = EACCES;
|
*len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff, strerror(EACCES));
|
||||||
*len = tftp_err(ERR_PERM, packet, _("cannot access %s: %s"), namebuff);
|
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -599,8 +598,8 @@ void check_tftp_listeners(time_t now)
|
|||||||
{
|
{
|
||||||
/* Wrong source address. See rfc1350 para 4. */
|
/* Wrong source address. See rfc1350 para 4. */
|
||||||
prettyprint_addr(&peer, daemon->addrbuff);
|
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);
|
||||||
sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer));
|
while(retry_send(sendto(transfer->sockfd, daemon->packet, len, 0, &peer.sa, sa_len(&peer))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,14 +742,13 @@ static void sanitise(char *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define MAXMESSAGE 500 /* limit to make packet < 512 bytes and definitely smaller than buffer */
|
#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 {
|
struct errmess {
|
||||||
unsigned short op, err;
|
unsigned short op, err;
|
||||||
char message[];
|
char message[];
|
||||||
} *mess = (struct errmess *)packet;
|
} *mess = (struct errmess *)packet;
|
||||||
ssize_t len, ret = 4;
|
ssize_t len, ret = 4;
|
||||||
char *errstr = strerror(errno);
|
|
||||||
|
|
||||||
memset(packet, 0, daemon->packet_buff_sz);
|
memset(packet, 0, daemon->packet_buff_sz);
|
||||||
if (file)
|
if (file)
|
||||||
@@ -758,7 +756,7 @@ static ssize_t tftp_err(int err, char *packet, char *message, char *file)
|
|||||||
|
|
||||||
mess->op = htons(OP_ERR);
|
mess->op = htons(OP_ERR);
|
||||||
mess->err = htons(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 */
|
ret += (len < MAXMESSAGE) ? len + 1 : MAXMESSAGE; /* include terminating zero */
|
||||||
|
|
||||||
if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
|
if (err != ERR_FNF || !option_bool(OPT_QUIET_TFTP))
|
||||||
@@ -772,7 +770,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 */
|
/* May have >1 refs to file, so potentially mangle a copy of the name */
|
||||||
if (file != daemon->namebuff)
|
if (file != daemon->namebuff)
|
||||||
strcpy(daemon->namebuff, file);
|
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. */
|
/* return -1 for error, zero for done. */
|
||||||
|
|||||||
+18
-13
@@ -233,8 +233,6 @@ char *canonicalise(char *in, int *nomem)
|
|||||||
{
|
{
|
||||||
# ifdef HAVE_LIBIDN2
|
# ifdef HAVE_LIBIDN2
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
rc = idn2_to_ascii_lz(in, &ret, IDN2_NONTRANSITIONAL);
|
||||||
if (rc == IDN2_DISALLOWED)
|
|
||||||
rc = idn2_to_ascii_lz(in, &ret, IDN2_TRANSITIONAL);
|
|
||||||
# else
|
# else
|
||||||
rc = idna_to_ascii_lz(in, &ret, 0);
|
rc = idna_to_ascii_lz(in, &ret, 0);
|
||||||
# endif
|
# endif
|
||||||
@@ -369,7 +367,7 @@ int sa_len(union mysockaddr *addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* don't use strcasecmp and friends here - they may be messed up by LOCALE */
|
/* 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;
|
unsigned int c1, c2;
|
||||||
|
|
||||||
@@ -382,11 +380,19 @@ int hostname_isequal(const char *a, const char *b)
|
|||||||
if (c2 >= 'A' && c2 <= 'Z')
|
if (c2 >= 'A' && c2 <= 'Z')
|
||||||
c2 += 'a' - 'A';
|
c2 += 'a' - 'A';
|
||||||
|
|
||||||
if (c1 != c2)
|
if (c1 < c2)
|
||||||
return 0;
|
return -1;
|
||||||
|
else if (c1 > c2)
|
||||||
|
return 1;
|
||||||
|
|
||||||
} while (c1);
|
} 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 */
|
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
|
||||||
@@ -430,13 +436,12 @@ int hostname_issubdomain(char *a, char *b)
|
|||||||
time_t dnsmasq_time(void)
|
time_t dnsmasq_time(void)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_BROKEN_RTC
|
#ifdef HAVE_BROKEN_RTC
|
||||||
struct tms dummy;
|
struct timespec ts;
|
||||||
static long tps = 0;
|
|
||||||
|
|
||||||
if (tps == 0)
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0)
|
||||||
tps = sysconf(_SC_CLK_TCK);
|
die(_("cannot read monotonic clock: %s"), NULL, EC_MISC);
|
||||||
|
|
||||||
return (time_t)(times(&dummy)/tps);
|
return ts.tv_sec;
|
||||||
#else
|
#else
|
||||||
return time(NULL);
|
return time(NULL);
|
||||||
#endif
|
#endif
|
||||||
@@ -550,7 +555,7 @@ void prettyprint_time(char *buf, unsigned int t)
|
|||||||
if ((x = (t/60)%60))
|
if ((x = (t/60)%60))
|
||||||
p += sprintf(&buf[p], "%um", x);
|
p += sprintf(&buf[p], "%um", x);
|
||||||
if ((x = t%60))
|
if ((x = t%60))
|
||||||
p += sprintf(&buf[p], "%us", x);
|
sprintf(&buf[p], "%us", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,7 +601,7 @@ int parse_hex(char *in, unsigned char *out, int maxlen,
|
|||||||
int j, bytes = (1 + (r - in))/2;
|
int j, bytes = (1 + (r - in))/2;
|
||||||
for (j = 0; j < bytes; j++)
|
for (j = 0; j < bytes; j++)
|
||||||
{
|
{
|
||||||
char sav = sav;
|
char sav;
|
||||||
if (j < bytes - 1)
|
if (j < bytes - 1)
|
||||||
{
|
{
|
||||||
sav = in[(j+1)*2];
|
sav = in[(j+1)*2];
|
||||||
|
|||||||
Reference in new issue
Block a user