Compare commits
45 Commits
v2.80test3
...
v2.80
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91421cb757 | ||
|
|
53792c934c | ||
|
|
df071825f2 | ||
|
|
e1791f36ea | ||
|
|
0fdf3c1f61 | ||
|
|
ee1df06aab | ||
|
|
1e87eba424 | ||
|
|
08933475ab | ||
|
|
7cbf497da4 | ||
|
|
3a610a007f | ||
|
|
48b090cb5c | ||
|
|
4139298d28 | ||
|
|
51cc10fa54 | ||
|
|
ea6cc33804 | ||
|
|
ad03967ee4 | ||
|
|
f4fd07d303 | ||
|
|
e3c08a34a7 | ||
|
|
118011fe2b | ||
|
|
af3bd07355 | ||
|
|
d68209978a | ||
|
|
47b45b2967 | ||
|
|
2b38e3823b | ||
|
|
282eab7952 | ||
|
|
c346f61535 | ||
|
|
03212e533b | ||
|
|
da8b6517de | ||
|
|
c5db8f93ec | ||
|
|
974a6d087a | ||
|
|
b758b67c37 | ||
|
|
9bafdc62b7 | ||
|
|
97f876b64c | ||
|
|
cbfbd173c4 | ||
|
|
b6f926fbef | ||
|
|
c822620967 | ||
|
|
397c0502e2 | ||
|
|
1682d15a74 | ||
|
|
dd33e98da0 | ||
|
|
c16d966ad3 | ||
|
|
1dfed16071 | ||
|
|
6f835ed6c8 | ||
|
|
9d6fd1727e | ||
|
|
8c1b6a5fd7 | ||
|
|
8dcdb33be9 | ||
|
|
aba8bbb6e3 | ||
|
|
caf4d571e6 |
26
CHANGELOG
26
CHANGELOG
@@ -41,7 +41,33 @@ version 2.80
|
||||
Fix missing fatal errors with some malformed options
|
||||
(server, local, address, rebind-domain-ok, ipset, alias).
|
||||
Thanks to Eugene Lozovoy for spotting the problem.
|
||||
|
||||
Fix crash on startup with a --synth-domain which has no prefix.
|
||||
Introduced in 2.79. Thanks to Andreas Engel for the bug report.
|
||||
|
||||
Fix missing EDNS0 section in some replies generated by local
|
||||
DNS configuration which confused systemd-resolvd. Thanks to
|
||||
Steve Dodd for characterising the problem.
|
||||
|
||||
Add --dhcp-name-match config option.
|
||||
|
||||
Add --caa-record config option.
|
||||
|
||||
Implement --address=/example.com/# as (more efficient) syntactic
|
||||
sugar for --address=/example.com/0.0.0.0 and
|
||||
--address=/example.com/::
|
||||
Returning null addresses is a useful technique for ad-blocking.
|
||||
Thanks to Peter Russell for the suggestion.
|
||||
|
||||
Change anti cache-snooping behaviour with queries with the
|
||||
recursion-desired bit unset. Instead to returning SERVFAIL, we
|
||||
now always forward, and never answer from the cache. This
|
||||
allows "dig +trace" command to work.
|
||||
|
||||
Include in the example config file a formulation which
|
||||
stops DHCP clients from claiming the DNS name "wpad".
|
||||
This is a fix for the CERT Vulnerability VU#598349.
|
||||
|
||||
|
||||
version 2.79
|
||||
Fix parsing of CNAME arguments, which are confused by extra spaces.
|
||||
|
||||
7
Makefile
7
Makefile
@@ -53,6 +53,7 @@ top?=$(CURDIR)
|
||||
|
||||
dbus_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --cflags dbus-1`
|
||||
dbus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DBUS $(PKG_CONFIG) --libs dbus-1`
|
||||
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS $(PKG_CONFIG) --copy -lubox -lubus`
|
||||
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
|
||||
idn_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --libs libidn`
|
||||
idn2_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LIBIDN2 $(PKG_CONFIG) --cflags libidn2`
|
||||
@@ -76,16 +77,16 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
|
||||
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
|
||||
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
|
||||
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o \
|
||||
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o
|
||||
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o metrics.o
|
||||
|
||||
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
|
||||
dns-protocol.h radv-protocol.h ip6addr.h
|
||||
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
|
||||
|
||||
all : $(BUILDDIR)
|
||||
@cd $(BUILDDIR) && $(MAKE) \
|
||||
top="$(top)" \
|
||||
build_cflags="$(version) $(dbus_cflags) $(idn2_cflags) $(idn_cflags) $(ct_cflags) $(lua_cflags) $(nettle_cflags)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs)" \
|
||||
build_libs="$(dbus_libs) $(idn2_libs) $(idn_libs) $(ct_libs) $(lua_libs) $(sunos_libs) $(nettle_libs) $(gmp_libs) $(ubus_libs)" \
|
||||
-f $(top)/Makefile dnsmasq
|
||||
|
||||
mostly_clean :
|
||||
|
||||
@@ -11,7 +11,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
|
||||
radv.c slaac.c auth.c ipset.c domain.c \
|
||||
dnssec.c dnssec-openssl.c blockdata.c tables.c \
|
||||
loop.c inotify.c poll.c rrfilter.c edns0.c arp.c \
|
||||
crypto.c dump.c
|
||||
crypto.c dump.c ubus.c
|
||||
|
||||
LOCAL_MODULE := dnsmasq
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt
|
||||
if (p >= end - 2)
|
||||
return NULL; /* malformed packet */
|
||||
opt_len = option_len(p);
|
||||
if (p >= end - (2 + opt_len))
|
||||
if (end - p >= (2 + opt_len))
|
||||
return NULL; /* malformed packet */
|
||||
if (*p == opt && opt_len >= minsize)
|
||||
return p;
|
||||
|
||||
@@ -270,7 +270,8 @@ int main(int argc, char **argv)
|
||||
|
||||
/* This voodoo fakes up a packet coming from the correct interface, which really matters for
|
||||
a DHCP server */
|
||||
strcpy(ifr.ifr_name, argv[1]);
|
||||
strncpy(ifr.ifr_name, argv[1], sizeof(ifr.ifr_name)-1);
|
||||
ifr.ifr_name[sizeof(ifr.ifr_name)-1] = '\0';
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
|
||||
{
|
||||
perror("cannot setup interface");
|
||||
|
||||
@@ -376,9 +376,12 @@ int send_release_packet(const char* iface, struct dhcp6_packet* packet)
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
close(sock);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
close(sock);
|
||||
fprintf(stderr, "Response timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -243,6 +243,10 @@ IPv4 or IPv6 address of the lease to remove.
|
||||
Note that this function will trigger the DhcpLeaseRemoved signal and the
|
||||
configured DHCP lease script will be run with the "del" action.
|
||||
|
||||
GetMetrics
|
||||
----------
|
||||
|
||||
Returns an array with various metrics for DNS and DHCP.
|
||||
|
||||
|
||||
2. SIGNALS
|
||||
|
||||
9
debian/changelog
vendored
9
debian/changelog
vendored
@@ -1,3 +1,12 @@
|
||||
dnsmasq (2.80-1) unstable; urgency=low
|
||||
|
||||
* New upstream. (closes: #837602) (closes: #794640) (closes: #794636)
|
||||
* Close old bugs, long agp fixed. (closes: #802845) (closes: #754299)
|
||||
* Provide usr/lib/tmpfiles.d/dnsmasq.conf. (closes: #872396)
|
||||
* Run restorecon on /run/dnsmasq for SE Linux. (closes: #872397)
|
||||
|
||||
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 17 Sep 2018 23:11:25 +0000
|
||||
|
||||
dnsmasq (2.79-1) unstable; urgency=low
|
||||
|
||||
* New upstream. (closes: #888200)
|
||||
|
||||
3
debian/init
vendored
3
debian/init
vendored
@@ -127,7 +127,8 @@ start()
|
||||
mkdir /run/dnsmasq || return 2
|
||||
chown dnsmasq:nogroup /run/dnsmasq || return 2
|
||||
fi
|
||||
|
||||
[ -x /sbin/restorecon ] && /sbin/restorecon /run/dnsmasq
|
||||
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON --test > /dev/null || return 1
|
||||
start-stop-daemon --start --quiet --pidfile /run/dnsmasq/$NAME.pid --exec $DAEMON -- \
|
||||
-x /run/dnsmasq/$NAME.pid \
|
||||
|
||||
2
debian/rules
vendored
2
debian/rules
vendored
@@ -169,6 +169,7 @@ binary-indep: checkroot
|
||||
-d debian/trees/daemon/usr/share/dnsmasq \
|
||||
-d debian/trees/daemon/etc/default \
|
||||
-d debian/trees/daemon/lib/systemd/system \
|
||||
-d debian/trees/daemon/usr/lib/tmpfiles.d \
|
||||
-d debian/trees/daemon/etc/insserv.conf.d
|
||||
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
|
||||
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
|
||||
@@ -180,6 +181,7 @@ binary-indep: checkroot
|
||||
install -m 644 dnsmasq.conf.example debian/trees/daemon/etc/dnsmasq.conf
|
||||
install -m 644 debian/readme.dnsmasq.d debian/trees/daemon/etc/dnsmasq.d/README
|
||||
install -m 644 debian/systemd.service debian/trees/daemon/lib/systemd/system/dnsmasq.service
|
||||
install -m 644 debian/tmpfiles.conf debian/trees/daemon/usr/lib/tmpfiles.d/dnsmasq.conf
|
||||
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
|
||||
ln -s $(package) debian/trees/daemon/usr/share/doc/dnsmasq
|
||||
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
|
||||
|
||||
1
debian/tmpfiles.conf
vendored
Normal file
1
debian/tmpfiles.conf
vendored
Normal file
@@ -0,0 +1 @@
|
||||
d /run/dnsmasq 755 dnsmasq nogroup
|
||||
@@ -672,3 +672,8 @@
|
||||
|
||||
# Include all files in a directory which end in .conf
|
||||
#conf-dir=/etc/dnsmasq.d/,*.conf
|
||||
|
||||
# If a DHCP client claims that its name is "wpad", ignore that.
|
||||
# This fixes a security hole. see CERT Vulnerability VU#598349
|
||||
#dhcp-name-match=set:wpad-ignore,wpad
|
||||
#dhcp-ignore-names=tag:wpad-ignore
|
||||
|
||||
@@ -27,7 +27,7 @@ TFTP server to allow net/PXE boot of DHCP hosts and also supports BOOTP. The PXE
|
||||
.PP
|
||||
The dnsmasq DHCPv6 server provides the same set of features as the
|
||||
DHCPv4 server, and in addition, it includes router advertisements and
|
||||
a neat feature which allows nameing for clients which use DHCPv4 and
|
||||
a neat feature which allows naming for clients which use DHCPv4 and
|
||||
stateless autoconfiguration only for IPv6 configuration. There is support for doing address allocation (both DHCPv6 and RA) from subnets which are dynamically delegated via DHCPv6 prefix delegation.
|
||||
.PP
|
||||
Dnsmasq is coded with small embedded systems in mind. It aims for the smallest possible memory footprint compatible with the supported functions, and allows unneeded functions to be omitted from the compiled binary.
|
||||
@@ -156,7 +156,7 @@ can be over-ridden with this switch.
|
||||
.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 default is "dip", if available, to facilitate access to
|
||||
/etc/ppp/resolv.conf which is not normally world readable.
|
||||
.TP
|
||||
.B \-v, --version
|
||||
@@ -231,7 +231,7 @@ options always override the others. The comments about interface labels for
|
||||
.B --listen-address
|
||||
apply here.
|
||||
.TP
|
||||
.B --auth-server=<domain>,<interface>|<ip-address>
|
||||
.B --auth-server=<domain>,[<interface>|<ip-address>...]
|
||||
Enable DNS authoritative mode for queries arriving at an interface or address. Note that the interface or address
|
||||
need not be mentioned in
|
||||
.B --interface
|
||||
@@ -244,7 +244,7 @@ specified interface. The <domain> is the "glue record". It should
|
||||
resolve in the global DNS to an A and/or AAAA record which points to
|
||||
the address dnsmasq is listening on. When an interface is specified,
|
||||
it may be qualified with "/4" or "/6" to specify only the IPv4 or IPv6
|
||||
addresses associated with the interface.
|
||||
addresses associated with the interface. Since any defined authoritative zones are also available as part of the normal recusive DNS service supplied by dnsmasq, it can make sense to have an --auth-server declaration with no interfaces or address, but simply specifying the glue record.
|
||||
.TP
|
||||
.B --local-service
|
||||
Accept DNS queries only from hosts whose address is on a local subnet,
|
||||
@@ -366,6 +366,11 @@ been built with DBus support. If the service name is given, dnsmasq
|
||||
provides service at that name, rather than the default which is
|
||||
.B uk.org.thekelleys.dnsmasq
|
||||
.TP
|
||||
.B --enable-ubus
|
||||
Enable dnsmasq UBus interface. It sends notifications via UBus on
|
||||
DHCPACK and DHCPRELEASE events. Furthermore it offers metrics.
|
||||
Requires that dnsmasq has been built with UBus support.
|
||||
.TP
|
||||
.B \-o, --strict-order
|
||||
By default, dnsmasq will send queries to any of the upstream servers
|
||||
it knows about and tries to favour servers that are known to
|
||||
@@ -505,7 +510,12 @@ upstream nameserver by a more specific \fB--server\fP directive. As for
|
||||
\fB--server\fP, one or more domains with no address returns a
|
||||
no-such-domain answer, so \fB--address=/example.com/\fP is equivalent to
|
||||
\fB--server=/example.com/\fP and returns NXDOMAIN for example.com and
|
||||
all its subdomains.
|
||||
all its subdomains. An address specified as '#' translates to the NULL
|
||||
address of 0.0.0.0 and its IPv6 equivalent of :: so
|
||||
\fB--address=/example.com/#\fP will return NULL addresses for example.com and
|
||||
its subdomains. This is partly syntactic sugar for \fB--address=/example.com/0.0.0.0\fP
|
||||
and \fB--address=/example.com/::\fP but is also more efficient than including both
|
||||
as seperate configuration lines. Note that NULL addresses normally work in the same way as localhost, so beware that clients looking up these names are likely to end up talking to themselves.
|
||||
.TP
|
||||
.B --ipset=/<domain>[/<domain>...]/<ipset>[,<ipset>...]
|
||||
Places the resolved IP addresses of queries for one or more domains in
|
||||
@@ -588,6 +598,9 @@ Return a PTR DNS record.
|
||||
.B --naptr-record=<name>,<order>,<preference>,<flags>,<service>,<regexp>[,<replacement>]
|
||||
Return an NAPTR DNS record, as specified in RFC3403.
|
||||
.TP
|
||||
.B --caa-record=<name>,<flags>,<tag>,<value>
|
||||
Return a CAA DNS record, as specified in RFC6844.
|
||||
.TP
|
||||
.B --cname=<cname>,[<cname>,]<target>[,<TTL>]
|
||||
Return a CNAME record which indicates that <cname> is really
|
||||
<target>. There are significant limitations on the target; it must be a
|
||||
@@ -814,7 +827,8 @@ authoritative zones as dnsmasq.
|
||||
.B --auth-peer=<ip-address>[,<ip-address>[,<ip-address>...]]
|
||||
Specify the addresses of secondary servers which are allowed to
|
||||
initiate zone transfer (AXFR) requests for zones for which dnsmasq is
|
||||
authoritative. If this option is not given, then AXFR requests will be
|
||||
authoritative. If this option is not given but --auth-sec-servers is,
|
||||
then AXFR requests will be
|
||||
accepted from any secondary. Specifying
|
||||
.B --auth-peer
|
||||
without
|
||||
@@ -1324,6 +1338,9 @@ The special form with vi-encap:<enterprise number> matches against
|
||||
vendor-identifying vendor classes for the specified enterprise. Please
|
||||
see RFC 3925 for more details of these rare and interesting beasts.
|
||||
.TP
|
||||
.B --dhcp-name-match=set:<tag>,<name>[*]
|
||||
Set the tag if the given name is supplied by a dhcp client. There may be a single trailing wildcard *, which has the usual meaning. Combined with dhcp-ignore or dhcp-ignore-names this gives the ability to ignore certain clients by name, or disallow certain hostnames from being claimed by a client.
|
||||
.TP
|
||||
.B --tag-if=set:<tag>[,set:<tag>[,tag:<tag>[,tag:<tag>]]]
|
||||
Perform boolean operations on tags. Any tag appearing as set:<tag> is set if
|
||||
all the tags which appear as tag:<tag> are set, (or unset when tag:!<tag> is used)
|
||||
@@ -2254,8 +2271,8 @@ secondary servers for reverse lookups.
|
||||
When dnsmasq is configured to act as an authoritative server, the
|
||||
following data is used to populate the authoritative zone.
|
||||
.PP
|
||||
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record
|
||||
, as long as the record names are in the authoritative domain.
|
||||
.B --mx-host, --srv-host, --dns-rr, --txt-record, --naptr-record, --caa-record,
|
||||
as long as the record names are in the authoritative domain.
|
||||
.PP
|
||||
.B --cname
|
||||
as long as the record name is in the authoritative domain. If the
|
||||
|
||||
79
po/de.po
79
po/de.po
@@ -9,18 +9,18 @@
|
||||
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: dnsmasq 2.77\n"
|
||||
"Project-Id-Version: dnsmasq 2.80\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
|
||||
"PO-Revision-Date: 2017-07-17 18:30+0100\n"
|
||||
"Last-Translator: Conrad Kostecki <ck@conrad-kostecki.de>\n"
|
||||
"PO-Revision-Date: 2018-09-29 00:13+0200\n"
|
||||
"Last-Translator: Conrad Kostecki <conrad@kostecki.com>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Poedit 2.0.1\n"
|
||||
"X-Generator: Poedit 2.1.1\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
#: cache.c:518
|
||||
@@ -150,7 +150,7 @@ msgstr "Konfigurationsdatei festlegen (Voreinstellung: %s)."
|
||||
|
||||
#: option.c:350
|
||||
msgid "Do NOT fork into the background: run in debug mode."
|
||||
msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus"
|
||||
msgstr "NICHT in den Hintergrund gehen: Betrieb im Debug-Modus."
|
||||
|
||||
#: option.c:351
|
||||
msgid "Do NOT forward queries with no domain part."
|
||||
@@ -166,12 +166,12 @@ msgstr "Erweitere einfache Namen in /etc/hosts mit der Domänen-Endung."
|
||||
|
||||
#: option.c:354
|
||||
msgid "Don't forward spurious DNS requests from Windows hosts."
|
||||
msgstr "'unechte' DNS-Anfragen von Windows-Rechnern nicht weiterleiten"
|
||||
msgstr "'unechte' DNS-Anfragen von Windows-Rechnern nicht weiterleiten."
|
||||
|
||||
# @Simon: I'm a bit unsure about "spurious"
|
||||
#: option.c:355
|
||||
msgid "Enable DHCP in the range given with lease duration."
|
||||
msgstr "DHCP für angegebenen Bereich und Dauer einschalten"
|
||||
msgstr "DHCP für angegebenen Bereich und Dauer einschalten."
|
||||
|
||||
#: option.c:356
|
||||
#, c-format
|
||||
@@ -314,7 +314,7 @@ msgstr "Ausgehenden Port erzwingen für DNS-Anfragen an vorgelagerte Server."
|
||||
|
||||
#: option.c:389
|
||||
msgid "Do NOT read resolv.conf."
|
||||
msgstr "resolv.conf NICHT lesen."
|
||||
msgstr "Die resolv.conf NICHT lesen."
|
||||
|
||||
#: option.c:390
|
||||
#, c-format
|
||||
@@ -323,7 +323,7 @@ msgstr "Pfad zu resolv.conf festlegen (%s voreingestellt)."
|
||||
|
||||
#: option.c:391
|
||||
msgid "Specify path to file with server= options"
|
||||
msgstr " Dateipfad mit der Option server= angeben"
|
||||
msgstr "Dateipfad mit der Option server= angeben"
|
||||
|
||||
#: option.c:392
|
||||
msgid "Specify address(es) of upstream servers with optional domains."
|
||||
@@ -376,7 +376,7 @@ msgstr "DHCP-\"vendor class\" auf Marke abbilden."
|
||||
|
||||
#: option.c:404
|
||||
msgid "Display dnsmasq version and copyright information."
|
||||
msgstr "dnsmasq-Version und Urheberrecht anzeigen."
|
||||
msgstr "DNSMasq-Version und Urheberrecht anzeigen."
|
||||
|
||||
#: option.c:405
|
||||
msgid "Translate IPv4 addresses from upstream servers."
|
||||
@@ -504,9 +504,8 @@ msgid "Export files by TFTP only from the specified subtree."
|
||||
msgstr "Nur vom festgelegten Unterbaum Dateien per TFTP exportieren."
|
||||
|
||||
#: option.c:435
|
||||
#, fuzzy
|
||||
msgid "Add client IP or hardware address to tftp-root."
|
||||
msgstr "IP-Adresse des Klienten an tftp-root anhängen."
|
||||
msgstr "IP-Adresse oder Hardware-Adresse des Klienten an tftp-root anhängen."
|
||||
|
||||
#: option.c:436
|
||||
msgid "Allow access only to files owned by the user running dnsmasq."
|
||||
@@ -517,9 +516,9 @@ msgid "Do not terminate the service if TFTP directories are inaccessible."
|
||||
msgstr "Der Dienst sollte nicht beendet werden, wenn die TFTP-Verzeichnisse nicht zugreifbar sind."
|
||||
|
||||
#: option.c:438
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "Maximum number of concurrent TFTP transfers (defaults to %s)."
|
||||
msgstr "Höchstzahl nebenläufiger TFTP-Übertragungen (%s voreingestellt)."
|
||||
msgstr "Maximale Anzahl gleichzeitiger TFTP-Übertragungen (%s voreingestellt)."
|
||||
|
||||
#: option.c:439
|
||||
msgid "Maximum MTU to use for TFTP transfers."
|
||||
@@ -675,7 +674,6 @@ msgid "Set TTL for authoritative replies"
|
||||
msgstr "Setzte TTL für autoritative Antworten"
|
||||
|
||||
#: option.c:477
|
||||
#, fuzzy
|
||||
msgid "Set authoritative zone information"
|
||||
msgstr "Setze autoritative Zoneninformationen"
|
||||
|
||||
@@ -724,9 +722,8 @@ msgid "Specify DHCPv6 prefix class"
|
||||
msgstr "Spezifiziere DHCPv6 Prefix Klasse"
|
||||
|
||||
#: option.c:491
|
||||
#, fuzzy
|
||||
msgid "Set MTU, priority, resend-interval and router-lifetime"
|
||||
msgstr "Setze Priorität, Intervall des erneuten Sendens und Router Lebenszeit"
|
||||
msgstr "Setze MTU, Priorität, Sendewiederholungsintervall und Router-Lebensdauer"
|
||||
|
||||
#: option.c:492
|
||||
msgid "Do not log routine DHCP."
|
||||
@@ -758,7 +755,7 @@ msgstr "Setzte TTL in DNS-Antworten mit DHCP-abgeleiteten Adressen."
|
||||
|
||||
#: option.c:499
|
||||
msgid "Delay DHCP replies for at least number of seconds."
|
||||
msgstr ""
|
||||
msgstr "Verzögere DHCP-Antworten für mindestens Anzahl von Sekunden."
|
||||
|
||||
#: option.c:703
|
||||
#, c-format
|
||||
@@ -781,7 +778,7 @@ msgstr "Gültige Optionen sind:\n"
|
||||
|
||||
#: option.c:754 option.c:868
|
||||
msgid "bad address"
|
||||
msgstr "Fehlerhafte Adresse."
|
||||
msgstr "Fehlerhafte Adresse"
|
||||
|
||||
#: option.c:779 option.c:783
|
||||
msgid "bad port"
|
||||
@@ -793,7 +790,7 @@ msgstr "Schnittstellenbindung nicht unterstützt"
|
||||
|
||||
#: option.c:821 option.c:856
|
||||
msgid "interface can only be specified once"
|
||||
msgstr ""
|
||||
msgstr "Schnittstelle kann nur einmal angegeben werden"
|
||||
|
||||
#: option.c:835 option.c:3809
|
||||
msgid "bad interface name"
|
||||
@@ -960,7 +957,7 @@ msgstr "Fehlerhafte DHCP-Proxy-Adresse"
|
||||
|
||||
#: option.c:3704
|
||||
msgid "Bad dhcp-relay"
|
||||
msgstr "unzulässiger dhcp-relay"
|
||||
msgstr "Uunzulässiger dhcp-relay"
|
||||
|
||||
#: option.c:3745
|
||||
msgid "bad RA-params"
|
||||
@@ -1016,7 +1013,7 @@ msgstr "unzulässige Wichtung"
|
||||
|
||||
#: option.c:4073
|
||||
msgid "Bad host-record"
|
||||
msgstr "unzulässiger host-record"
|
||||
msgstr "Unzulässiger host-record"
|
||||
|
||||
#: option.c:4097
|
||||
msgid "Bad name in host-record"
|
||||
@@ -1123,7 +1120,7 @@ msgstr "unzulässige Optionen auf der Befehlszeile: %s"
|
||||
#: option.c:4818
|
||||
#, c-format
|
||||
msgid "CNAME loop involving %s"
|
||||
msgstr ""
|
||||
msgstr "CNAME-Schleife mit %s"
|
||||
|
||||
#: option.c:4854
|
||||
#, c-format
|
||||
@@ -1178,7 +1175,7 @@ msgstr "möglichen DNS-Rebind-Angriff entdeckt: %s"
|
||||
#: forward.c:870
|
||||
#, c-format
|
||||
msgid "reducing DNS packet size for nameserver %s to %d"
|
||||
msgstr ""
|
||||
msgstr "Reduziere der DNS-Paketgröße für Nameserver %s auf %d"
|
||||
|
||||
#: forward.c:1266 forward.c:1704
|
||||
msgid "Ignoring query from non-local network"
|
||||
@@ -1204,9 +1201,9 @@ msgid "LOUD WARNING: use --bind-dynamic rather than --bind-interfaces to avoid D
|
||||
msgstr "LOUD WARNING: Es sollte --bind-dynamic anstatt --bind-interfaces benutzt werden, um DNS-Verstärkungsangriffe auf diesen Schnittstellen zu unterbinden"
|
||||
|
||||
#: network.c:1047
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "warning: using interface %s instead"
|
||||
msgstr "Warnung: %s nicht zugreifbar"
|
||||
msgstr "Warnung: Benutzer stattdessen Schnittstelle %s"
|
||||
|
||||
#: network.c:1056
|
||||
#, c-format
|
||||
@@ -1289,9 +1286,9 @@ msgid "using nameserver %s#%d"
|
||||
msgstr "Benutze Namensserver %s#%d"
|
||||
|
||||
#: network.c:1591
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "using %d more local addresses"
|
||||
msgstr "Benutze %d mehr Namensserver"
|
||||
msgstr "Benutze %d mehr lokale Adressen"
|
||||
|
||||
#: network.c:1593
|
||||
#, c-format
|
||||
@@ -1425,9 +1422,8 @@ msgid "DNSSEC validation enabled"
|
||||
msgstr "DNSSEC-Validierung aktiviert"
|
||||
|
||||
#: dnsmasq.c:775
|
||||
#, fuzzy
|
||||
msgid "DNSSEC signature timestamps not checked until receipt of SIGINT"
|
||||
msgstr "DNSSEC Signatur-Zeitstempel werden erst ab dem ersten Neuladen des Caches überprüft"
|
||||
msgstr "DNSSEC-Signatur-Zeitstempel werden erst nach Empfang von SIGINT überprüft"
|
||||
|
||||
#: dnsmasq.c:778
|
||||
msgid "DNSSEC signature timestamps not checked until system time valid"
|
||||
@@ -1549,7 +1545,7 @@ msgstr "Das TFTP-Verzeichnis %s ist nicht zugreifbar: %s"
|
||||
#: dnsmasq.c:1242
|
||||
#, c-format
|
||||
msgid "cannot create timestamp file %s: %s"
|
||||
msgstr "Kann keine timestamp-Datei %s erzeugen: %s "
|
||||
msgstr "Kann keine Zeitstempel-Datei %s erzeugen: %s"
|
||||
|
||||
#: dnsmasq.c:1326
|
||||
#, c-format
|
||||
@@ -1671,12 +1667,12 @@ msgstr "kann Lease-Datei %s nicht öffnen: %s"
|
||||
#: lease.c:175
|
||||
#, c-format
|
||||
msgid "failed to parse lease database, invalid line: %s %s %s %s ..."
|
||||
msgstr ""
|
||||
msgstr "Fehler beim Parsen der Lease-Datenbank, ungültige Zeile: %s %s %s %s ..."
|
||||
|
||||
#: lease.c:180
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "failed to read lease file %s: %s"
|
||||
msgstr "konnte %s nicht lesen: %s"
|
||||
msgstr "konnte Lease-Datei %s nicht lesen: %s"
|
||||
|
||||
#: lease.c:196
|
||||
#, c-format
|
||||
@@ -1874,7 +1870,7 @@ msgstr "Kann RFC3925-Option nicht senden: zu viele Optionen für Unternehmen Nr.
|
||||
#: rfc2131.c:2650
|
||||
#, c-format
|
||||
msgid "%u reply delay: %d"
|
||||
msgstr ""
|
||||
msgstr "%u Antwortverzögerung: %d"
|
||||
|
||||
#: netlink.c:77
|
||||
#, c-format
|
||||
@@ -2111,7 +2107,7 @@ msgstr ", Prefix veraltet"
|
||||
#: dhcp-common.c:823
|
||||
#, c-format
|
||||
msgid ", lease time "
|
||||
msgstr ", Lease Zeit"
|
||||
msgstr ", Lease Zeit "
|
||||
|
||||
#: dhcp-common.c:865
|
||||
#, c-format
|
||||
@@ -2174,14 +2170,13 @@ msgid "failed to create IPset control socket: %s"
|
||||
msgstr "konnte IPset-Kontroll-Socket nicht erzeugen: %s"
|
||||
|
||||
#: ipset.c:233
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "failed to update ipset %s: %s"
|
||||
msgstr "kann die mtime nicht auf %s aktualisieren: %s"
|
||||
msgstr "Aktualisierung von ipset %s fehlgeschlagen: %s"
|
||||
|
||||
#: dnssec.c:208
|
||||
#, fuzzy
|
||||
msgid "system time considered valid, now checking DNSSEC signature timestamps."
|
||||
msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel"
|
||||
msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel."
|
||||
|
||||
#: blockdata.c:58
|
||||
#, c-format
|
||||
@@ -2209,9 +2204,9 @@ msgid "error: cannot strlcpy table name %s"
|
||||
msgstr "Fehler: Kann den Tabellennamen %s nicht strlcpy"
|
||||
|
||||
#: tables.c:101
|
||||
#, fuzzy, c-format
|
||||
#, c-format
|
||||
msgid "IPset: error:%s"
|
||||
msgstr "DBus-Fehler: %s"
|
||||
msgstr "IPset: Fehler: %s"
|
||||
|
||||
#: tables.c:108
|
||||
msgid "info: table created"
|
||||
|
||||
30
src/auth.c
30
src/auth.c
@@ -103,7 +103,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
{
|
||||
char *name = daemon->namebuff;
|
||||
unsigned char *p, *ansp;
|
||||
int qtype, qclass;
|
||||
int qtype, qclass, rc;
|
||||
int nameoffset, axfroffset = 0;
|
||||
int q, anscount = 0, authcount = 0;
|
||||
struct crec *crecp;
|
||||
@@ -283,11 +283,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
|
||||
for (rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (!rec->issrv && hostname_isequal(name, rec->name))
|
||||
if (!rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
|
||||
if (qtype == T_MX)
|
||||
if (rc == 2 && qtype == T_MX)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<MX>");
|
||||
@@ -298,11 +298,11 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
|
||||
for (move = NULL, up = &daemon->mxnames, rec = daemon->mxnames; rec; rec = rec->next)
|
||||
if (rec->issrv && hostname_isequal(name, rec->name))
|
||||
if (rec->issrv && (rc = hostname_issubdomain(name, rec->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
|
||||
if (qtype == T_SRV)
|
||||
if (rc == 2 && qtype == T_SRV)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<SRV>");
|
||||
@@ -333,13 +333,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
|
||||
for (txt = daemon->rr; txt; txt = txt->next)
|
||||
if (hostname_isequal(name, txt->name))
|
||||
if ((rc = hostname_issubdomain(name, txt->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (txt->class == qtype)
|
||||
if (rc == 2 && txt->class == qtype)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, txt->class));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp, daemon->auth_ttl,
|
||||
NULL, txt->class, C_IN, "t", txt->len, txt->txt))
|
||||
anscount++;
|
||||
@@ -347,10 +347,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
|
||||
for (txt = daemon->txt; txt; txt = txt->next)
|
||||
if (txt->class == C_IN && hostname_isequal(name, txt->name))
|
||||
if (txt->class == C_IN && (rc = hostname_issubdomain(name, txt->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (qtype == T_TXT)
|
||||
if (rc == 2 && qtype == T_TXT)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<TXT>");
|
||||
@@ -361,10 +361,10 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
}
|
||||
|
||||
for (na = daemon->naptr; na; na = na->next)
|
||||
if (hostname_isequal(name, na->name))
|
||||
if ((rc = hostname_issubdomain(name, na->name)))
|
||||
{
|
||||
nxdomain = 0;
|
||||
if (qtype == T_NAPTR)
|
||||
if (rc == 2 && qtype == T_NAPTR)
|
||||
{
|
||||
found = 1;
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<NAPTR>");
|
||||
@@ -384,13 +384,13 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
#endif
|
||||
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(name, intr->name))
|
||||
if ((rc = hostname_issubdomain(name, intr->name)))
|
||||
{
|
||||
struct addrlist *addrlist;
|
||||
|
||||
nxdomain = 0;
|
||||
|
||||
if (flag)
|
||||
if (rc == 2 && flag)
|
||||
for (addrlist = intr->addr; addrlist; addrlist = addrlist->next)
|
||||
if (((addrlist->flags & ADDRLIST_IPV6) ? T_AAAA : T_A) == qtype &&
|
||||
(local_query || filter_zone(zone, flag, &addrlist->addr)))
|
||||
@@ -567,6 +567,8 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
||||
|
||||
goto cname_restart;
|
||||
}
|
||||
else if (cache_find_non_terminal(name, now))
|
||||
nxdomain = 0;
|
||||
|
||||
log_query(flag | F_NEG | (nxdomain ? F_NXDOMAIN : 0) | F_FORWARD | F_AUTH, name, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
struct in6_ifreq ifr6;
|
||||
|
||||
memset(&ifr6, 0, sizeof(ifr6));
|
||||
strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||||
safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||||
|
||||
ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||||
if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
||||
|
||||
193
src/cache.c
193
src/cache.c
@@ -21,10 +21,12 @@ static struct crec *cache_head = NULL, *cache_tail = NULL, **hash_table = NULL;
|
||||
static struct crec *dhcp_spare = NULL;
|
||||
#endif
|
||||
static struct crec *new_chain = NULL;
|
||||
static int cache_inserted = 0, cache_live_freed = 0, insert_error;
|
||||
static int insert_error;
|
||||
static union bigname *big_free = NULL;
|
||||
static int bignames_left, hash_size;
|
||||
|
||||
static void make_non_terminals(struct crec *source);
|
||||
|
||||
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||
static const struct {
|
||||
unsigned int type;
|
||||
@@ -68,7 +70,8 @@ static const struct {
|
||||
{ 252, "AXFR" },
|
||||
{ 253, "MAILB" },
|
||||
{ 254, "MAILA" },
|
||||
{ 255, "ANY" }
|
||||
{ 255, "ANY" },
|
||||
{ 257, "CAA" }
|
||||
};
|
||||
|
||||
static void cache_free(struct crec *crecp);
|
||||
@@ -556,7 +559,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
|
||||
|
||||
free_avail = 1; /* Must be free space now. */
|
||||
cache_scan_free(cache_get_name(new), &free_addr, now, new->flags, NULL, NULL);
|
||||
cache_live_freed++;
|
||||
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]++;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -641,13 +644,27 @@ void cache_end_insert(void)
|
||||
{
|
||||
cache_hash(new_chain);
|
||||
cache_link(new_chain);
|
||||
cache_inserted++;
|
||||
daemon->metrics[METRIC_DNS_CACHE_INSERTED]++;
|
||||
}
|
||||
new_chain = tmp;
|
||||
}
|
||||
new_chain = NULL;
|
||||
}
|
||||
|
||||
int cache_find_non_terminal(char *name, time_t now)
|
||||
{
|
||||
struct crec *crecp;
|
||||
|
||||
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
|
||||
if (!is_outdated_cname_pointer(crecp) &&
|
||||
!is_expired(now, crecp) &&
|
||||
(crecp->flags & F_FORWARD) &&
|
||||
hostname_isequal(name, cache_get_name(crecp)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsigned int prot)
|
||||
{
|
||||
struct crec *ans;
|
||||
@@ -808,7 +825,7 @@ static void add_hosts_cname(struct crec *target)
|
||||
for (a = daemon->cnames; a; a = a->next)
|
||||
if (a->alias[1] != '*' &&
|
||||
hostname_isequal(cache_get_name(target), a->target) &&
|
||||
(crec = whine_malloc(sizeof(struct crec))))
|
||||
(crec = whine_malloc(SIZEOF_POINTER_CREC)))
|
||||
{
|
||||
crec->flags = F_FORWARD | F_IMMORTAL | F_NAMEP | F_CONFIG | F_CNAME;
|
||||
crec->ttd = a->ttl;
|
||||
@@ -818,6 +835,8 @@ static void add_hosts_cname(struct crec *target)
|
||||
crec->addr.cname.uid = target->uid;
|
||||
crec->uid = UID_NONE;
|
||||
cache_hash(crec);
|
||||
make_non_terminals(crec);
|
||||
|
||||
add_hosts_cname(crec); /* handle chains */
|
||||
}
|
||||
}
|
||||
@@ -889,6 +908,7 @@ static void add_hosts_entry(struct crec *cache, struct all_addr *addr, int addrl
|
||||
cache->uid = index;
|
||||
memcpy(&cache->addr.addr, addr, addrlen);
|
||||
cache_hash(cache);
|
||||
make_non_terminals(cache);
|
||||
|
||||
/* don't need to do alias stuff for second and subsequent addresses. */
|
||||
if (!nameexists)
|
||||
@@ -1009,8 +1029,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
||||
{
|
||||
/* If set, add a version of the name with a default domain appended */
|
||||
if (option_bool(OPT_EXPAND) && domain_suffix && !fqdn &&
|
||||
(cache = whine_malloc(sizeof(struct crec) +
|
||||
strlen(canon)+2+strlen(domain_suffix)-SMALLDNAME)))
|
||||
(cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 2 + strlen(domain_suffix))))
|
||||
{
|
||||
strcpy(cache->name.sname, canon);
|
||||
strcat(cache->name.sname, ".");
|
||||
@@ -1020,7 +1039,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
||||
add_hosts_entry(cache, &addr, addrlen, index, rhash, hashsz);
|
||||
name_count++;
|
||||
}
|
||||
if ((cache = whine_malloc(sizeof(struct crec) + strlen(canon)+1-SMALLDNAME)))
|
||||
if ((cache = whine_malloc(SIZEOF_BARE_CREC + strlen(canon) + 1)))
|
||||
{
|
||||
strcpy(cache->name.sname, canon);
|
||||
cache->flags = flags;
|
||||
@@ -1059,7 +1078,8 @@ void cache_reload(void)
|
||||
struct ds_config *ds;
|
||||
#endif
|
||||
|
||||
cache_inserted = cache_live_freed = 0;
|
||||
daemon->metrics[METRIC_DNS_CACHE_INSERTED] = 0;
|
||||
daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED] = 0;
|
||||
|
||||
for (i=0; i<hash_size; i++)
|
||||
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
|
||||
@@ -1092,7 +1112,7 @@ void cache_reload(void)
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (a->alias[1] != '*' &&
|
||||
hostname_isequal(a->target, intr->name) &&
|
||||
((cache = whine_malloc(sizeof(struct crec)))))
|
||||
((cache = whine_malloc(SIZEOF_POINTER_CREC))))
|
||||
{
|
||||
cache->flags = F_FORWARD | F_NAMEP | F_CNAME | F_IMMORTAL | F_CONFIG;
|
||||
cache->ttd = a->ttl;
|
||||
@@ -1101,12 +1121,13 @@ void cache_reload(void)
|
||||
cache->addr.cname.uid = SRC_INTERFACE;
|
||||
cache->uid = UID_NONE;
|
||||
cache_hash(cache);
|
||||
make_non_terminals(cache);
|
||||
add_hosts_cname(cache); /* handle chains */
|
||||
}
|
||||
|
||||
#ifdef HAVE_DNSSEC
|
||||
for (ds = daemon->ds; ds; ds = ds->next)
|
||||
if ((cache = whine_malloc(sizeof(struct crec))) &&
|
||||
if ((cache = whine_malloc(SIZEOF_POINTER_CREC)) &&
|
||||
(cache->addr.ds.keydata = blockdata_alloc(ds->digest, ds->digestlen)))
|
||||
{
|
||||
cache->flags = F_FORWARD | F_IMMORTAL | F_DS | F_CONFIG | F_NAMEP;
|
||||
@@ -1118,6 +1139,7 @@ void cache_reload(void)
|
||||
cache->addr.ds.digest = ds->digest_type;
|
||||
cache->uid = ds->class;
|
||||
cache_hash(cache);
|
||||
make_non_terminals(cache);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1132,7 +1154,7 @@ void cache_reload(void)
|
||||
for (nl = hr->names; nl; nl = nl->next)
|
||||
{
|
||||
if (hr->addr.s_addr != 0 &&
|
||||
(cache = whine_malloc(sizeof(struct crec))))
|
||||
(cache = whine_malloc(SIZEOF_POINTER_CREC)))
|
||||
{
|
||||
cache->name.namep = nl->name;
|
||||
cache->ttd = hr->ttl;
|
||||
@@ -1141,7 +1163,7 @@ void cache_reload(void)
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
if (!IN6_IS_ADDR_UNSPECIFIED(&hr->addr6) &&
|
||||
(cache = whine_malloc(sizeof(struct crec))))
|
||||
(cache = whine_malloc(SIZEOF_POINTER_CREC)))
|
||||
{
|
||||
cache->name.namep = nl->name;
|
||||
cache->ttd = hr->ttl;
|
||||
@@ -1218,7 +1240,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
if ((aliasc = dhcp_spare))
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
else /* need new one */
|
||||
aliasc = whine_malloc(sizeof(struct crec));
|
||||
aliasc = whine_malloc(SIZEOF_POINTER_CREC);
|
||||
|
||||
if (aliasc)
|
||||
{
|
||||
@@ -1233,6 +1255,7 @@ static void add_dhcp_cname(struct crec *target, time_t ttd)
|
||||
aliasc->addr.cname.uid = target->uid;
|
||||
aliasc->uid = UID_NONE;
|
||||
cache_hash(aliasc);
|
||||
make_non_terminals(aliasc);
|
||||
add_dhcp_cname(aliasc, ttd);
|
||||
}
|
||||
}
|
||||
@@ -1308,7 +1331,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
if ((crec = dhcp_spare))
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
else /* need new one */
|
||||
crec = whine_malloc(sizeof(struct crec));
|
||||
crec = whine_malloc(SIZEOF_POINTER_CREC);
|
||||
|
||||
if (crec) /* malloc may fail */
|
||||
{
|
||||
@@ -1321,12 +1344,106 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
||||
crec->name.namep = host_name;
|
||||
crec->uid = UID_NONE;
|
||||
cache_hash(crec);
|
||||
make_non_terminals(crec);
|
||||
|
||||
add_dhcp_cname(crec, ttd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Called when we put a local or DHCP name into the cache.
|
||||
Creates empty cache entries for subnames (ie,
|
||||
for three.two.one, for two.one and one), without
|
||||
F_IPV4 or F_IPV6 or F_CNAME set. These convert
|
||||
NXDOMAIN answers to NoData ones. */
|
||||
static void make_non_terminals(struct crec *source)
|
||||
{
|
||||
char *name = cache_get_name(source);
|
||||
struct crec *crecp, *tmp, **up;
|
||||
int type = F_HOSTS | F_CONFIG;
|
||||
#ifdef HAVE_DHCP
|
||||
if (source->flags & F_DHCP)
|
||||
type = F_DHCP;
|
||||
#endif
|
||||
|
||||
/* First delete any empty entries for our new real name. Note that
|
||||
we only delete empty entries deriving from DHCP for a new DHCP-derived
|
||||
entry and vice-versa for HOSTS and CONFIG. This ensures that
|
||||
non-terminals from DHCP go when we reload DHCP and
|
||||
for HOSTS/CONFIG when we re-read. */
|
||||
for (up = hash_bucket(name), crecp = *up; crecp; crecp = tmp)
|
||||
{
|
||||
tmp = crecp->hash_next;
|
||||
|
||||
if (!is_outdated_cname_pointer(crecp) &&
|
||||
(crecp->flags & F_FORWARD) &&
|
||||
(crecp->flags & type) &&
|
||||
!(crecp->flags & (F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS)) &&
|
||||
hostname_isequal(name, cache_get_name(crecp)))
|
||||
{
|
||||
*up = crecp->hash_next;
|
||||
#ifdef HAVE_DHCP
|
||||
if (type & F_DHCP)
|
||||
{
|
||||
crecp->next = dhcp_spare;
|
||||
dhcp_spare = crecp;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
free(crecp);
|
||||
break;
|
||||
}
|
||||
else
|
||||
up = &crecp->hash_next;
|
||||
}
|
||||
|
||||
while ((name = strchr(name, '.')))
|
||||
{
|
||||
name++;
|
||||
|
||||
/* Look for one existing, don't need another */
|
||||
for (crecp = *hash_bucket(name); crecp; crecp = crecp->hash_next)
|
||||
if (!is_outdated_cname_pointer(crecp) &&
|
||||
(crecp->flags & F_FORWARD) &&
|
||||
(crecp->flags & type) &&
|
||||
hostname_isequal(name, cache_get_name(crecp)))
|
||||
break;
|
||||
|
||||
if (crecp)
|
||||
{
|
||||
/* If the new name expires later, transfer that time to
|
||||
empty non-terminal entry. */
|
||||
if (!(crecp->flags & F_IMMORTAL))
|
||||
{
|
||||
if (source->flags & F_IMMORTAL)
|
||||
crecp->flags |= F_IMMORTAL;
|
||||
else if (difftime(crecp->ttd, source->ttd) < 0)
|
||||
crecp->ttd = source->ttd;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if ((source->flags & F_DHCP) && dhcp_spare)
|
||||
{
|
||||
crecp = dhcp_spare;
|
||||
dhcp_spare = dhcp_spare->next;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
crecp = whine_malloc(SIZEOF_POINTER_CREC);
|
||||
|
||||
if (crecp)
|
||||
{
|
||||
crecp->flags = (source->flags | F_NAMEP) & ~(F_IPV4 | F_IPV6 | F_CNAME | F_DNSKEY | F_DS | F_REVERSE);
|
||||
crecp->ttd = source->ttd;
|
||||
crecp->name.namep = name;
|
||||
|
||||
cache_hash(crecp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NO_ID
|
||||
int cache_make_stat(struct txt_record *t)
|
||||
{
|
||||
@@ -1348,24 +1465,24 @@ int cache_make_stat(struct txt_record *t)
|
||||
break;
|
||||
|
||||
case TXT_STAT_INSERTS:
|
||||
sprintf(buff+1, "%d", cache_inserted);
|
||||
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
|
||||
break;
|
||||
|
||||
case TXT_STAT_EVICTIONS:
|
||||
sprintf(buff+1, "%d", cache_live_freed);
|
||||
sprintf(buff+1, "%d", daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED]);
|
||||
break;
|
||||
|
||||
case TXT_STAT_MISSES:
|
||||
sprintf(buff+1, "%u", daemon->queries_forwarded);
|
||||
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]);
|
||||
break;
|
||||
|
||||
case TXT_STAT_HITS:
|
||||
sprintf(buff+1, "%u", daemon->local_answer);
|
||||
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
|
||||
break;
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
case TXT_STAT_AUTH:
|
||||
sprintf(buff+1, "%u", daemon->auth_answer);
|
||||
sprintf(buff+1, "%u", daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@@ -1442,15 +1559,14 @@ static char *sanitise(char *name)
|
||||
void dump_cache(time_t now)
|
||||
{
|
||||
struct server *serv, *serv1;
|
||||
char *t = "";
|
||||
|
||||
my_syslog(LOG_INFO, _("time %lu"), (unsigned long)now);
|
||||
my_syslog(LOG_INFO, _("cache size %d, %d/%d cache insertions re-used unexpired cache entries."),
|
||||
daemon->cachesize, cache_live_freed, cache_inserted);
|
||||
daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
|
||||
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
|
||||
daemon->queries_forwarded, daemon->local_answer);
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
|
||||
#ifdef HAVE_AUTH
|
||||
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->auth_answer);
|
||||
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
||||
#endif
|
||||
#ifdef HAVE_DNSSEC
|
||||
blockdata_report();
|
||||
@@ -1488,6 +1604,7 @@ void dump_cache(time_t now)
|
||||
for (i=0; i<hash_size; i++)
|
||||
for (cache = hash_table[i]; cache; cache = cache->hash_next)
|
||||
{
|
||||
char *t = " ";
|
||||
char *a = daemon->addrbuff, *p = daemon->namebuff, *n = cache_get_name(cache);
|
||||
*a = 0;
|
||||
if (strlen(n) == 0 && !(cache->flags & F_REVERSE))
|
||||
@@ -1588,9 +1705,13 @@ char *querystr(char *desc, unsigned short type)
|
||||
break;
|
||||
}
|
||||
|
||||
len += 3; /* braces, terminator */
|
||||
len += strlen(desc);
|
||||
|
||||
if (desc)
|
||||
{
|
||||
len += 2; /* braces */
|
||||
len += strlen(desc);
|
||||
}
|
||||
len++; /* terminator */
|
||||
|
||||
if (!buff || bufflen < len)
|
||||
{
|
||||
if (buff)
|
||||
@@ -1604,12 +1725,22 @@ char *querystr(char *desc, unsigned short type)
|
||||
|
||||
if (buff)
|
||||
{
|
||||
if (types)
|
||||
sprintf(buff, "%s[%s]", desc, types);
|
||||
if (desc)
|
||||
{
|
||||
if (types)
|
||||
sprintf(buff, "%s[%s]", desc, types);
|
||||
else
|
||||
sprintf(buff, "%s[type=%d]", desc, type);
|
||||
}
|
||||
else
|
||||
sprintf(buff, "%s[type=%d]", desc, type);
|
||||
{
|
||||
if (types)
|
||||
sprintf(buff, "<%s>", types);
|
||||
else
|
||||
sprintf(buff, "type=%d", type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return buff ? buff : "";
|
||||
}
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@ HAVE_DBUS
|
||||
support some methods to allow (re)configuration of the upstream DNS
|
||||
servers via DBus.
|
||||
|
||||
HAVE_UBUS
|
||||
define this if you want to link against libubus
|
||||
|
||||
HAVE_IDN
|
||||
define this if you want international domain name 2003 support.
|
||||
|
||||
|
||||
31
src/dbus.c
31
src/dbus.c
@@ -85,6 +85,9 @@ const char* introspection_xml_template =
|
||||
" <arg name=\"success\" type=\"b\" direction=\"out\"/>\n"
|
||||
" </method>\n"
|
||||
#endif
|
||||
" <method name=\"GetMetrics\">\n"
|
||||
" <arg name=\"metrics\" direction=\"out\" type=\"a{su}\"/>\n"
|
||||
" </method>\n"
|
||||
" </interface>\n"
|
||||
"</node>\n";
|
||||
|
||||
@@ -613,6 +616,30 @@ static DBusMessage *dbus_del_lease(DBusMessage* message)
|
||||
}
|
||||
#endif
|
||||
|
||||
static DBusMessage *dbus_get_metrics(DBusMessage* message)
|
||||
{
|
||||
DBusMessage *reply = dbus_message_new_method_return(message);
|
||||
DBusMessageIter array, dict, iter;
|
||||
int i;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{su}", &array);
|
||||
|
||||
for (i = 0; i < __METRIC_MAX; i++) {
|
||||
const char *key = get_metric_name(i);
|
||||
dbus_uint32_t value = daemon->metrics[i];
|
||||
|
||||
dbus_message_iter_open_container(&array, DBUS_TYPE_DICT_ENTRY, NULL, &dict);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &key);
|
||||
dbus_message_iter_append_basic(&dict, DBUS_TYPE_UINT32, &value);
|
||||
dbus_message_iter_close_container(&array, &dict);
|
||||
}
|
||||
|
||||
dbus_message_iter_close_container(&iter, &array);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
@@ -680,6 +707,10 @@ DBusHandlerResult message_handler(DBusConnection *connection,
|
||||
reply = dbus_del_lease(message);
|
||||
}
|
||||
#endif
|
||||
else if (strcmp(method, "GetMetrics") == 0)
|
||||
{
|
||||
reply = dbus_get_metrics(message);
|
||||
}
|
||||
else if (strcmp(method, "ClearCache") == 0)
|
||||
clear_cache = 1;
|
||||
else
|
||||
|
||||
@@ -485,8 +485,11 @@ char *whichdevice(void)
|
||||
|
||||
void bindtodevice(char *device, int fd)
|
||||
{
|
||||
size_t len = strlen(device)+1;
|
||||
if (len > IFNAMSIZ)
|
||||
len = IFNAMSIZ;
|
||||
/* only allowed by root. */
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, IFNAMSIZ) == -1 &&
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, device, len) == -1 &&
|
||||
errno != EPERM)
|
||||
die(_("failed to set SO_BINDTODEVICE on DHCP socket: %s"), NULL, EC_BADNET);
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
/* ARP fiddling uses original interface even if we pretend to use a different one. */
|
||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
||||
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
||||
#endif
|
||||
|
||||
/* If the interface on which the DHCP request was received is an
|
||||
@@ -255,7 +255,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(ifr.ifr_name, bridge->iface, IF_NAMESIZE);
|
||||
safe_strncpy(ifr.ifr_name, bridge->iface, sizeof(ifr.ifr_name));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -279,7 +279,7 @@ void dhcp_packet(time_t now, int pxe_fd)
|
||||
is_relay_reply = 1;
|
||||
iov.iov_len = sz;
|
||||
#ifdef HAVE_LINUX_NETWORK
|
||||
strncpy(arp_req.arp_dev, ifr.ifr_name, 16);
|
||||
safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -988,8 +988,7 @@ char *host_from_dns(struct in_addr addr)
|
||||
if (!legal_hostname(hostname))
|
||||
return NULL;
|
||||
|
||||
strncpy(daemon->dhcp_buff, hostname, 256);
|
||||
daemon->dhcp_buff[255] = 0;
|
||||
safe_strncpy(daemon->dhcp_buff, hostname, 256);
|
||||
strip_hostname(daemon->dhcp_buff);
|
||||
|
||||
return daemon->dhcp_buff;
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#define T_AXFR 252
|
||||
#define T_MAILB 253
|
||||
#define T_ANY 255
|
||||
#define T_CAA 257
|
||||
|
||||
#define EDNS0_OPTION_MAC 65001 /* dyndns.org temporary assignment */
|
||||
#define EDNS0_OPTION_CLIENT_SUBNET 8 /* IANA */
|
||||
|
||||
@@ -216,7 +216,7 @@ int main (int argc, char **argv)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AUTH
|
||||
if (daemon->authserver)
|
||||
if (daemon->auth_zones)
|
||||
die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
@@ -225,18 +225,30 @@ int main (int argc, char **argv)
|
||||
die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UBUS
|
||||
if (option_bool(OPT_UBUS))
|
||||
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
|
||||
#endif
|
||||
|
||||
if (daemon->max_port < daemon->min_port)
|
||||
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
||||
|
||||
now = dnsmasq_time();
|
||||
|
||||
/* Create a serial at startup if not configured. */
|
||||
if (daemon->authinterface && daemon->soa_sn == 0)
|
||||
if (daemon->auth_zones)
|
||||
{
|
||||
if (!daemon->authserver)
|
||||
die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
|
||||
|
||||
/* Create a serial at startup if not configured. */
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
|
||||
if (daemon->soa_sn == 0)
|
||||
die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
|
||||
#else
|
||||
daemon->soa_sn = now;
|
||||
if (daemon->soa_sn == 0)
|
||||
daemon->soa_sn = now;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DHCP6
|
||||
if (daemon->dhcp6)
|
||||
@@ -947,8 +959,13 @@ int main (int argc, char **argv)
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
set_dbus_listeners();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_UBUS
|
||||
if (option_bool(OPT_UBUS))
|
||||
set_ubus_listeners();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DHCP
|
||||
if (daemon->dhcp || daemon->relay4)
|
||||
{
|
||||
@@ -1078,7 +1095,12 @@ int main (int argc, char **argv)
|
||||
}
|
||||
check_dbus_listeners();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_UBUS
|
||||
if (option_bool(OPT_UBUS))
|
||||
check_ubus_listeners();
|
||||
#endif
|
||||
|
||||
check_dns_listeners(now);
|
||||
|
||||
#ifdef HAVE_TFTP
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
# define __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
#if (defined(__GNUC__) && __GNUC__ >= 3) || defined(__clang__)
|
||||
#define ATTRIBUTE_NORETURN __attribute__ ((noreturn))
|
||||
#else
|
||||
#define ATTRIBUTE_NORETURN
|
||||
#endif
|
||||
|
||||
/* get these before config.h for IPv6 stuff... */
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -57,6 +63,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "ip6addr.h"
|
||||
#include "metrics.h"
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
@@ -254,7 +261,8 @@ struct event_desc {
|
||||
#define OPT_MAC_HEX 55
|
||||
#define OPT_TFTP_APREF_MAC 56
|
||||
#define OPT_RAPID_COMMIT 57
|
||||
#define OPT_LAST 58
|
||||
#define OPT_UBUS 58
|
||||
#define OPT_LAST 59
|
||||
|
||||
/* extra flags for my_syslog, we use a couple of facilities since they are known
|
||||
not to occupy the same bits as priorities, no matter how syslog.h is set up. */
|
||||
@@ -434,6 +442,9 @@ struct crec {
|
||||
} name;
|
||||
};
|
||||
|
||||
#define SIZEOF_BARE_CREC (sizeof(struct crec) - SMALLDNAME)
|
||||
#define SIZEOF_POINTER_CREC (sizeof(struct crec) + sizeof(char *) - SMALLDNAME)
|
||||
|
||||
#define F_IMMORTAL (1u<<0)
|
||||
#define F_NAMEP (1u<<1)
|
||||
#define F_REVERSE (1u<<2)
|
||||
@@ -820,6 +831,13 @@ struct dhcp_boot {
|
||||
struct dhcp_boot *next;
|
||||
};
|
||||
|
||||
struct dhcp_match_name {
|
||||
char *name;
|
||||
int wildcard;
|
||||
struct dhcp_netid *netid;
|
||||
struct dhcp_match_name *next;
|
||||
};
|
||||
|
||||
struct pxe_service {
|
||||
unsigned short CSA, type;
|
||||
char *menu, *basename, *sname;
|
||||
@@ -1012,6 +1030,7 @@ extern struct daemon {
|
||||
struct ra_interface *ra_interfaces;
|
||||
struct dhcp_config *dhcp_conf;
|
||||
struct dhcp_opt *dhcp_opts, *dhcp_match, *dhcp_opts6, *dhcp_match6;
|
||||
struct dhcp_match_name *dhcp_name_match;
|
||||
struct dhcp_vendor *dhcp_vendors;
|
||||
struct dhcp_mac *dhcp_macs;
|
||||
struct dhcp_boot *boot_config;
|
||||
@@ -1040,6 +1059,7 @@ extern struct daemon {
|
||||
char *dump_file;
|
||||
int dump_mask;
|
||||
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||
u32 metrics[__METRIC_MAX];
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
struct prefix_class *prefix_classes;
|
||||
#endif
|
||||
@@ -1060,7 +1080,6 @@ extern struct daemon {
|
||||
int dnssec_no_time_check;
|
||||
int back_to_the_future;
|
||||
#endif
|
||||
unsigned int local_answer, queries_forwarded, auth_answer;
|
||||
struct frec *frec_list;
|
||||
struct serverfd *sfds;
|
||||
struct irec *interfaces;
|
||||
@@ -1125,6 +1144,7 @@ void next_uid(struct crec *crecp);
|
||||
void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg);
|
||||
char *record_source(unsigned int index);
|
||||
char *querystr(char *desc, unsigned short type);
|
||||
int cache_find_non_terminal(char *name, time_t now);
|
||||
struct crec *cache_find_by_addr(struct crec *crecp,
|
||||
struct all_addr *addr, time_t now,
|
||||
unsigned int prot);
|
||||
@@ -1207,7 +1227,7 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
|
||||
#endif
|
||||
|
||||
/* dnssec.c */
|
||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, union mysockaddr *addr, int edns_pktsz);
|
||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class, int type, int edns_pktsz);
|
||||
int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class);
|
||||
int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class,
|
||||
@@ -1235,11 +1255,13 @@ int legal_hostname(char *name);
|
||||
char *canonicalise(char *in, int *nomem);
|
||||
unsigned char *do_rfc1035_name(unsigned char *p, char *sval, char *limit);
|
||||
void *safe_malloc(size_t size);
|
||||
void safe_strncpy(char *dest, const char *src, size_t size);
|
||||
void safe_pipe(int *fd, int read_noblock);
|
||||
void *whine_malloc(size_t size);
|
||||
int sa_len(union mysockaddr *addr);
|
||||
int sockaddr_isequal(union mysockaddr *s1, union mysockaddr *s2);
|
||||
int hostname_isequal(const char *a, const char *b);
|
||||
int hostname_issubdomain(char *a, char *b);
|
||||
time_t dnsmasq_time(void);
|
||||
int netmask_length(struct in_addr mask);
|
||||
int is_same_net(struct in_addr a, struct in_addr b, struct in_addr mask);
|
||||
@@ -1263,7 +1285,7 @@ int wildcard_match(const char* wildcard, const char* match);
|
||||
int wildcard_matchn(const char* wildcard, const char* match, int num);
|
||||
|
||||
/* log.c */
|
||||
void die(char *message, char *arg1, int exit_code);
|
||||
void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN;
|
||||
int log_start(struct passwd *ent_pw, int errfd);
|
||||
int log_reopen(char *log_file);
|
||||
|
||||
@@ -1445,6 +1467,13 @@ void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* ubus.c */
|
||||
#ifdef HAVE_UBUS
|
||||
void set_ubus_listeners(void);
|
||||
void check_ubus_listeners(void);
|
||||
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface);
|
||||
#endif
|
||||
|
||||
/* ipset.c */
|
||||
#ifdef HAVE_IPSET
|
||||
void ipset_init(void);
|
||||
|
||||
20
src/dnssec.c
20
src/dnssec.c
@@ -1761,7 +1761,7 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
|
||||
unsigned char *ans_start, *p1, *p2;
|
||||
int type1, class1, rdlen1 = 0, type2, class2, rdlen2, qclass, qtype, targetidx;
|
||||
int i, j, rc;
|
||||
int i, j, rc = STAT_INSECURE;
|
||||
int secure = STAT_SECURE;
|
||||
|
||||
/* extend rr_status if necessary */
|
||||
@@ -1835,10 +1835,10 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
|
||||
|
||||
for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
|
||||
{
|
||||
if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
|
||||
return STAT_BOGUS;
|
||||
|
||||
if (!extract_name(header, plen, &p1, name, 1, 10))
|
||||
if (i != 0 && !ADD_RDLEN(header, p1, plen, rdlen1))
|
||||
return STAT_BOGUS;
|
||||
|
||||
if (!extract_name(header, plen, &p1, name, 1, 10))
|
||||
return STAT_BOGUS; /* bad packet */
|
||||
|
||||
GETSHORT(type1, p1);
|
||||
@@ -2026,19 +2026,11 @@ int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
|
||||
}
|
||||
|
||||
size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char *name, int class,
|
||||
int type, union mysockaddr *addr, int edns_pktsz)
|
||||
int type, int edns_pktsz)
|
||||
{
|
||||
unsigned char *p;
|
||||
char *types = querystr("dnssec-query", type);
|
||||
size_t ret;
|
||||
|
||||
if (addr->sa.sa_family == AF_INET)
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
|
||||
#endif
|
||||
|
||||
header->qdcount = htons(1);
|
||||
header->ancount = htons(0);
|
||||
header->nscount = htons(0);
|
||||
|
||||
141
src/forward.c
141
src/forward.c
@@ -118,6 +118,7 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
unsigned int matchlen = 0;
|
||||
struct server *serv;
|
||||
unsigned int flags = 0;
|
||||
static struct all_addr zero;
|
||||
|
||||
for (serv = daemon->servers; serv; serv=serv->next)
|
||||
if (qtype == F_DNSSECOK && !(serv->flags & SERV_DO_DNSSEC))
|
||||
@@ -129,9 +130,16 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
*type = SERV_FOR_NODOTS;
|
||||
if (serv->flags & SERV_NO_ADDR)
|
||||
flags = F_NXDOMAIN;
|
||||
else if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||
else if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||
{
|
||||
if (sflag & qtype)
|
||||
/* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
|
||||
if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
|
||||
{
|
||||
memset(&zero, 0, sizeof(zero));
|
||||
flags = qtype;
|
||||
*addrpp = &zero;
|
||||
}
|
||||
else if (sflag & qtype)
|
||||
{
|
||||
flags = sflag;
|
||||
if (serv->addr.sa.sa_family == AF_INET)
|
||||
@@ -184,7 +192,14 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
flags = F_NXDOMAIN;
|
||||
else if (serv->flags & SERV_LITERAL_ADDRESS)
|
||||
{
|
||||
if (sflag & qtype)
|
||||
/* literal address = '#' -> return all-zero address for IPv4 and IPv6 */
|
||||
if ((serv->flags & SERV_USE_RESOLV) && (qtype & (F_IPV6 | F_IPV4)))
|
||||
{
|
||||
memset(&zero, 0, sizeof(zero));
|
||||
flags = qtype;
|
||||
*addrpp = &zero;
|
||||
}
|
||||
else if (sflag & qtype)
|
||||
{
|
||||
flags = sflag;
|
||||
if (serv->addr.sa.sa_family == AF_INET)
|
||||
@@ -214,12 +229,18 @@ static unsigned int search_servers(time_t now, struct all_addr **addrpp, unsigne
|
||||
|
||||
if (flags)
|
||||
{
|
||||
int logflags = 0;
|
||||
|
||||
if (flags == F_NXDOMAIN || flags == F_NOERR)
|
||||
logflags = F_NEG | qtype;
|
||||
|
||||
log_query(logflags | flags | F_CONFIG | F_FORWARD, qdomain, *addrpp, NULL);
|
||||
if (flags == F_NXDOMAIN || flags == F_NOERR)
|
||||
log_query(flags | qtype | F_NEG | F_CONFIG | F_FORWARD, qdomain, NULL, NULL);
|
||||
else
|
||||
{
|
||||
/* handle F_IPV4 and F_IPV6 set on ANY query to 0.0.0.0/:: domain. */
|
||||
if (flags & F_IPV4)
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV6, qdomain, *addrpp, NULL);
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
log_query((flags | F_CONFIG | F_FORWARD) & ~F_IPV4, qdomain, *addrpp, NULL);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if ((*type) & SERV_USE_RESOLV)
|
||||
{
|
||||
@@ -246,9 +267,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
|
||||
void *hash = &crc;
|
||||
#endif
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
|
||||
(void)do_bit;
|
||||
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
|
||||
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||
(void)do_bit;
|
||||
|
||||
/* may be no servers available. */
|
||||
if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
|
||||
@@ -399,7 +420,6 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
struct server *firstsentto = start;
|
||||
int subnet, forwarded = 0;
|
||||
size_t edns0_len;
|
||||
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
|
||||
unsigned char *pheader;
|
||||
|
||||
/* If a query is retried, use the log_id for the retry when logging the answer. */
|
||||
@@ -554,6 +574,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
|
||||
if (udpfd != -1)
|
||||
{
|
||||
plen = setup_reply(header, plen, addrp, flags, daemon->local_ttl);
|
||||
if (oph)
|
||||
plen = add_pseudoheader(header, plen, ((unsigned char *) header) + PACKETSZ, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||
send_from(udpfd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND), (char *)header, plen, udpaddr, dst_addr, dst_iface);
|
||||
}
|
||||
|
||||
@@ -1036,7 +1058,7 @@ void reply_query(int fd, int family, time_t now)
|
||||
status = STAT_ABANDONED;
|
||||
else
|
||||
{
|
||||
int fd, type = SERV_DO_DNSSEC;
|
||||
int querytype, fd, type = SERV_DO_DNSSEC;
|
||||
struct frec *next = new->next;
|
||||
char *domain;
|
||||
|
||||
@@ -1089,15 +1111,26 @@ void reply_query(int fd, int family, time_t now)
|
||||
if (status == STAT_NEED_KEY)
|
||||
{
|
||||
new->flags |= FREC_DNSKEY_QUERY;
|
||||
nn = dnssec_generate_query(header, ((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class, T_DNSKEY, &server->addr, server->edns_pktsz);
|
||||
querytype = T_DNSKEY;
|
||||
}
|
||||
else
|
||||
{
|
||||
new->flags |= FREC_DS_QUERY;
|
||||
nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class, T_DS, &server->addr, server->edns_pktsz);
|
||||
querytype = T_DS;
|
||||
}
|
||||
|
||||
nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
|
||||
daemon->keyname, forward->class, querytype, server->edns_pktsz);
|
||||
|
||||
if (server->addr.sa.sa_family == AF_INET)
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (struct all_addr *)&(server->addr.in.sin_addr),
|
||||
querystr("dnssec-query", querytype));
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (struct all_addr *)&(server->addr.in6.sin6_addr),
|
||||
querystr("dnssec-query", querytype));
|
||||
#endif
|
||||
|
||||
if ((hash = hash_questions(header, nn, daemon->namebuff)))
|
||||
memcpy(new->hash, hash, HASH_SIZE);
|
||||
new->new_id = get_id();
|
||||
@@ -1553,7 +1586,7 @@ void receive_query(struct listener *listen, time_t now)
|
||||
{
|
||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||
daemon->auth_answer++;
|
||||
daemon->metrics[METRIC_DNS_AUTH_ANSWERED]++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1571,13 +1604,13 @@ void receive_query(struct listener *listen, time_t now)
|
||||
{
|
||||
send_from(listen->fd, option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND),
|
||||
(char *)header, m, &source_addr, &dst_addr, if_index);
|
||||
daemon->local_answer++;
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
}
|
||||
else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
|
||||
header, (size_t)n, now, NULL, ad_reqd, do_bit))
|
||||
daemon->queries_forwarded++;
|
||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED]++;
|
||||
else
|
||||
daemon->local_answer++;
|
||||
daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1631,9 +1664,9 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
new_status = STAT_ABANDONED;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
m = dnssec_generate_query(new_header, ((unsigned char *) new_header) + 65536, keyname, class,
|
||||
new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, &server->addr, server->edns_pktsz);
|
||||
new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS, server->edns_pktsz);
|
||||
|
||||
*length = htons(m);
|
||||
|
||||
@@ -1666,30 +1699,30 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
|
||||
(server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
|
||||
continue;
|
||||
|
||||
retry:
|
||||
/* may need to make new connection. */
|
||||
if (server->tcpfd == -1)
|
||||
{
|
||||
if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
|
||||
continue; /* No good, next server */
|
||||
|
||||
|
||||
retry:
|
||||
/* may need to make new connection. */
|
||||
if (server->tcpfd == -1)
|
||||
{
|
||||
if ((server->tcpfd = socket(server->addr.sa.sa_family, SOCK_STREAM, 0)) == -1)
|
||||
continue; /* No good, next server */
|
||||
|
||||
#ifdef HAVE_CONNTRACK
|
||||
/* Copy connection mark of incoming query to outgoing connection. */
|
||||
if (have_mark)
|
||||
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
||||
/* Copy connection mark of incoming query to outgoing connection. */
|
||||
if (have_mark)
|
||||
setsockopt(server->tcpfd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
|
||||
#endif
|
||||
|
||||
if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1) ||
|
||||
connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
|
||||
{
|
||||
close(server->tcpfd);
|
||||
server->tcpfd = -1;
|
||||
continue; /* No good, next server */
|
||||
}
|
||||
|
||||
server->flags &= ~SERV_GOT_TCP;
|
||||
}
|
||||
|
||||
if (!local_bind(server->tcpfd, &server->source_addr, server->interface, 0, 1) ||
|
||||
connect(server->tcpfd, &server->addr.sa, sa_len(&server->addr)) == -1)
|
||||
{
|
||||
close(server->tcpfd);
|
||||
server->tcpfd = -1;
|
||||
continue; /* No good, next server */
|
||||
}
|
||||
|
||||
server->flags &= ~SERV_GOT_TCP;
|
||||
}
|
||||
|
||||
if (!read_write(server->tcpfd, packet, m + sizeof(u16), 0) ||
|
||||
!read_write(server->tcpfd, &c1, 1, 1) ||
|
||||
@@ -1706,6 +1739,16 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (server->addr.sa.sa_family == AF_INET)
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (struct all_addr *)&(server->addr.in.sin_addr),
|
||||
querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
|
||||
#ifdef HAVE_IPV6
|
||||
else
|
||||
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (struct all_addr *)&(server->addr.in6.sin6_addr),
|
||||
querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
|
||||
#endif
|
||||
|
||||
server->flags |= SERV_GOT_TCP;
|
||||
|
||||
@@ -2104,7 +2147,11 @@ unsigned char *tcp_request(int confd, time_t now,
|
||||
|
||||
/* In case of local answer or no connections made. */
|
||||
if (m == 0)
|
||||
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
||||
{
|
||||
m = setup_reply(header, (unsigned int)size, addrp, flags, daemon->local_ttl);
|
||||
if (have_pseudoheader)
|
||||
m = add_pseudoheader(header, m, ((unsigned char *) header) + 65536, daemon->edns_pktsz, 0, NULL, 0, do_bit, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
11
src/lease.c
11
src/lease.c
@@ -555,7 +555,9 @@ void lease_prune(struct dhcp_lease *target, time_t now)
|
||||
file_dirty = 1;
|
||||
if (lease->hostname)
|
||||
dns_dirty = 1;
|
||||
|
||||
|
||||
daemon->metrics[lease->addr.s_addr ? METRIC_LEASES_PRUNED_4 : METRIC_LEASES_PRUNED_6]++;
|
||||
|
||||
*up = lease->next; /* unlink */
|
||||
|
||||
/* Put on old_leases list 'till we
|
||||
@@ -773,7 +775,10 @@ struct dhcp_lease *lease4_allocate(struct in_addr addr)
|
||||
{
|
||||
struct dhcp_lease *lease = lease_allocate();
|
||||
if (lease)
|
||||
lease->addr = addr;
|
||||
{
|
||||
lease->addr = addr;
|
||||
daemon->metrics[METRIC_LEASES_ALLOCATED_4]++;
|
||||
}
|
||||
|
||||
return lease;
|
||||
}
|
||||
@@ -788,6 +793,8 @@ struct dhcp_lease *lease6_allocate(struct in6_addr *addrp, int lease_type)
|
||||
lease->addr6 = *addrp;
|
||||
lease->flags |= lease_type;
|
||||
lease->iaid = 0;
|
||||
|
||||
daemon->metrics[METRIC_LEASES_ALLOCATED_6]++;
|
||||
}
|
||||
|
||||
return lease;
|
||||
|
||||
@@ -232,7 +232,7 @@ static void log_write(void)
|
||||
logaddr.sun_len = sizeof(logaddr) - sizeof(logaddr.sun_path) + strlen(_PATH_LOG) + 1;
|
||||
#endif
|
||||
logaddr.sun_family = AF_UNIX;
|
||||
strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
||||
safe_strncpy(logaddr.sun_path, _PATH_LOG, sizeof(logaddr.sun_path));
|
||||
|
||||
/* Got connection back? try again. */
|
||||
if (connect(log_fd, (struct sockaddr *)&logaddr, sizeof(logaddr)) != -1)
|
||||
|
||||
44
src/metrics.c
Normal file
44
src/metrics.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
const char * metric_names[] = {
|
||||
"dns_cache_inserted",
|
||||
"dns_cache_live_freed",
|
||||
"dns_queries_forwarded",
|
||||
"dns_auth_answered",
|
||||
"dns_local_answered",
|
||||
"bootp",
|
||||
"pxe",
|
||||
"dhcp_ack",
|
||||
"dhcp_decline",
|
||||
"dhcp_discover",
|
||||
"dhcp_inform",
|
||||
"dhcp_nak",
|
||||
"dhcp_offer",
|
||||
"dhcp_release",
|
||||
"dhcp_request",
|
||||
"noanswer",
|
||||
"leases_allocated_4",
|
||||
"leases_pruned_4",
|
||||
"leases_allocated_6",
|
||||
"leases_pruned_6",
|
||||
};
|
||||
|
||||
const char* get_metric_name(int i) {
|
||||
return metric_names[i];
|
||||
}
|
||||
43
src/metrics.h
Normal file
43
src/metrics.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* If you modify this list, please keep the labels in metrics.c in sync. */
|
||||
enum {
|
||||
METRIC_DNS_CACHE_INSERTED,
|
||||
METRIC_DNS_CACHE_LIVE_FREED,
|
||||
METRIC_DNS_QUERIES_FORWARDED,
|
||||
METRIC_DNS_AUTH_ANSWERED,
|
||||
METRIC_DNS_LOCAL_ANSWERED,
|
||||
METRIC_BOOTP,
|
||||
METRIC_PXE,
|
||||
METRIC_DHCPACK,
|
||||
METRIC_DHCPDECLINE,
|
||||
METRIC_DHCPDISCOVER,
|
||||
METRIC_DHCPINFORM,
|
||||
METRIC_DHCPNAK,
|
||||
METRIC_DHCPOFFER,
|
||||
METRIC_DHCPRELEASE,
|
||||
METRIC_DHCPREQUEST,
|
||||
METRIC_NOANSWER,
|
||||
METRIC_LEASES_ALLOCATED_4,
|
||||
METRIC_LEASES_PRUNED_4,
|
||||
METRIC_LEASES_ALLOCATED_6,
|
||||
METRIC_LEASES_PRUNED_6,
|
||||
|
||||
__METRIC_MAX,
|
||||
};
|
||||
|
||||
const char* get_metric_name(int);
|
||||
@@ -149,10 +149,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||||
struct rtgenmsg g;
|
||||
} req;
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
|
||||
addr.nl_family = AF_NETLINK;
|
||||
addr.nl_pad = 0;
|
||||
addr.nl_groups = 0;
|
||||
addr.nl_pid = 0; /* address to kernel */
|
||||
|
||||
again:
|
||||
if (family == AF_UNSPEC)
|
||||
|
||||
@@ -29,7 +29,7 @@ int indextoname(int fd, int index, char *name)
|
||||
if (ioctl(fd, SIOCGIFNAME, &ifr) == -1)
|
||||
return 0;
|
||||
|
||||
strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
||||
safe_strncpy(name, ifr.ifr_name, IF_NAMESIZE);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -82,12 +82,12 @@ int indextoname(int fd, int index, char *name)
|
||||
for (i = lifc.lifc_len / sizeof(struct lifreq); i; i--, lifrp++)
|
||||
{
|
||||
struct lifreq lifr;
|
||||
strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
||||
safe_strncpy(lifr.lifr_name, lifrp->lifr_name, IF_NAMESIZE);
|
||||
if (ioctl(fd, SIOCGLIFINDEX, &lifr) < 0)
|
||||
return 0;
|
||||
|
||||
if (lifr.lifr_index == index) {
|
||||
strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
||||
safe_strncpy(name, lifr.lifr_name, IF_NAMESIZE);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ int loopback_exception(int fd, int family, struct all_addr *addr, char *name)
|
||||
struct ifreq ifr;
|
||||
struct irec *iface;
|
||||
|
||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
|
||||
ifr.ifr_flags & IFF_LOOPBACK)
|
||||
{
|
||||
@@ -1286,7 +1286,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strcpy(sfd->interface, intname);
|
||||
safe_strncpy(sfd->interface, intname, sizeof(sfd->interface));
|
||||
sfd->source_addr = *addr;
|
||||
sfd->next = daemon->sfds;
|
||||
sfd->ifindex = ifindex;
|
||||
@@ -1458,7 +1458,7 @@ void add_update_server(int flags,
|
||||
serv->flags |= SERV_HAS_DOMAIN;
|
||||
|
||||
if (interface)
|
||||
strcpy(serv->interface, interface);
|
||||
safe_strncpy(serv->interface, interface, sizeof(serv->interface));
|
||||
if (addr)
|
||||
serv->addr = *addr;
|
||||
if (source_addr)
|
||||
|
||||
160
src/option.c
160
src/option.c
@@ -163,6 +163,9 @@ struct myoption {
|
||||
#define LOPT_RAPID_COMMIT 351
|
||||
#define LOPT_DUMPFILE 352
|
||||
#define LOPT_DUMPMASK 353
|
||||
#define LOPT_UBUS 354
|
||||
#define LOPT_NAME_MATCH 355
|
||||
#define LOPT_CAA 356
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
static const struct option opts[] =
|
||||
@@ -231,8 +234,10 @@ static const struct myoption opts[] =
|
||||
{ "srv-host", 1, 0, 'W' },
|
||||
{ "localise-queries", 0, 0, 'y' },
|
||||
{ "txt-record", 1, 0, 'Y' },
|
||||
{ "caa-record", 1, 0 , LOPT_CAA },
|
||||
{ "dns-rr", 1, 0, LOPT_RR },
|
||||
{ "enable-dbus", 2, 0, '1' },
|
||||
{ "enable-ubus", 0, 0, LOPT_UBUS },
|
||||
{ "bootp-dynamic", 2, 0, '3' },
|
||||
{ "dhcp-mac", 1, 0, '4' },
|
||||
{ "no-ping", 0, 0, '5' },
|
||||
@@ -271,7 +276,8 @@ static const struct myoption opts[] =
|
||||
{ "stop-dns-rebind", 0, 0, LOPT_REBIND },
|
||||
{ "rebind-domain-ok", 1, 0, LOPT_NO_REBIND },
|
||||
{ "all-servers", 0, 0, LOPT_NOLAST },
|
||||
{ "dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{ "dhcp-match", 1, 0, LOPT_MATCH },
|
||||
{ "dhcp-name-match", 1, 0, LOPT_NAME_MATCH },
|
||||
{ "dhcp-broadcast", 2, 0, LOPT_BROADCAST },
|
||||
{ "neg-ttl", 1, 0, LOPT_NEGTTL },
|
||||
{ "max-ttl", 1, 0, LOPT_MAXTTL },
|
||||
@@ -420,6 +426,7 @@ static struct {
|
||||
{ 'z', OPT_NOWILD, NULL, gettext_noop("Bind only to interfaces in use."), NULL },
|
||||
{ 'Z', OPT_ETHERS, NULL, gettext_noop("Read DHCP static host information from %s."), ETHERSFILE },
|
||||
{ '1', ARG_ONE, "[=<busname>]", gettext_noop("Enable the DBus interface for setting upstream servers, etc."), NULL },
|
||||
{ LOPT_UBUS, OPT_UBUS, NULL, gettext_noop("Enable the UBus interface."), NULL },
|
||||
{ '2', ARG_DUP, "<interface>", gettext_noop("Do not provide DHCP on this interface, only provide DNS."), NULL },
|
||||
{ '3', ARG_DUP, "[=tag:<tag>]...", gettext_noop("Enable dynamic address allocation for bootp."), NULL },
|
||||
{ '4', ARG_DUP, "set:<tag>,<mac address>", gettext_noop("Map MAC address (with wildcards) to option set."), NULL },
|
||||
@@ -453,6 +460,7 @@ static struct {
|
||||
{ LOPT_NO_REBIND, ARG_DUP, "/<domain>/", gettext_noop("Inhibit DNS-rebind protection on this domain."), NULL },
|
||||
{ LOPT_NOLAST, OPT_ALL_SERVERS, NULL, gettext_noop("Always perform DNS queries to all servers."), NULL },
|
||||
{ LOPT_MATCH, ARG_DUP, "set:<tag>,<optspec>", gettext_noop("Set tag if client includes matching option in request."), NULL },
|
||||
{ LOPT_NAME_MATCH, ARG_DUP, "set:<tag>,<string>[*]", gettext_noop("Set tag if client provides given name."), NULL },
|
||||
{ LOPT_ALTPORT, ARG_ONE, "[=<ports>]", gettext_noop("Use alternative ports for DHCP."), NULL },
|
||||
{ LOPT_NAPTR, ARG_DUP, "<name>,<naptr>", gettext_noop("Specify NAPTR DNS record."), NULL },
|
||||
{ LOPT_MINPORT, ARG_ONE, "<port>", gettext_noop("Specify lowest port available for DNS query transmission."), NULL },
|
||||
@@ -475,6 +483,7 @@ static struct {
|
||||
{ LOPT_RA, OPT_RA, NULL, gettext_noop("Send router-advertisements for interfaces doing DHCPv6"), NULL },
|
||||
{ LOPT_DUID, ARG_ONE, "<enterprise>,<duid>", gettext_noop("Specify DUID_EN-type DHCPv6 server DUID"), NULL },
|
||||
{ LOPT_HOST_REC, ARG_DUP, "<name>,<address>[,<ttl>]", gettext_noop("Specify host (A/AAAA and PTR) records"), NULL },
|
||||
{ LOPT_CAA, ARG_DUP, "<name>,<flags>,<tag>,<value>", gettext_noop("Specify certification authority authorization record"), NULL },
|
||||
{ LOPT_RR, ARG_DUP, "<name>,<RR-number>,[<data>]", gettext_noop("Specify arbitrary DNS resource record"), NULL },
|
||||
{ LOPT_CLVERBIND, OPT_CLEVERBIND, NULL, gettext_noop("Bind to interfaces in use - check for new interfaces"), NULL },
|
||||
{ LOPT_AUTHSERV, ARG_ONE, "<NS>,<interface>", gettext_noop("Export local names to global DNS"), NULL },
|
||||
@@ -801,7 +810,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
if (interface_opt)
|
||||
{
|
||||
#if defined(SO_BINDTODEVICE)
|
||||
strncpy(interface, interface_opt, IF_NAMESIZE - 1);
|
||||
safe_strncpy(interface, interface_opt, IF_NAMESIZE);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
@@ -830,7 +839,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
return _("interface can only be specified once");
|
||||
|
||||
source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
safe_strncpy(interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
@@ -865,7 +874,7 @@ char *parse_server(char *arg, union mysockaddr *addr, union mysockaddr *source_a
|
||||
return _("interface can only be specified once");
|
||||
|
||||
source_addr->in6.sin6_addr = in6addr_any;
|
||||
strncpy(interface, source, IF_NAMESIZE - 1);
|
||||
safe_strncpy(interface, source, IF_NAMESIZE);
|
||||
#else
|
||||
return _("interface binding not supported");
|
||||
#endif
|
||||
@@ -1746,7 +1755,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 'x': /* --pid-file */
|
||||
daemon->runfile = opt_string_alloc(arg);
|
||||
break;
|
||||
@@ -1892,47 +1901,43 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_AUTH
|
||||
case LOPT_AUTHSERV: /* --auth-server */
|
||||
if (!(comma = split(arg)))
|
||||
ret_err(gen_err);
|
||||
comma = split(arg);
|
||||
|
||||
daemon->authserver = opt_string_alloc(arg);
|
||||
arg = comma;
|
||||
do {
|
||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||
comma = split(arg);
|
||||
new->name = NULL;
|
||||
unhide_metas(arg);
|
||||
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
|
||||
new->addr.sa.sa_family = AF_INET;
|
||||
|
||||
while ((arg = comma))
|
||||
{
|
||||
struct iname *new = opt_malloc(sizeof(struct iname));
|
||||
comma = split(arg);
|
||||
new->name = NULL;
|
||||
unhide_metas(arg);
|
||||
if (inet_pton(AF_INET, arg, &new->addr.in.sin_addr) > 0)
|
||||
new->addr.sa.sa_family = AF_INET;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
|
||||
new->addr.sa.sa_family = AF_INET6;
|
||||
else if (inet_pton(AF_INET6, arg, &new->addr.in6.sin6_addr) > 0)
|
||||
new->addr.sa.sa_family = AF_INET6;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
char *fam = split_chr(arg, '/');
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->addr.sa.sa_family = 0;
|
||||
if (fam)
|
||||
{
|
||||
if (strcmp(fam, "4") == 0)
|
||||
new->addr.sa.sa_family = AF_INET;
|
||||
else
|
||||
{
|
||||
char *fam = split_chr(arg, '/');
|
||||
new->name = opt_string_alloc(arg);
|
||||
new->addr.sa.sa_family = 0;
|
||||
if (fam)
|
||||
{
|
||||
if (strcmp(fam, "4") == 0)
|
||||
new->addr.sa.sa_family = AF_INET;
|
||||
#ifdef HAVE_IPV6
|
||||
else if (strcmp(fam, "6") == 0)
|
||||
new->addr.sa.sa_family = AF_INET6;
|
||||
else if (strcmp(fam, "6") == 0)
|
||||
new->addr.sa.sa_family = AF_INET6;
|
||||
#endif
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
new->next = daemon->authinterface;
|
||||
daemon->authinterface = new;
|
||||
|
||||
arg = comma;
|
||||
} while (arg);
|
||||
else
|
||||
ret_err(gen_err);
|
||||
}
|
||||
}
|
||||
new->next = daemon->authinterface;
|
||||
daemon->authinterface = new;
|
||||
};
|
||||
|
||||
break;
|
||||
|
||||
@@ -2068,7 +2073,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 's': /* --domain */
|
||||
case LOPT_SYNTH: /* --synth-domain */
|
||||
@@ -2229,7 +2233,9 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
char *star;
|
||||
new->next = daemon->synth_domains;
|
||||
daemon->synth_domains = new;
|
||||
if ((star = strrchr(new->prefix, '*')) && *(star+1) == 0)
|
||||
if (new->prefix &&
|
||||
(star = strrchr(new->prefix, '*'))
|
||||
&& *(star+1) == 0)
|
||||
{
|
||||
*star = 0;
|
||||
new->indexed = 1;
|
||||
@@ -2459,11 +2465,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
}
|
||||
|
||||
else if (strcmp(arg, "#") == 0)
|
||||
{
|
||||
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
|
||||
if (newlist->flags & SERV_LITERAL_ADDRESS)
|
||||
ret_err(gen_err);
|
||||
}
|
||||
newlist->flags |= SERV_USE_RESOLV; /* treat in ordinary way */
|
||||
else
|
||||
{
|
||||
char *err = parse_server(arg, &newlist->addr, &newlist->source_addr, newlist->interface, &newlist->flags);
|
||||
@@ -3284,7 +3286,33 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
||||
option == LOPT_FORCE ? DHOPT_FORCE :
|
||||
(option == LOPT_MATCH ? DHOPT_MATCH :
|
||||
(option == LOPT_OPTS ? DHOPT_BANK : 0)));
|
||||
|
||||
|
||||
case LOPT_NAME_MATCH: /* --dhcp-name-match */
|
||||
{
|
||||
struct dhcp_match_name *new = opt_malloc(sizeof(struct dhcp_match_name));
|
||||
struct dhcp_netid *id = opt_malloc(sizeof(struct dhcp_netid));
|
||||
ssize_t len;
|
||||
|
||||
if (!(comma = split(arg)) || (len = strlen(comma)) == 0)
|
||||
ret_err(gen_err);
|
||||
|
||||
new->wildcard = 0;
|
||||
new->netid = id;
|
||||
id->net = opt_string_alloc(set_prefix(arg));
|
||||
|
||||
if (comma[len-1] == '*')
|
||||
{
|
||||
comma[len-1] = 0;
|
||||
new->wildcard = 1;
|
||||
}
|
||||
new->name = opt_string_alloc(comma);
|
||||
|
||||
new->next = daemon->dhcp_name_match;
|
||||
daemon->dhcp_name_match = new;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'M': /* --dhcp-boot */
|
||||
{
|
||||
struct dhcp_netid *id = NULL;
|
||||
@@ -3971,7 +3999,7 @@ err:
|
||||
|
||||
if (data)
|
||||
{
|
||||
new->txt=opt_malloc(len);
|
||||
new->txt = opt_malloc(len);
|
||||
new->len = len;
|
||||
memcpy(new->txt, data, len);
|
||||
}
|
||||
@@ -3979,6 +4007,37 @@ err:
|
||||
break;
|
||||
}
|
||||
|
||||
case LOPT_CAA: /* --caa-record */
|
||||
{
|
||||
struct txt_record *new;
|
||||
char *tag, *value;
|
||||
int flags;
|
||||
|
||||
comma = split(arg);
|
||||
tag = split(comma);
|
||||
value = split(tag);
|
||||
|
||||
new = opt_malloc(sizeof(struct txt_record));
|
||||
new->next = daemon->rr;
|
||||
daemon->rr = new;
|
||||
|
||||
if (!atoi_check(comma, &flags) || !tag || !value || !(new->name = canonicalise_opt(arg)))
|
||||
ret_err(_("bad CAA record"));
|
||||
|
||||
unhide_metas(tag);
|
||||
unhide_metas(value);
|
||||
|
||||
new->len = strlen(tag) + strlen(value) + 2;
|
||||
new->txt = opt_malloc(new->len);
|
||||
new->txt[0] = flags;
|
||||
new->txt[1] = strlen(tag);
|
||||
memcpy(&new->txt[2], tag, strlen(tag));
|
||||
memcpy(&new->txt[2 + strlen(tag)], value, strlen(value));
|
||||
new->class = T_CAA;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'Y': /* --txt-record */
|
||||
{
|
||||
struct txt_record *new;
|
||||
@@ -4336,7 +4395,7 @@ static void read_file(char *file, FILE *f, int hard_opt)
|
||||
if (errmess)
|
||||
strcpy(daemon->namebuff, errmess);
|
||||
|
||||
if (errmess || !one_opt(option, arg, buff, _("error"), 0, hard_opt == LOPT_REV_SERV))
|
||||
if (errmess || !one_opt(option, arg, daemon->namebuff, _("error"), 0, hard_opt == LOPT_REV_SERV))
|
||||
{
|
||||
sprintf(daemon->namebuff + strlen(daemon->namebuff), _(" at line %d of %s"), lineno, file);
|
||||
if (hard_opt != 0)
|
||||
@@ -4740,8 +4799,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
||||
argbuf_size = strlen(optarg) + 1;
|
||||
argbuf = opt_malloc(argbuf_size);
|
||||
}
|
||||
strncpy(argbuf, optarg, argbuf_size);
|
||||
argbuf[argbuf_size-1] = 0;
|
||||
safe_strncpy(argbuf, optarg, argbuf_size);
|
||||
arg = argbuf;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -956,22 +956,26 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||
log_query(F_CONFIG | F_RCODE, "error", &a, NULL);
|
||||
SET_RCODE(header, SERVFAIL);
|
||||
}
|
||||
else if (flags == F_IPV4)
|
||||
{ /* we know the address */
|
||||
SET_RCODE(header, NOERROR);
|
||||
header->ancount = htons(1);
|
||||
header->hb3 |= HB3_AA;
|
||||
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
|
||||
}
|
||||
#ifdef HAVE_IPV6
|
||||
else if (flags == F_IPV6)
|
||||
else if (flags & ( F_IPV4 | F_IPV6))
|
||||
{
|
||||
SET_RCODE(header, NOERROR);
|
||||
header->ancount = htons(1);
|
||||
header->hb3 |= HB3_AA;
|
||||
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
|
||||
}
|
||||
if (flags & F_IPV4)
|
||||
{ /* we know the address */
|
||||
SET_RCODE(header, NOERROR);
|
||||
header->ancount = htons(1);
|
||||
header->hb3 |= HB3_AA;
|
||||
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_A, C_IN, "4", addrp);
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (flags & F_IPV6)
|
||||
{
|
||||
SET_RCODE(header, NOERROR);
|
||||
header->ancount = htons(ntohs(header->ancount) + 1);
|
||||
header->hb3 |= HB3_AA;
|
||||
add_resource_record(header, NULL, NULL, sizeof(struct dns_header), &p, ttl, NULL, T_AAAA, C_IN, "6", addrp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else /* nowhere to forward to */
|
||||
{
|
||||
struct all_addr a;
|
||||
@@ -986,40 +990,35 @@ size_t setup_reply(struct dns_header *header, size_t qlen,
|
||||
/* check if name matches local names ie from /etc/hosts or DHCP or local mx names. */
|
||||
int check_for_local_domain(char *name, time_t now)
|
||||
{
|
||||
struct crec *crecp;
|
||||
struct mx_srv_record *mx;
|
||||
struct txt_record *txt;
|
||||
struct interface_name *intr;
|
||||
struct ptr_record *ptr;
|
||||
struct naptr *naptr;
|
||||
|
||||
/* Note: the call to cache_find_by_name is intended to find any record which matches
|
||||
ie A, AAAA, CNAME. */
|
||||
|
||||
if ((crecp = cache_find_by_name(NULL, name, now, F_IPV4 | F_IPV6 | F_CNAME | F_NO_RR)) &&
|
||||
(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)))
|
||||
return 1;
|
||||
|
||||
for (naptr = daemon->naptr; naptr; naptr = naptr->next)
|
||||
if (hostname_isequal(name, naptr->name))
|
||||
if (hostname_issubdomain(name, naptr->name))
|
||||
return 1;
|
||||
|
||||
for (mx = daemon->mxnames; mx; mx = mx->next)
|
||||
if (hostname_isequal(name, mx->name))
|
||||
if (hostname_issubdomain(name, mx->name))
|
||||
return 1;
|
||||
|
||||
for (txt = daemon->txt; txt; txt = txt->next)
|
||||
if (hostname_isequal(name, txt->name))
|
||||
if (hostname_issubdomain(name, txt->name))
|
||||
return 1;
|
||||
|
||||
for (intr = daemon->int_names; intr; intr = intr->next)
|
||||
if (hostname_isequal(name, intr->name))
|
||||
if (hostname_issubdomain(name, intr->name))
|
||||
return 1;
|
||||
|
||||
for (ptr = daemon->ptr; ptr; ptr = ptr->next)
|
||||
if (hostname_isequal(name, ptr->name))
|
||||
if (hostname_issubdomain(name, ptr->name))
|
||||
return 1;
|
||||
|
||||
|
||||
if (cache_find_non_terminal(name, now))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1294,16 +1293,14 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
struct mx_srv_record *rec;
|
||||
size_t len;
|
||||
|
||||
if (ntohs(header->ancount) != 0 ||
|
||||
/* never answer queries with RD unset, to avoid cache snooping. */
|
||||
if (!(header->hb3 & HB3_RD) ||
|
||||
ntohs(header->ancount) != 0 ||
|
||||
ntohs(header->nscount) != 0 ||
|
||||
ntohs(header->qdcount) == 0 ||
|
||||
OPCODE(header) != QUERY )
|
||||
return 0;
|
||||
|
||||
/* always servfail queries with RD unset, to avoid cache snooping. */
|
||||
if (!(header->hb3 & HB3_RD))
|
||||
return setup_reply(header, qlen, NULL, F_SERVFAIL, 0);
|
||||
|
||||
/* Don't return AD set if checking disabled. */
|
||||
if (header->hb4 & HB4_CD)
|
||||
sec_data = 0;
|
||||
@@ -1382,11 +1379,11 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
||||
sec_data = 0;
|
||||
if (!dryrun)
|
||||
{
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, "<RR>");
|
||||
log_query(F_CONFIG | F_RRNAME, name, NULL, querystr(NULL, t->class));
|
||||
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||
daemon->local_ttl, NULL,
|
||||
t->class, C_IN, "t", t->len, t->txt))
|
||||
anscount ++;
|
||||
anscount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -626,6 +626,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
}
|
||||
|
||||
daemon->metrics[METRIC_BOOTP]++;
|
||||
log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
|
||||
|
||||
return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
|
||||
@@ -701,6 +702,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
if (client_hostname && option_bool(OPT_LOG_OPTS))
|
||||
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
|
||||
|
||||
|
||||
if (have_config(config, CONFIG_NAME))
|
||||
{
|
||||
@@ -713,11 +715,15 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
}
|
||||
else if (client_hostname)
|
||||
{
|
||||
struct dhcp_match_name *m;
|
||||
size_t nl;
|
||||
|
||||
domain = strip_hostname(client_hostname);
|
||||
|
||||
if (strlen(client_hostname) != 0)
|
||||
if ((nl = strlen(client_hostname)) != 0)
|
||||
{
|
||||
hostname = client_hostname;
|
||||
|
||||
if (!config)
|
||||
{
|
||||
/* Search again now we have a hostname.
|
||||
@@ -735,6 +741,30 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
netid = &known_id;
|
||||
}
|
||||
}
|
||||
|
||||
for (m = daemon->dhcp_name_match; m; m = m->next)
|
||||
{
|
||||
size_t ml = strlen(m->name);
|
||||
char save = 0;
|
||||
|
||||
if (nl < ml)
|
||||
continue;
|
||||
if (nl > ml)
|
||||
{
|
||||
save = client_hostname[ml];
|
||||
client_hostname[ml] = 0;
|
||||
}
|
||||
|
||||
if (hostname_isequal(client_hostname, m->name) &&
|
||||
(save == 0 || m->wildcard))
|
||||
{
|
||||
m->netid->next = netid;
|
||||
netid = m->netid;
|
||||
}
|
||||
|
||||
if (save != 0)
|
||||
client_hostname[ml] = save;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -917,7 +947,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
|
||||
|
||||
if (boot->file)
|
||||
strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
||||
safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
||||
}
|
||||
|
||||
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
|
||||
@@ -928,6 +958,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if ((pxe && !workaround) || !redirect4011)
|
||||
do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
|
||||
|
||||
daemon->metrics[METRIC_PXE]++;
|
||||
log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
if (!ignore)
|
||||
@@ -962,6 +993,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
|
||||
return 0;
|
||||
|
||||
daemon->metrics[METRIC_DHCPDECLINE]++;
|
||||
log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
|
||||
|
||||
if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
|
||||
@@ -994,6 +1026,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
message = _("unknown lease");
|
||||
|
||||
daemon->metrics[METRIC_DHCPRELEASE]++;
|
||||
log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
return 0;
|
||||
@@ -1060,6 +1093,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
message = _("no address available");
|
||||
}
|
||||
|
||||
daemon->metrics[METRIC_DHCPDISCOVER]++;
|
||||
log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
|
||||
@@ -1080,6 +1114,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
goto rapid_commit;
|
||||
}
|
||||
|
||||
daemon->metrics[METRIC_DHCPOFFER]++;
|
||||
log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||
|
||||
time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
|
||||
@@ -1192,6 +1227,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
mess->yiaddr = mess->ciaddr;
|
||||
}
|
||||
|
||||
daemon->metrics[METRIC_DHCPREQUEST]++;
|
||||
log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
|
||||
|
||||
rapid_commit:
|
||||
@@ -1265,6 +1301,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
if (message)
|
||||
{
|
||||
daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
|
||||
log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
|
||||
|
||||
/* rapid commit case: lease allocate failed but don't send DHCPNAK */
|
||||
@@ -1426,6 +1463,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
else
|
||||
override = lease->override;
|
||||
|
||||
daemon->metrics[METRIC_DHCPACK]++;
|
||||
log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||
|
||||
clear_packet(mess, end);
|
||||
@@ -1444,6 +1482,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
if (ignore || have_config(config, CONFIG_DISABLE))
|
||||
message = _("ignored");
|
||||
|
||||
daemon->metrics[METRIC_DHCPINFORM]++;
|
||||
log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
|
||||
|
||||
if (message || mess->ciaddr.s_addr == 0)
|
||||
@@ -1470,6 +1509,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
|
||||
|
||||
log_tags(tagif_netid, ntohl(mess->xid));
|
||||
|
||||
daemon->metrics[METRIC_DHCPACK]++;
|
||||
log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
|
||||
|
||||
if (lease)
|
||||
@@ -1636,6 +1676,13 @@ static void log_packet(char *type, void *addr, unsigned char *ext_mac,
|
||||
daemon->namebuff,
|
||||
string ? string : "",
|
||||
err ? err : "");
|
||||
|
||||
#ifdef HAVE_UBUS
|
||||
if (!strcmp(type, "DHCPACK"))
|
||||
ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
||||
else if (!strcmp(type, "DHCPRELEASE"))
|
||||
ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? inet_ntoa(a) : NULL, string ? string : NULL, interface);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void log_options(unsigned char *start, u32 xid)
|
||||
@@ -2311,7 +2358,7 @@ static void do_options(struct dhcp_context *context,
|
||||
in_list(req_options, OPTION_SNAME))
|
||||
option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
|
||||
else
|
||||
strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname)-1);
|
||||
safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
|
||||
}
|
||||
|
||||
if (boot->file)
|
||||
@@ -2321,7 +2368,7 @@ static void do_options(struct dhcp_context *context,
|
||||
in_list(req_options, OPTION_FILENAME))
|
||||
option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
|
||||
else
|
||||
strncpy((char *)mess->file, boot->file, sizeof(mess->file)-1);
|
||||
safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
|
||||
}
|
||||
|
||||
if (boot->next_server.s_addr)
|
||||
@@ -2338,14 +2385,14 @@ static void do_options(struct dhcp_context *context,
|
||||
if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
|
||||
(opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
|
||||
{
|
||||
strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file)-1);
|
||||
safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
|
||||
done_file = 1;
|
||||
}
|
||||
|
||||
if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
|
||||
(opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
|
||||
{
|
||||
strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname)-1);
|
||||
safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
|
||||
done_server = 1;
|
||||
}
|
||||
|
||||
|
||||
133
src/rfc3315.c
133
src/rfc3315.c
@@ -496,11 +496,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
else if (state->client_hostname)
|
||||
{
|
||||
struct dhcp_match_name *m;
|
||||
size_t nl;
|
||||
|
||||
state->domain = strip_hostname(state->client_hostname);
|
||||
nl = strlen(state->client_hostname);
|
||||
|
||||
if (strlen(state->client_hostname) != 0)
|
||||
{
|
||||
state->hostname = state->client_hostname;
|
||||
|
||||
if (!config)
|
||||
{
|
||||
/* Search again now we have a hostname.
|
||||
@@ -510,6 +515,30 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
|
||||
config = new;
|
||||
}
|
||||
|
||||
for (m = daemon->dhcp_name_match; m; m = m->next)
|
||||
{
|
||||
size_t ml = strlen(m->name);
|
||||
char save = 0;
|
||||
|
||||
if (nl < ml)
|
||||
continue;
|
||||
if (nl > ml)
|
||||
{
|
||||
save = state->client_hostname[ml];
|
||||
state->client_hostname[ml] = 0;
|
||||
}
|
||||
|
||||
if (hostname_isequal(state->client_hostname, m->name) &&
|
||||
(save == 0 || m->wildcard))
|
||||
{
|
||||
m->netid->next = state->tags;
|
||||
state->tags = m->netid;
|
||||
}
|
||||
|
||||
if (save != 0)
|
||||
state->client_hostname[ml] = save;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -639,9 +668,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
int plain_range = 1;
|
||||
u32 lease_time;
|
||||
struct dhcp_lease *ltmp;
|
||||
struct in6_addr *req_addr;
|
||||
struct in6_addr addr;
|
||||
|
||||
struct in6_addr req_addr, addr;
|
||||
|
||||
if (!check_ia(state, opt, &ia_end, &ia_option))
|
||||
continue;
|
||||
|
||||
@@ -709,9 +737,10 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
|
||||
for (ia_counter = 0; ia_option; ia_counter++, ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
req_addr = opt6_ptr(ia_option, 0);
|
||||
/* worry about alignment here. */
|
||||
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if ((c = address6_valid(state->context, req_addr, solicit_tags, plain_range)))
|
||||
if ((c = address6_valid(state->context, &req_addr, solicit_tags, plain_range)))
|
||||
{
|
||||
lease_time = c->lease_time;
|
||||
/* If the client asks for an address on the same network as a configured address,
|
||||
@@ -719,14 +748,14 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
addresses automatic. */
|
||||
if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr) && check_address(state, &addr))
|
||||
{
|
||||
req_addr = &addr;
|
||||
req_addr = addr;
|
||||
mark_config_used(c, &addr);
|
||||
if (have_config(config, CONFIG_TIME))
|
||||
lease_time = config->lease_time;
|
||||
}
|
||||
else if (!(c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
|
||||
else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
|
||||
continue; /* not an address we're allowed */
|
||||
else if (!check_address(state, req_addr))
|
||||
else if (!check_address(state, &req_addr))
|
||||
continue; /* address leased elsewhere */
|
||||
|
||||
/* add address to output packet */
|
||||
@@ -734,8 +763,8 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
||||
state->send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(state, c, lease_time, ia_option, &min_time, req_addr, now);
|
||||
mark_context_used(state, req_addr);
|
||||
add_address(state, c, lease_time, ia_option, &min_time, &req_addr, now);
|
||||
mark_context_used(state, &req_addr);
|
||||
get_context_tag(state, c);
|
||||
address_assigned = 1;
|
||||
}
|
||||
@@ -768,15 +797,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
ltmp = NULL;
|
||||
while ((ltmp = lease6_find_by_client(ltmp, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA, state->clid, state->clid_len, state->iaid)))
|
||||
{
|
||||
req_addr = <mp->addr6;
|
||||
if ((c = address6_available(state->context, req_addr, solicit_tags, plain_range)))
|
||||
req_addr = ltmp->addr6;
|
||||
if ((c = address6_available(state->context, &req_addr, solicit_tags, plain_range)))
|
||||
{
|
||||
#ifdef OPTION6_PREFIX_CLASS
|
||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
||||
state->send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(state, c, c->lease_time, NULL, &min_time, req_addr, now);
|
||||
mark_context_used(state, req_addr);
|
||||
add_address(state, c, c->lease_time, NULL, &min_time, &req_addr, now);
|
||||
mark_context_used(state, &req_addr);
|
||||
get_context_tag(state, c);
|
||||
address_assigned = 1;
|
||||
}
|
||||
@@ -892,16 +921,19 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
|
||||
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
struct in6_addr req_addr;
|
||||
struct dhcp_context *dynamic, *c;
|
||||
unsigned int lease_time;
|
||||
struct in6_addr addr;
|
||||
int config_ok = 0;
|
||||
|
||||
/* align. */
|
||||
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if ((c = address6_valid(state->context, req_addr, tagif, 1)))
|
||||
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr);
|
||||
if ((c = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||
config_ok = config_valid(config, c, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr);
|
||||
|
||||
if ((dynamic = address6_available(state->context, req_addr, tagif, 1)) || c)
|
||||
if ((dynamic = address6_available(state->context, &req_addr, tagif, 1)) || c)
|
||||
{
|
||||
if (!dynamic && !config_ok)
|
||||
{
|
||||
@@ -911,7 +943,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
put_opt6_string(_("address unavailable"));
|
||||
end_opt6(o1);
|
||||
}
|
||||
else if (!check_address(state, req_addr))
|
||||
else if (!check_address(state, &req_addr))
|
||||
{
|
||||
/* Address leased to another DUID/IAID */
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
@@ -933,7 +965,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
if (dump_all_prefix_classes && state->ia_type == OPTION6_IA_NA)
|
||||
state->send_prefix_class = prefix_class_from_context(c);
|
||||
#endif
|
||||
add_address(state, dynamic, lease_time, ia_option, &min_time, req_addr, now);
|
||||
add_address(state, dynamic, lease_time, ia_option, &min_time, &req_addr, now);
|
||||
get_context_tag(state, dynamic);
|
||||
address_assigned = 1;
|
||||
}
|
||||
@@ -996,15 +1028,17 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
for (; ia_option; ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct dhcp_lease *lease = NULL;
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
struct in6_addr req_addr;
|
||||
unsigned int preferred_time = opt6_uint(ia_option, 16, 4);
|
||||
unsigned int valid_time = opt6_uint(ia_option, 20, 4);
|
||||
char *message = NULL;
|
||||
struct dhcp_context *this_context;
|
||||
|
||||
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if (!(lease = lease6_find(state->clid, state->clid_len,
|
||||
state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||
state->iaid, req_addr)))
|
||||
state->iaid, &req_addr)))
|
||||
{
|
||||
/* If the server cannot find a client entry for the IA the server
|
||||
returns the IA containing no addresses with a Status Code option set
|
||||
@@ -1012,7 +1046,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
save_counter(iacntr);
|
||||
t1cntr = 0;
|
||||
|
||||
log6_packet(state, "DHCPREPLY", req_addr, _("lease not found"));
|
||||
log6_packet(state, "DHCPREPLY", &req_addr, _("lease not found"));
|
||||
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6NOBINDING);
|
||||
@@ -1024,15 +1058,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
|
||||
if ((this_context = address6_available(state->context, req_addr, tagif, 1)) ||
|
||||
(this_context = address6_valid(state->context, req_addr, tagif, 1)))
|
||||
if ((this_context = address6_available(state->context, &req_addr, tagif, 1)) ||
|
||||
(this_context = address6_valid(state->context, &req_addr, tagif, 1)))
|
||||
{
|
||||
struct in6_addr addr;
|
||||
unsigned int lease_time;
|
||||
|
||||
get_context_tag(state, this_context);
|
||||
|
||||
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, req_addr) && have_config(config, CONFIG_TIME))
|
||||
if (config_valid(config, this_context, &addr) && IN6_ARE_ADDR_EQUAL(&addr, &req_addr) && have_config(config, CONFIG_TIME))
|
||||
lease_time = config->lease_time;
|
||||
else
|
||||
lease_time = this_context->lease_time;
|
||||
@@ -1045,7 +1079,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
lease_set_hwaddr(lease, state->mac, state->clid, state->mac_len, state->mac_type, state->clid_len, now, 0);
|
||||
if (state->ia_type == OPTION6_IA_NA && state->hostname)
|
||||
{
|
||||
char *addr_domain = get_domain6(req_addr);
|
||||
char *addr_domain = get_domain6(&req_addr);
|
||||
if (!state->send_domain)
|
||||
state->send_domain = addr_domain;
|
||||
lease_set_hostname(lease, state->hostname, state->hostname_auth, addr_domain, state->domain);
|
||||
@@ -1063,12 +1097,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
if (message && (message != state->hostname))
|
||||
log6_packet(state, "DHCPREPLY", req_addr, message);
|
||||
log6_packet(state, "DHCPREPLY", &req_addr, message);
|
||||
else
|
||||
log6_quiet(state, "DHCPREPLY", req_addr, message);
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, message);
|
||||
|
||||
o1 = new_opt6(OPTION6_IAADDR);
|
||||
put_opt6(req_addr, sizeof(*req_addr));
|
||||
put_opt6(&req_addr, sizeof(req_addr));
|
||||
put_opt6_long(preferred_time);
|
||||
put_opt6_long(valid_time);
|
||||
end_opt6(o1);
|
||||
@@ -1100,20 +1134,23 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
ia_option;
|
||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct in6_addr *req_addr = opt6_ptr(ia_option, 0);
|
||||
struct in6_addr req_addr;
|
||||
|
||||
/* alignment */
|
||||
memcpy(&req_addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if (!address6_valid(state->context, req_addr, tagif, 1))
|
||||
if (!address6_valid(state->context, &req_addr, tagif, 1))
|
||||
{
|
||||
o1 = new_opt6(OPTION6_STATUS_CODE);
|
||||
put_opt6_short(DHCP6NOTONLINK);
|
||||
put_opt6_string(_("confirm failed"));
|
||||
end_opt6(o1);
|
||||
log6_quiet(state, "DHCPREPLY", req_addr, _("confirm failed"));
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, _("confirm failed"));
|
||||
return 1;
|
||||
}
|
||||
|
||||
good_addr = 1;
|
||||
log6_quiet(state, "DHCPREPLY", req_addr, state->hostname);
|
||||
log6_quiet(state, "DHCPREPLY", &req_addr, state->hostname);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1172,9 +1209,12 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
|
||||
struct in6_addr addr;
|
||||
|
||||
/* align */
|
||||
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||
state->iaid, opt6_ptr(ia_option, 0))))
|
||||
state->iaid, &addr)))
|
||||
lease_prune(lease, now);
|
||||
else
|
||||
{
|
||||
@@ -1191,7 +1231,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
o1 = new_opt6(OPTION6_IAADDR);
|
||||
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
put_opt6(&addr, IN6ADDRSZ);
|
||||
put_opt6_long(0);
|
||||
put_opt6_long(0);
|
||||
end_opt6(o1);
|
||||
@@ -1234,12 +1274,15 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
ia_option = opt6_find(opt6_next(ia_option, ia_end), ia_end, OPTION6_IAADDR, 24))
|
||||
{
|
||||
struct dhcp_lease *lease;
|
||||
struct in6_addr *addrp = opt6_ptr(ia_option, 0);
|
||||
struct in6_addr addr;
|
||||
|
||||
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, addrp))
|
||||
/* align */
|
||||
memcpy(&addr, opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
|
||||
if (have_config(config, CONFIG_ADDR6) && IN6_ARE_ADDR_EQUAL(&config->addr6, &addr))
|
||||
{
|
||||
prettyprint_time(daemon->dhcp_buff3, DECLINE_BACKOFF);
|
||||
inet_ntop(AF_INET6, addrp, daemon->addrbuff, ADDRSTRLEN);
|
||||
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
|
||||
daemon->addrbuff, daemon->dhcp_buff3);
|
||||
config->flags |= CONFIG_DECLINED;
|
||||
@@ -1251,7 +1294,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
context_tmp->addr_epoch++;
|
||||
|
||||
if ((lease = lease6_find(state->clid, state->clid_len, state->ia_type == OPTION6_IA_NA ? LEASE_NA : LEASE_TA,
|
||||
state->iaid, opt6_ptr(ia_option, 0))))
|
||||
state->iaid, &addr)))
|
||||
lease_prune(lease, now);
|
||||
else
|
||||
{
|
||||
@@ -1268,7 +1311,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
|
||||
}
|
||||
|
||||
o1 = new_opt6(OPTION6_IAADDR);
|
||||
put_opt6(opt6_ptr(ia_option, 0), IN6ADDRSZ);
|
||||
put_opt6(&addr, IN6ADDRSZ);
|
||||
put_opt6_long(0);
|
||||
put_opt6_long(0);
|
||||
end_opt6(o1);
|
||||
@@ -1936,7 +1979,11 @@ static void log6_opts(int nest, unsigned int xid, void *start_opts, void *end_op
|
||||
}
|
||||
else if (type == OPTION6_IAADDR)
|
||||
{
|
||||
inet_ntop(AF_INET6, opt6_ptr(opt, 0), daemon->addrbuff, ADDRSTRLEN);
|
||||
struct in6_addr addr;
|
||||
|
||||
/* align */
|
||||
memcpy(&addr, opt6_ptr(opt, 0), IN6ADDRSZ);
|
||||
inet_ntop(AF_INET6, &addr, daemon->addrbuff, ADDRSTRLEN);
|
||||
sprintf(daemon->namebuff, "%s PL=%u VL=%u",
|
||||
daemon->addrbuff, opt6_uint(opt, 16, 4), opt6_uint(opt, 20, 4));
|
||||
optname = "iaaddr";
|
||||
|
||||
@@ -166,7 +166,8 @@ time_t periodic_slaac(time_t now, struct dhcp_lease *leases)
|
||||
|
||||
if (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(-1), 0,
|
||||
(struct sockaddr *)&addr, sizeof(addr)) == -1 &&
|
||||
errno == EHOSTUNREACH)
|
||||
errno == EHOSTUNREACH &&
|
||||
slaac->backoff == 12)
|
||||
slaac->ping_time = 0; /* Give up */
|
||||
else
|
||||
{
|
||||
|
||||
@@ -234,7 +234,7 @@ void tftp_request(struct listener *listen, time_t now)
|
||||
#endif
|
||||
}
|
||||
|
||||
strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
|
||||
if (ioctl(listen->tftpfd, SIOCGIFMTU, &ifr) != -1)
|
||||
{
|
||||
mtu = ifr.ifr_mtu;
|
||||
|
||||
107
src/ubus.c
Normal file
107
src/ubus.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 dated June, 1991, or
|
||||
(at your option) version 3 dated 29 June, 2007.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "dnsmasq.h"
|
||||
|
||||
#ifdef HAVE_UBUS
|
||||
|
||||
#include <libubus.h>
|
||||
|
||||
static struct ubus_context *ubus = NULL;
|
||||
static struct blob_buf b;
|
||||
|
||||
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg);
|
||||
static struct ubus_method ubus_object_methods[] = {
|
||||
{.name = "metrics", .handler = ubus_handle_metrics},
|
||||
};
|
||||
|
||||
static struct ubus_object_type ubus_object_type = UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
|
||||
|
||||
static struct ubus_object ubus_object = {
|
||||
.name = "dnsmasq",
|
||||
.type = &ubus_object_type,
|
||||
.methods = ubus_object_methods,
|
||||
.n_methods = ARRAY_SIZE(ubus_object_methods),
|
||||
};
|
||||
|
||||
void set_ubus_listeners()
|
||||
{
|
||||
if (!ubus)
|
||||
return;
|
||||
|
||||
poll_listen(ubus->sock.fd, POLLIN);
|
||||
poll_listen(ubus->sock.fd, POLLERR);
|
||||
poll_listen(ubus->sock.fd, POLLHUP);
|
||||
}
|
||||
|
||||
void check_ubus_listeners()
|
||||
{
|
||||
if (!ubus)
|
||||
{
|
||||
ubus = ubus_connect(NULL);
|
||||
if (!ubus)
|
||||
return;
|
||||
ubus_add_object(ubus, &ubus_object);
|
||||
}
|
||||
|
||||
if (poll_check(ubus->sock.fd, POLLIN))
|
||||
ubus_handle_event(ubus);
|
||||
|
||||
if (poll_check(ubus->sock.fd, POLLHUP))
|
||||
{
|
||||
ubus_free(ubus);
|
||||
ubus = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int ubus_handle_metrics(struct ubus_context *ctx, struct ubus_object *obj,
|
||||
struct ubus_request_data *req, const char *method,
|
||||
struct blob_attr *msg)
|
||||
{
|
||||
int i;
|
||||
blob_buf_init(&b, 0);
|
||||
|
||||
for(i=0; i < __METRIC_MAX; i++)
|
||||
blobmsg_add_u32(&b, get_metric_name(i), daemon->metrics[i]);
|
||||
|
||||
ubus_send_reply(ctx, req, b.head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ubus_event_bcast(const char *type, const char *mac, const char *ip, const char *name, const char *interface)
|
||||
{
|
||||
if (!ubus || !ubus_object.has_subscribers)
|
||||
return;
|
||||
|
||||
blob_buf_init(&b, 0);
|
||||
if (mac)
|
||||
blobmsg_add_string(&b, "mac", mac);
|
||||
if (ip)
|
||||
blobmsg_add_string(&b, "ip", ip);
|
||||
if (name)
|
||||
blobmsg_add_string(&b, "name", name);
|
||||
if (interface)
|
||||
blobmsg_add_string(&b, "interface", interface);
|
||||
|
||||
ubus_notify(ubus, &ubus_object, type, b.head, -1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_UBUS */
|
||||
51
src/util.c
51
src/util.c
@@ -281,7 +281,18 @@ void *safe_malloc(size_t size)
|
||||
die(_("could not get memory"), NULL, EC_NOMEM);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure limited size string is always terminated.
|
||||
* Can be replaced by (void)strlcpy() on some platforms */
|
||||
void safe_strncpy(char *dest, const char *src, size_t size)
|
||||
{
|
||||
if (size != 0)
|
||||
{
|
||||
dest[size-1] = '\0';
|
||||
strncpy(dest, src, size-1);
|
||||
}
|
||||
}
|
||||
|
||||
void safe_pipe(int *fd, int read_noblock)
|
||||
{
|
||||
@@ -355,6 +366,44 @@ int hostname_isequal(const char *a, const char *b)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is b equal to or a subdomain of a return 2 for equal, 1 for subdomain */
|
||||
int hostname_issubdomain(char *a, char *b)
|
||||
{
|
||||
char *ap, *bp;
|
||||
unsigned int c1, c2;
|
||||
|
||||
/* move to the end */
|
||||
for (ap = a; *ap; ap++);
|
||||
for (bp = b; *bp; bp++);
|
||||
|
||||
/* a shorter than b or a empty. */
|
||||
if ((bp - b) < (ap - a) || ap == a)
|
||||
return 0;
|
||||
|
||||
do
|
||||
{
|
||||
c1 = (unsigned char) *(--ap);
|
||||
c2 = (unsigned char) *(--bp);
|
||||
|
||||
if (c1 >= 'A' && c1 <= 'Z')
|
||||
c1 += 'a' - 'A';
|
||||
if (c2 >= 'A' && c2 <= 'Z')
|
||||
c2 += 'a' - 'A';
|
||||
|
||||
if (c1 != c2)
|
||||
return 0;
|
||||
} while (ap != a);
|
||||
|
||||
if (bp == b)
|
||||
return 2;
|
||||
|
||||
if (*(--bp) == '.')
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
time_t dnsmasq_time(void)
|
||||
{
|
||||
#ifdef HAVE_BROKEN_RTC
|
||||
|
||||
Reference in New Issue
Block a user