Compare commits

...
52 Commits
Author SHA1 Message Date
Simon Kelley 327bbc92bc Changed priority to high in Debian changelog. 2021-01-17 23:35:24 +00:00
Simon Kelley cc0b4489c7 Update to new struct frec fields in conntrack code. 2021-01-15 22:21:52 +00:00
Simon Kelley 9212ad284f Update Debian changelog. 2021-01-15 22:17:30 +00:00
Simon Kelley 503f68dbc4 Fix warning message logic. 2021-01-15 21:53:29 +00:00
Simon Kelley e01e09c712 Add CVE numbers to security update descriptions in CHANGELOG 2021-01-08 22:50:03 +00:00
Simon Kelley 6a6e06fbb0 Small cleanups in frec_src datastucture handling. 2020-12-16 15:49:03 +00:00
Petr Menšík 2024f97297 Support hash function from nettle (only)
Unlike COPTS=-DHAVE_DNSSEC, allow usage of just sha256 function from
nettle, but keep DNSSEC disabled at build time. Skips use of internal
hash implementation without support for validation built-in.
2020-12-16 15:49:03 +00:00
Simon Kelley 25e63f1e56 Handle caching with EDNS options better.
If we add the EDNS client subnet option, or the client's
MAC address, then the reply we get back may very depending on
that. Since the cache is ignorant of such things, it's not safe to
cache such replies. This patch determines when a dangerous EDNS
option is being added and disables caching.

Note that for much the same reason, we can't combine multiple
queries for the same question when dangerous EDNS options are
being added, and the code now handles that in the same way. This
query combining is required for security against cache poisoning,
so disabling the cache has a security function as well as a
correctness one.
2020-12-16 15:49:03 +00:00
Simon Kelley 15b60ddf93 Handle multiple identical near simultaneous DNS queries better.
Previously, such queries would all be forwarded
independently. This is, in theory, inefficent but in practise
not a problem, _except_ that is means that an answer for any
of the forwarded queries will be accepted and cached.
An attacker can send a query multiple times, and for each repeat,
another {port, ID} becomes capable of accepting the answer he is
sending in the blind, to random IDs and ports. The chance of a
succesful attack is therefore multiplied by the number of repeats
of the query. The new behaviour detects repeated queries and
merely stores the clients sending repeats so that when the
first query completes, the answer can be sent to all the
clients who asked. Refer: CERT VU#434904.
2020-12-16 15:49:02 +00:00
Simon Kelley 824461192c Add missing check for NULL return from allocate_rfd(). 2020-12-16 15:49:02 +00:00
Simon Kelley 1eb6cedb03 Fix DNS reply when asking for DNSSEC and a validated CNAME is already cached. 2020-12-16 15:49:02 +00:00
Simon Kelley 059aded070 Optimse RR digest calculation in DNSSEC.
If an RR is of a type which doesn't need canonicalisation,
bypass the relatively slow canonicalisation code, and insert
it direct into the digest.
2020-12-16 15:49:02 +00:00
Simon Kelley 2d765867c5 Use SHA-256 to provide security against DNS cache poisoning.
Use the SHA-256 hash function to verify that DNS answers
received are for the questions originally asked. This replaces
the slightly insecure SHA-1 (when compiled with DNSSEC) or
the very insecure CRC32 (otherwise). Refer: CERT VU#434904.
2020-12-16 15:49:02 +00:00
Simon Kelley 257ac0c5f7 Check destination of DNS UDP query replies.
At any time, dnsmasq will have a set of sockets open, bound to
random ports, on which it sends queries to upstream nameservers.
This patch fixes the existing problem that a reply for ANY in-flight
query would be accepted via ANY open port, which increases the
chances of an attacker flooding answers "in the blind" in an
attempt to poison the DNS cache. CERT VU#434904 refers.
2020-12-16 15:48:36 +00:00
Simon Kelley 4e96a4be68 Fix remote buffer overflow CERT VU#434904
The problem is in the sort_rrset() function and allows a remote
attacker to overwrite memory. Any dnsmasq instance with DNSSEC
enabled is vulnerable.
2020-12-16 15:47:42 +00:00
Simon Kelley a2a7e040b1 Use the values of --min-port and --max-port in TCP connections.
Rather that letting the kernel pick source ports, do it ourselves
so that the --min-port and --max-port parameters are be obeyed.
2020-12-12 23:26:45 +00:00
Wang Shanker 4ded96209e pxe: support pxe clients with custom vendor-class
From 606d638918edb0e0ec07fe27eb68d06fb5ebd981 Mon Sep 17 00:00:00 2001
From: Miao Wang <shankerwangmiao@gmail.com>
Date: Fri, 4 Dec 2020 09:59:37 +0800
Subject: [PATCH v2] pxe: support pxe clients with custom vendor-class

According to UEFI[1] and PXE[2] specs, PXE clients are required to have
`PXEClient` identfier in the vendor-class field of DHCP requests, and
PXE servers should also include that identifier in their responses.
However, the firmware of servers from a few vendors[3] are customized to
include a different identifier. This patch adds an option named
`dhcp-pxe-vendor` to provide a list of such identifiers. The identifier
used in responses sent from dnsmasq is identical to that in the coresponding
request.

[1]: https://uefi.org/sites/default/files/resources/UEFI%20Spec%202.8B%20May%202020.pdf
[2]: http://www.pix.net/software/pxeboot/archive/pxespec.pdf
[3]: For instance, TaiShan servers from Huawei, which are Arm64-based,
       send `HW-Client` in PXE requests up to now.

Signed-off-by: Miao Wang <shankerwangmiao@gmail.com>
2020-12-06 22:48:11 +00:00
Matthias Andree f60fea1fb0 CHANGELOG: Fix three typoes. 2020-07-19 21:54:44 +01:00
Simon Kelley 4d85e409cd Change default lease time for DHCPv6 to one day.
Also remove floor on valid and preffered times in RA when
no time is specified.
2020-07-12 22:45:46 +01:00
Simon Kelley 2bd02d2f59 Backdated CHANGELOG update. 2020-07-12 21:57:38 +01:00
Simon Kelley 7e194a0a7d Apply floor of 60s to TTL of DNSKEY and DS records in cache.
Short TTLs and specifically zero TTLs can mess up DNSSEC validation.
2020-07-12 17:43:25 +01:00
Simon Kelley 9beb4d9ea2 Fix BNF in man page description for --server. 2020-07-05 17:17:39 +01:00
Simon Kelley ab5ebe9507 Bump Debian version to 2.82 2020-06-26 22:23:15 +01:00
Simon Kelley 837e8f4eb5 Remove runit support when building debs for Ubuntu. 2020-06-26 22:13:27 +01:00
Simon Kelley e2cb655958 Thorough clean-up following 8270648da1. 2020-06-20 22:30:12 +01:00
Frank 8270648da1 Fix memory corruption on EAGAIN return from pipe during TCP requests.
This patch fixes a buffer overflow in TCP requests. Since the read is not
actually being retried, the byte written by the child can be left
in the pipe. When that happens, cache_recv_insert() reads the length of the
name, which is now multiplied by 256 due to the extra 0 byte (8 bit shift)
and results in daemon->namebuff being overflowed.

Namebuff is immediately before the daemon struct in memory so it
ends up corrupting the beginning of the daemon struct.
2020-06-20 15:17:56 +01:00
Simon Kelley 619000a3c5 Suppress logging of listen addresses during startup.
The initial call to enumerate_interfaces() happens before the
logging subsystem in initialised and the startup banner logged.
It's not intended that syslog be written at this point.
2020-04-29 00:09:58 +01:00
Petr Menšík 1c1b925052 Remove duplicate address family from listener
Since address already contain family, remove separate family from
listener. Use now family from address itself.
2020-04-29 00:06:57 +01:00
Petr Menšík 49bdf1ead9 Handle listening on duplicate addresses
Save listening address into listener. Use it to find existing listeners
before creating new one. If it exist, increase just used counter.
Release only listeners not already used.

Duplicates family in listener.
2020-04-29 00:06:31 +01:00
Petr Mensik 60a3ae19c5 Cleanup interfaces no longer available
Clean addresses and interfaces not found after enumerate. Free unused
records to speed up checking active interfaces and reduce used memory.
2020-04-29 00:06:01 +01:00
Petr Mensik 951a22165c Compare address and interface index for allowed interface
If interface is recreated with the same address but different index, it
would not change any other parameter.

Test also address family on incoming TCP queries.
2020-04-29 00:04:29 +01:00
Petr Mensik 51cdd1a227 Explicitly mark address port not used
On many places return value is ignored. Usually it means port is always
the same and not needed to be displayed. Unify warnings.
2020-04-29 00:04:04 +01:00
Petr Mensik 66adee85be Log listening on new interfaces
Log in debug mode listening on interfaces. They can be dynamically
found, include interface number, since it is checked on TCP connections.
Print also addresses found on them.
2020-04-29 00:03:21 +01:00
Simon Kelley 4890bcdea2 Workaround for reported recvmsg() ignoring MSG_PEEK. 2020-04-28 14:02:53 +01:00
Simon Kelley 8baf583a3f Allow IPv6 addresses ofthe form [::ffff:1.2.3.4] in --dhcp-option. 2020-04-23 23:14:45 +01:00
Simon Kelley 913fa15fb1 Convert failure of setsockopt(..., SOL_NETLINK, NETLINK_NO_ENOBUFS, ...) into warning.
We call this, which avoids POLLERR returns from netlink on a loaded system,
if the kernel is new enough to support it. Sadly, qemu-user doesn't support
the socket option, so if it fails despite the kernel being new enough to
support it, we just emit a warning, rather than failing hard.
2020-04-19 23:16:52 +01:00
Simon Kelley 00fe2f49e0 Debian package fix for kFreeBSD. 2020-04-19 21:59:13 +01:00
Simon Kelley ec2067df75 Debian package fixes.
Add runit /etc files to conffiles.
Fix broken copyright file in dnsmasq binary package.
2020-04-12 16:12:50 +01:00
Simon Kelley 7ddb99d251 Debian changelog entry for CVE-2019-14834 2020-04-08 17:32:53 +01:00
Geert Stappers ba26d3485b [PATCH] src/dnsmasq.c: Labeled a lonely #endif 2020-04-06 15:42:39 +01:00
Matthias Andree 081a1c4014 2.81rc5 CHANGELOG and man/dnsmasq.8 manual page improvements
Hi Simon,

>         Add --shared-network config. This enables allocation of addresses
>         the DHCP server in subnets where the server (or relay) doesn't
>         have an interface on the network in that subnet. Many thanks to
>         kamp.de for sponsoring this feature.
Does this paragraph lack a preposition "by" early on the 2nd line, or am
I mis-guessing the purpose?

...enables allocation of addresses *by* the DHCP server...

The manual page also seems to offer room for linguistic improvement
(apparently written by a German, so I see the typical patterns, and also
the misuse of which vs. that.

I am attaching a patch series vs. git to fix several issues in the
manpage and CHANGELOG.

From 35b88d98429e2fe016d9989d220f6faf2b933764 Mon Sep 17 00:00:00 2001
From: Matthias Andree <matthias.andree@gmx.de>
Date: Sun, 5 Apr 2020 11:18:05 +0200
Subject: [PATCH 1/5] man/dnsmasq.8: Properly capitalize DHCP acronym.
2020-04-06 15:29:24 +01:00
Simon Kelley 532246fc9e Tweak to DNSSEC logging. 2020-04-04 18:50:56 +01:00
Simon Kelley 8caf3d7c6c Fix rare problem allocating frec for DNSSEC.
A call to get_new_frec() for a DNSSEC query could manage to
free the original frec that we're doing the DNSSEC query to validate.
Bad things then happen.

This requires that the original frec is old, so it doesn't happen
in practice. I found it when running under gdb, and there have been
reports of SEGV associated with large system-clock warps which are
probably the same thing.
2020-04-04 17:00:32 +01:00
Oldřich Jedlička d162bee356 Allow overriding of ubus service name.
Same as for the dbus, allow specifying ubus service name (namespace) on
the command line as an optional argument to --enable-ubus option.

Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
2020-03-28 18:16:53 +00:00
Simon Kelley b43585c34b Fix nameserver list in auth mode.
If dnsmasq is not acting as an authoritative nameserver (no second
argument to --auth-server) then it should not appear in the NS RRset.

This leaves simply the list of servers specified in --auth-sec-servers.
2020-03-28 17:41:06 +00:00
Oldřich Jedlička 3f60ecd6f0 Fixed resource leak on ubus_init failure.
When ubus_add_object fails, the ubus_connect object is not freed, so the
connection leaks. Add ubus_destroy to free the connection object.

Signed-off-by: Oldřich Jedlička <oldium.pro@gmail.com>
2020-03-19 22:20:18 +00:00
Simon Kelley 0506a5ed4e Handle old kernels that don't do NETLINK_NO_ENOBUFS.
Deal with both old kernel header files that don't define it,
and old kernels that don't implement it.

Also generalise Linux kernel version handling.
2020-03-19 21:56:45 +00:00
Dominik DL6ER e7ee1aa093 Extend stop-dns-rebind to reject IPv6 LL and ULA addresses.
We also reject the loopback address if rebind-localhost-ok is NOT set.

Signed-off-by: DL6ER <dl6er@dl6er.de>
2020-03-17 22:59:17 +00:00
Simon Kelley 63ed917ad9 Update to Debian runit mods. 2020-03-17 17:07:49 +00:00
Simon Kelley 63e21bdea3 Remove 19036 trust anchor, now expired. 2020-03-17 14:43:42 +00:00
Simon Kelley 1627d577af Set NETLINK_NO_ENOBUFS in netlink socket, to avoid POLLERR returns. 2020-03-10 23:55:18 +00:00
Conrad Kostecki b837c4528d Update German translation. 2020-03-10 21:20:46 +00:00
33 changed files with 1493 additions and 667 deletions

No files matched your search

+61 -6
View File
@@ -1,12 +1,67 @@
version 2.83
Use the values of --min-port and --max-port in outgoing
TCP connections to upstream DNS servers.
Fix a remote buffer overflow problem in the DNSSEC code. Any
dnsmasq with DNSSEC compiled in and enabled is vulnerable to this,
referenced by CVE-2020-25681, CVE-2020-25682, CVE-2020-25683
CVE-2020-25687.
Be sure to only accept UDP DNS query replies at the address
from which the query was originated. This keeps as much entropy
in the {query-ID, random-port} tuple as possible, to help defeat
cache poisoning attacks. Refer: CVE-2020-25684.
Use the SHA-256 hash function to verify that DNS answers
received are for the questions originally asked. This replaces
the slightly insecure SHA-1 (when compiled with DNSSEC) or
the very insecure CRC32 (otherwise). Refer: CVE-2020-25685.
Handle multiple identical near simultaneous DNS queries better.
Previously, such queries would all be forwarded
independently. This is, in theory, inefficent but in practise
not a problem, _except_ that is means that an answer for any
of the forwarded queries will be accepted and cached.
An attacker can send a query multiple times, and for each repeat,
another {port, ID} becomes capable of accepting the answer he is
sending in the blind, to random IDs and ports. The chance of a
succesful attack is therefore multiplied by the number of repeats
of the query. The new behaviour detects repeated queries and
merely stores the clients sending repeats so that when the
first query completes, the answer can be sent to all the
clients who asked. Refer: CVE-2020-25686.
version 2.82
Improve behaviour in the face of network interfaces which come
and go and change index. Thanks to Petr Mensik for the patch.
Convert hard startup failure on NETLINK_NO_ENOBUFS under qemu-user
to a warning.
Allow IPv6 addresses ofthe form [::ffff:1.2.3.4] in --dhcp-option.
Fix crash under heavy TCP connection load introduced in 2.81.
Thanks to Frank for good work chasing this down.
Change default lease time for DHCPv6 to one day.
Alter calculation of preferred and valid times in router
advertisements, so that these do not have a floor applied
of the lease time in the dhcp-range if this is not explicitly
specified and is merely the default.
Thanks to Martin-Éric Racine for suggestions on this.
version 2.81
Impove cache behaviour for TCP connections. For ease of
implementaion, dnsmasq has always forked a new process to handle
Improve cache behaviour for TCP connections. For ease of
implementation, dnsmasq has always forked a new process to handle
each incoming TCP connection. A side-effect of this is that
any DNS queries answered from TCP connections are not cached:
when TCP connections were rare, this was not a problem.
With the coming of DNSSEC, it's now the case that some
With the coming of DNSSEC, it is now the case that some
DNSSEC queries have answers which spill to TCP, and if,
for instance, this applies to the keys for the root then
for instance, this applies to the keys for the root, then
those never get cached, and performance is very bad.
This fix passes cache entries back from the TCP child process to
the main server process, and fixes the problem.
@@ -35,7 +90,7 @@ version 2.81
configuration.
Add --shared-network config. This enables allocation of addresses
the DHCP server in subnets where the server (or relay) doesn't
by the DHCP server in subnets where the server (or relay) does not
have an interface on the network in that subnet. Many thanks to
kamp.de for sponsoring this feature.
@@ -66,7 +121,7 @@ version 2.81
Evgenii Seliavka for the suggestion and initial patch.
In the router advert code, handle case where we have two
different interfaces on the same IPv6 net, and we're doing
different interfaces on the same IPv6 net, and we are doing
RA/DHCP service on only one of them. Thanks to NIIBE Yutaka
for spotting this case and making the initial patch.
+7 -4
View File
@@ -53,7 +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 "" --copy -lubox -lubus`
ubus_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_UBUS "" --copy '-lubox -lubus'`
idn_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_IDN $(PKG_CONFIG) --cflags libidn`
idn_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`
@@ -62,8 +62,10 @@ ct_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CON
ct_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_CONNTRACK $(PKG_CONFIG) --libs libnetfilter_conntrack`
lua_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --cflags lua5.2`
lua_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_LUASCRIPT $(PKG_CONFIG) --libs lua5.2`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags nettle hogweed`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs nettle hogweed`
nettle_cflags = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --cflags 'nettle hogweed' \
HAVE_NETTLEHASH $(PKG_CONFIG) --cflags nettle`
nettle_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC $(PKG_CONFIG) --libs 'nettle hogweed' \
HAVE_NETTLEHASH $(PKG_CONFIG) --libs nettle`
gmp_libs = `echo $(COPTS) | $(top)/bld/pkg-wrapper HAVE_DNSSEC NO_GMP --copy -lgmp`
sunos_libs = `if uname | grep SunOS >/dev/null 2>&1; then echo -lsocket -lnsl -lposix4; fi`
version = -DVERSION='\"`$(top)/bld/get-version $(top)`\"'
@@ -77,7 +79,8 @@ 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 ubus.o metrics.o
poll.o rrfilter.o edns0.o arp.o crypto.o dump.o ubus.o \
metrics.o hash_questions.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h metrics.h
+1 -1
View File
@@ -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 ubus.c
crypto.c dump.c ubus.c metrics.c hash_questions.c
LOCAL_MODULE := dnsmasq
+22 -19
View File
@@ -1,35 +1,37 @@
#!/bin/sh
search=$1
shift
pkg=$1
shift
op=$1
shift
in=`cat`
if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
echo $in | grep $search >/dev/null 2>&1; then
search()
{
grep "^\#[[:space:]]*define[[:space:]]*$1" config.h >/dev/null 2>&1 || \
echo $in | grep $1 >/dev/null 2>&1
}
while [ "$#" -gt 0 ]; do
search=$1
pkg=$2
op=$3
lib=$4
shift 4
if search "$search"; then
# Nasty, nasty, in --copy, arg 2 (if non-empty) is another config to search for, used with NO_GMP
if [ $op = "--copy" ]; then
if [ -z "$pkg" ]; then
pkg="$*"
elif grep "^\#[[:space:]]*define[[:space:]]*$pkg" config.h >/dev/null 2>&1 || \
echo $in | grep $pkg >/dev/null 2>&1; then
pkg="$lib"
elif search "$pkg"; then
pkg=""
else
pkg="$*"
pkg="$lib"
fi
elif grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
pkg=`$pkg --static $op $*`
elif search "${search}_STATIC"; then
pkg=`$pkg --static $op $lib`
else
pkg=`$pkg $op $*`
pkg=`$pkg $op $lib`
fi
if grep "^\#[[:space:]]*define[[:space:]]*${search}_STATIC" config.h >/dev/null 2>&1 || \
echo $in | grep ${search}_STATIC >/dev/null 2>&1; then
if search "${search}_STATIC"; then
if [ $op = "--libs" ] || [ $op = "--copy" ]; then
echo "-Wl,-Bstatic $pkg -Wl,-Bdynamic"
else
@@ -40,3 +42,4 @@ if grep "^\#[[:space:]]*define[[:space:]]*$search" config.h >/dev/null 2>&1 || \
fi
fi
done
+33 -1
View File
@@ -1,3 +1,34 @@
dnsmasq (2.83-1) unstable; urgency=high
* New upstream.
* Includes fixes to CVE-2020-25681 - CVE-2020-25687 inclusive.
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 15 Jan 2021 22:22:41 +0000
dnsmasq (2.82-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 22:22:41 +0000
dnsmasq (2.81-4) unstable; urgency=low
* Remove runit support when building for Ubuntu. (closes: #960401)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 21:52:44 +0000
dnsmasq (2.81-3) unstable; urgency=low
* Fixes to control file for bug 958100
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 19 Apr 2020 21:44:12 +0000
dnsmasq (2.81-2) unstable; urgency=low
* Fix FTBFS on kFreeBSD. (closes: #958100)
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 18 Apr 2020 18:34:15 +0000
dnsmasq (2.81-1) unstable; urgency=low
* New upstream.
@@ -12,8 +43,9 @@ dnsmasq (2.81-1) unstable; urgency=low
* Fix breakage of dig +trace. (closes: #942363)
* Fix build faliure with newer Nettle libraries. (closes: #940985)
* Support runscript init-system (closes: #929884)
* Security fix for CVE-2019-14834 (closes: #948373)
-- Simon Kelley <simon@thekelleys.org.uk> Mon, 27 Jan 2020 22:31:15 +0000
-- Simon Kelley <simon@thekelleys.org.uk> Wed, 8 Apr 2020 17:33:15 +0000
dnsmasq (2.80-1) unstable; urgency=low
+3 -2
View File
@@ -3,8 +3,9 @@ Section: net
Priority: optional
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
nettle-dev (>=2.4-3), libbsd-dev [!linux-any],
liblua5.2-dev, dh-runit, debhelper-compat (= 10)
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
liblua5.2-dev, dh-runit, debhelper-compat (= 10),
pkg-config
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
+1 -1
View File
@@ -1 +1 @@
debian/dnsmasq.runscript name=dnsmasq,logscript,since=2.80-1+runit
debian/dnsmasq.runscript name=dnsmasq,logscript,presubj
+17 -10
View File
@@ -98,9 +98,10 @@ ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DNSSEC
endif
ifneq ($(DEB_HOST_ARCH_OS),linux)
ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
# For strlcpy in FreeBSD
LDFLAGS += -lbsd
LIBS += $(shell ${PKG_CONFIG} --libs libbsd-overlay)
CFLAGS += $(shell ${PKG_CONFIG} --cflags libbsd-overlay)
endif
define build_tree
@@ -169,16 +170,20 @@ binary-indep: checkroot
-d debian/trees/daemon/etc/resolvconf/update.d \
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
-d debian/trees/daemon/usr/share/dnsmasq \
-d debian/trees/daemon/usr/share/doc/dnsmasq \
-d debian/trees/daemon/etc/default \
-d debian/trees/daemon/lib/systemd/system \
-d debian/trees/daemon/usr/lib/tmpfiles.d \
-d debian/trees/daemon/etc/insserv.conf.d
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper
dh_runit -pdnsmasq -Pdebian/trees/daemon
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm
if ! dpkg-vendor --derives-from Ubuntu; then \
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper; \
dh_runit -pdnsmasq -Pdebian/trees/daemon; \
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst; \
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm; \
cd debian/trees/daemon && find etc/sv -type f -printf '/%p\n' >>DEBIAN/conffiles; \
fi
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
@@ -190,7 +195,9 @@ binary-indep: checkroot
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
install -m 644 debian/copyright debian/trees/daemon/usr/share/doc/dnsmasq/copyright
install -m 644 debian/changelog debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
gzip -9n debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/dnsmasq.substvars -pdnsmasq -Pdebian/trees/daemon
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
@@ -200,7 +207,7 @@ binary-indep: checkroot
binary-arch: checkroot
$(call build_tree,debian/trees/base)
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
$(call add_docs,debian/trees/base)
else
@@ -219,7 +226,7 @@ endif
dpkg --build debian/trees/base ..
$(call build_tree,debian/trees/lua-base)
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
$(call add_docs,debian/trees/lua-base)
else
@@ -249,7 +256,7 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
install -m 755 -d debian/trees/utils/usr/share/man/man1
endif
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
+59 -31
View File
@@ -1,4 +1,4 @@
.TH DNSMASQ 8
.TH DNSMASQ 8 2020-04-05
.SH NAME
dnsmasq \- A lightweight DHCP and caching DNS server.
.SH SYNOPSIS
@@ -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. 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.
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 primary external nameserver.
.TP
.B --local-service
Accept DNS queries only from hosts whose address is on a local subnet,
@@ -366,10 +366,13 @@ 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
.B --enable-ubus[=<service-name>]
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.
Requires that dnsmasq has been built with UBus support. If the service
name is given, dnsmasq provides service at that namespace, rather than
the default which is
.B dnsmasq
.TP
.B \-o, --strict-order
By default, dnsmasq will send queries to any of the upstream servers
@@ -395,11 +398,13 @@ were previously disabled.
.TP
.B --stop-dns-rebind
Reject (and log) addresses from upstream nameservers which are in the
private IP ranges. This blocks an attack where a browser behind a
firewall is used to probe machines on the local network.
private ranges. This blocks an attack where a browser behind a
firewall is used to probe machines on the local network. For IPv6, the
private range covers the IPv4-mapped addresses in private space plus
all link-local (LL) and site-local (ULA) addresses.
.TP
.B --rebind-localhost-ok
Exempt 127.0.0.0/8 from rebinding checks. This address range is
Exempt 127.0.0.0/8 and ::1 from rebinding checks. This address range is
returned by realtime black hole servers, so blocking it may disable
these services.
.TP
@@ -423,7 +428,7 @@ Tells dnsmasq to never forward A or AAAA queries for plain names, without dots
or domain parts, to upstream nameservers. If the name is not known
from /etc/hosts or DHCP then a "not found" answer is returned.
.TP
.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>][@<source-ip>|<interface>[#<port>]]
.B \-S, --local, --server=[/[<domain>]/[domain/]][<ipaddr>[#<port>]][@<source-ip>|<interface>[#<port>]]
Specify IP address of upstream servers directly. Setting this flag does
not suppress reading of /etc/resolv.conf, use \fB--no-resolv\fP to do that. If one or more
optional domains are given, that server is used only for those domains
@@ -687,8 +692,8 @@ still marks the request so that no upstream nameserver will add client
address information either. The default is zero for both IPv4 and
IPv6. Note that upstream nameservers may be configured to return
different results based on this information, but the dnsmasq cache
does not take account. If a dnsmasq instance is configured such that
different results may be encountered, caching should be disabled.
does not take account. Caching is therefore disabled for such replies,
unless the subnet address being added is constant.
For example,
.B --add-subnet=24,96
@@ -856,7 +861,7 @@ in
options. If the lease time is given, then leases
will be given for that length of time. The lease time is in seconds,
or minutes (eg 45m) or hours (eg 1h) or "infinite". If not given,
the default lease time is one hour. The
the default lease time is one hour for IPv4 and one day for IPv6. The
minimum lease time is two minutes. For IPv6 ranges, the lease time
maybe "deprecated"; this sets the preferred lifetime sent in a DHCP
lease or router advertisement to zero, which causes clients to use
@@ -904,7 +909,7 @@ then the address can be simply ::
The optional
.B set:<tag>
sets an alphanumeric label which marks this network so that
dhcp options may be specified on a per-network basis.
DHCP options may be specified on a per-network basis.
When it is prefixed with 'tag:' instead, then its meaning changes from setting
a tag to matching it. Only one tag may be set, but more than one tag
may be matched.
@@ -1012,7 +1017,7 @@ may contain an IPv4 address or one or more IPv6 addresses, or both. IPv6 address
.B --dhcp-host=laptop,[1234::56]
IPv6 addresses may contain only the host-identifier part:
.B --dhcp-host=laptop,[::56]
in which case they act as wildcards in constructed dhcp ranges, with
in which case they act as wildcards in constructed DHCP ranges, with
the appropriate network part inserted. For IPv6, an address may include a prefix length:
.B --dhcp-host=laptop,[1234:50/126]
which (in this case) specifies four addresses, 1234::50 to 1234::53. This (an the ability
@@ -1349,7 +1354,7 @@ 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.
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
@@ -1475,6 +1480,22 @@ to allow netbooting. This mode is enabled using the
.B proxy
keyword in
.B --dhcp-range.
.TP
.B --dhcp-pxe-vendor=<vendor>[,...]
According to UEFI and PXE specifications, DHCP packets between PXE clients and
proxy PXE servers should have
.I PXEClient
in their vendor-class field. However, the firmware of computers from a few
vendors is customized to carry a different identifier in that field. This option
is used to consider such identifiers valid for identifying PXE clients. For
instance
.B --dhcp-pxe-vendor=PXEClient,HW-Client
will enable dnsmasq to also provide proxy PXE service to those PXE clients with
.I HW-Client
in as their identifier.
>>>>>>> 907def3... pxe: support pxe clients with custom vendor-class
.TP
.B \-X, --dhcp-lease-max=<number>
Limits dnsmasq to the specified maximum number of DHCP leases. The
@@ -1746,7 +1767,7 @@ option also forces the leasechange script to be called on changes
to the client-id and lease length and expiry time.
.TP
.B --script-on-renewal
Call the dhcp script when the lease expiry time changes, for instance when the
Call the DHCP script when the lease expiry time changes, for instance when the
lease is renewed.
.TP
.B --bridge-interface=<interface>,<alias>[,<alias>]
@@ -1762,25 +1783,34 @@ It is permissible to add more than one alias using more than one \fB--bridge-int
\fB--bridge-interface=int1,alias1,alias2\fP is exactly equivalent to
\fB--bridge-interface=int1,alias1 --bridge-interface=int1,alias2\fP
.TP
.B --shared-network=<interface>|<addr>,<addr>
The DHCP server determines which dhcp ranges are useable for allocating and
.B --shared-network=<interface>,<addr>
.PD 0
.TP
.B --shared-network=<addr>,<addr>
.PD 1v
The DHCP server determines which DHCP ranges are useable for allocating an
address to a DHCP client based on the network from which the DHCP request arrives,
and the IP configuration of the server's interface on that network. The shared-network
option extends the available subnets (and therefore dhcp ranges) beyond the
subnets configured on the arrival interface. The first argument is either the
name of an interface or an address which is configured on a local interface, and the
option extends the available subnets (and therefore DHCP ranges) beyond the
subnets configured on the arrival interface.
The first argument is either the
name of an interface, or an address that is configured on a local interface, and the
second argument is an address which defines another subnet on which addresses can be allocated.
To be useful, there must be suitable dhcp-range which allows address allocation on this subnet
and this dhcp-range MUST include the netmask. Use shared-network also needs extra
consideration of routing. Dnsmasq doesn't have the usual information which it uses to
To be useful, there must be a suitable dhcp-range which allows address allocation on this subnet
and this dhcp-range MUST include the netmask.
Using shared-network also needs extra
consideration of routing. Dnsmasq does not have the usual information that it uses to
determine the default route, so the default route option (or other routing) MUST be
manually configured. The client must have a route to the server: if the two-address form
of shared-network is used, this will be to the first specified address. If the interface,address
configured manually. The client must have a route to the server: if the two-address form
of shared-network is used, this needs to be to the first specified address. If the interface,address
form is used, there must be a route to all of the addresses configured on the interface.
The two-address form of shared-network is also usable with a DHCP relay: the first address
is the address of the relay and the second, as before, specifies an extra subnet which
may be allocated.
addresses may be allocated from.
.TP
.B \-s, --domain=<domain>[,<address range>[,local]]
@@ -1790,7 +1820,7 @@ firstly it causes the DHCP server to return the domain to any hosts
which request it, and secondly it sets the domain which it is legal
for DHCP-configured hosts to claim. The intention is to constrain
hostnames so that an untrusted host on the LAN cannot advertise
its name via dhcp as e.g. "microsoft.com" and capture traffic not
its name via DHCP as e.g. "microsoft.com" and capture traffic not
meant for it. If no domain suffix is specified, then any DHCP
hostname with a domain part (ie with a period) will be disallowed
and logged. If suffix is specified, then hostnames with a domain
@@ -1881,7 +1911,7 @@ The mtu: parameter may be an arbitrary interface name, in which case the MTU val
for (eg) advertising the MTU of a WAN interface on the other interfaces of a router.
.TP
.B --dhcp-reply-delay=[tag:<tag>,]<integer>
Delays sending DHCPOFFER and proxydhcp replies for at least the specified number of seconds.
Delays sending DHCPOFFER and PROXYDHCP replies for at least the specified number of seconds.
This can be used as workaround for bugs in PXE boot firmware that does not function properly when
receiving an instant reply.
This option takes into account the time already spent waiting (e.g. performing ping check) if any.
@@ -2017,7 +2047,7 @@ and
.I /etc/ethers
and any file given by \fB--dhcp-hostsfile\fP, \fB--dhcp-hostsdir\fP, \fB--dhcp-optsfile\fP,
\fB--dhcp-optsdir\fP, \fB--addn-hosts\fP or \fB--hostsdir\fP.
The dhcp lease change script is called for all
The DHCP lease change script is called for all
existing DHCP leases. If
.B
--no-poll
@@ -2195,7 +2225,6 @@ as is the tag "bootp", allowing some control over the options returned to
different classes of hosts.
.SH AUTHORITATIVE CONFIGURATION
.PP
Configuring dnsmasq to act as an authoritative DNS server is
complicated by the fact that it involves configuration of external DNS
servers to provide delegation. We will walk through three scenarios of
@@ -2365,7 +2394,6 @@ used, and must match the zone's domain.
.SH EXIT CODES
.PP
0 - Dnsmasq successfully forked into the background, or terminated
normally if backgrounding is not enabled.
.PP
+56 -71
View File
@@ -9,10 +9,10 @@
# Simon Kelley <simon@thekelleys.org.uk>, 2005.
msgid ""
msgstr ""
"Project-Id-Version: dnsmasq 2.80\n"
"Project-Id-Version: dnsmasq 2.81\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-06-18 12:24+0100\n"
"PO-Revision-Date: 2018-09-29 00:13+0200\n"
"PO-Revision-Date: 2020-03-08 20:25+0100\n"
"Last-Translator: Conrad Kostecki <conrad@kostecki.com>\n"
"Language-Team: German <de@li.org>\n"
"Language: de\n"
@@ -20,7 +20,7 @@ msgstr ""
"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.1.1\n"
"X-Generator: Poedit 2.3\n"
"X-Poedit-SourceCharset: UTF-8\n"
#: cache.c:559
@@ -431,7 +431,7 @@ msgstr "DBus-Schnittstelle zum Festlegen vorgelagerter Server usw. festlegen."
#: option.c:431
msgid "Enable the UBus interface."
msgstr ""
msgstr "UBus-Schnittstelle aktivieren."
#: option.c:432
msgid "Do not provide DHCP on this interface, only provide DNS."
@@ -451,7 +451,7 @@ msgstr "DHCP-Anfragen von Alias-Schnittstellen für die Hauptschnittstelle beant
#: option.c:436
msgid "Specify extra networks sharing a broadcast domain for DHCP"
msgstr ""
msgstr "Geben Sie zusätzliche Netzwerke an, die eine Broadcast-Domäne für DHCP gemeinsam nutzen"
#: option.c:437
msgid "Disable ICMP echo address checking in the DHCP server."
@@ -546,7 +546,7 @@ msgstr "Bereich für vorübergehende Ports für TFTP-Übertragungen."
#: option.c:459
msgid "Use only one port for TFTP server."
msgstr ""
msgstr "Bitte nur einen Port für den TFTP-Server nutzen."
#: option.c:460
msgid "Extra logging for DHCP."
@@ -577,9 +577,8 @@ msgid "Set tag if client includes matching option in request."
msgstr "Marke setzen, wenn Klient eine entsprechende Option anfragt."
#: option.c:467
#, fuzzy
msgid "Set tag if client provides given name."
msgstr "Marke setzen, wenn Klient eine entsprechende Option anfragt."
msgstr "Setzt das Tag, wenn der Client diesen Namen anbietet."
#: option.c:468
msgid "Use alternative ports for DHCP."
@@ -651,9 +650,8 @@ msgid "Attempt to allocate sequential IP addresses to DHCP clients."
msgstr "Versuche sequenzielle IP-Adressen an DHCP-Klienten zu vergeben."
#: option.c:485
#, fuzzy
msgid "Ignore client identifier option sent by DHCP clients."
msgstr "Von DHCP-Clients gelieferte Hostnamen ignorieren."
msgstr "Ignorieren Sie die von DHCP-Clients gesendete Client-ID-Option."
#: option.c:486
msgid "Copy connection-track mark from queries to upstream connections."
@@ -677,7 +675,7 @@ msgstr "Spezifiziere Host (A/AAAA und PTR) Einträge"
#: option.c:491
msgid "Specify certification authority authorization record"
msgstr ""
msgstr "Geben Sie den Autorisierungsdatensatz der Zertifizierungsstelle an"
#: option.c:492
msgid "Specify arbitrary DNS resource record"
@@ -781,20 +779,19 @@ msgstr "Verzögere DHCP-Antworten für mindestens Anzahl von Sekunden."
#: option.c:517
msgid "Enables DHCPv4 Rapid Commit option."
msgstr ""
msgstr "Aktiviert die Option DHCPv4 Rapid Commit."
#: option.c:518
msgid "Path to debug packet dump file"
msgstr ""
msgstr "Pfad zur Debug-Paketdatei, wohin gedumpt werden soll"
#: option.c:519
msgid "Mask which packets to dump"
msgstr ""
msgstr "Maskiere Pakete, welche gedumpt werden sollen"
#: option.c:520
#, fuzzy
msgid "Call dhcp-script when lease expiry changes."
msgstr "Rufe dhcp-script mit Änderungen an der lokalen ARP-Tabelle auf."
msgstr "Rufe dhcp-script auf, wenn der Ablauf des Leases sich ändert."
#: option.c:725
#, c-format
@@ -931,7 +928,7 @@ msgstr "unzulässige Brücken-Schnittstelle"
#: option.c:2941
msgid "bad shared-network"
msgstr ""
msgstr "unzulässiger geteiltes Netz"
#: option.c:2996
msgid "only one tag allowed"
@@ -970,9 +967,8 @@ msgid "bad hex constant"
msgstr "Falscher Hexwert"
#: option.c:3315
#, fuzzy
msgid "bad IPv6 prefix"
msgstr "unzulässiger Präfix"
msgstr "unzulässiger IPv6-Präfix"
#: option.c:3362
#, c-format
@@ -1008,9 +1004,8 @@ msgid "bad DUID"
msgstr "unzulässige DUID"
#: option.c:4023
#, fuzzy
msgid "missing address in alias"
msgstr "Adresse ungültig"
msgstr "Adresse fehlt in Alias"
#: option.c:4029
msgid "invalid alias range"
@@ -1037,9 +1032,8 @@ msgid "bad RR record"
msgstr "unzulässiger RR-Eintrag"
#: option.c:4236
#, fuzzy
msgid "bad CAA record"
msgstr "unzulässiger RR-Eintrag"
msgstr "unzulässiger CAA-Eintrag"
#: option.c:4265
msgid "bad TXT record"
@@ -1071,7 +1065,7 @@ msgstr "Unzulässiger Name in host-record"
#: option.c:4444
msgid "bad value for dnssec-check-unsigned"
msgstr ""
msgstr "Ungültiger Wert für dnssec-check-unsigned"
#: option.c:4480
msgid "bad trust anchor"
@@ -1310,9 +1304,9 @@ msgid "domain"
msgstr "Domain"
#: network.c:1543
#, fuzzy, c-format
#, c-format
msgid "using only locally-known addresses for %s %s"
msgstr "Benutze lokale Adressen nur für %s %s"
msgstr "Benutze nur lokal-bekannte Adressen für %s %s"
#: network.c:1546
#, c-format
@@ -1394,9 +1388,8 @@ msgid "loop detection not available: set HAVE_LOOP in src/config.h"
msgstr "Loop-Erkennung nicht verfügbar, Aktiviere HAVE_LOOP in src/config.h"
#: dnsmasq.c:232
#, fuzzy
msgid "Ubus not available: set HAVE_UBUS in src/config.h"
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
msgstr "UBus nicht verfügbar: setzen Sie HAVE_UBUS in src/config.h"
#: dnsmasq.c:236
msgid "max_port cannot be smaller than min_port"
@@ -1404,7 +1397,7 @@ msgstr "max_port darf nicht kleiner als min_port sein"
#: dnsmasq.c:243
msgid "--auth-server required when an auth zone is defined."
msgstr ""
msgstr "--Auth-Server ist notwendig, wenn eine Auth-Zone definiert ist."
#: dnsmasq.c:248
msgid "zone serial must be configured in --auth-soa"
@@ -1429,9 +1422,8 @@ msgid "unknown interface %s"
msgstr "unbekannte Schnittstelle %s"
#: dnsmasq.c:406
#, fuzzy
msgid "Packet dumps not available: set HAVE_DUMP in src/config.h"
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
msgstr "Paketdump nicht verfügbar: setzen Sie HAVE_DUMP in src/config.h"
#: dnsmasq.c:416 dnsmasq.c:1171
#, c-format
@@ -1443,9 +1435,8 @@ msgid "DBus not available: set HAVE_DBUS in src/config.h"
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
#: dnsmasq.c:429
#, fuzzy
msgid "UBus not available: set HAVE_UBUS in src/config.h"
msgstr "DBus nicht verfügbar: setzen Sie HAVE_DBUS in src/config.h"
msgstr "UBus nicht verfügbar: setzen Sie HAVE_UBUS in src/config.h"
#: dnsmasq.c:459
#, c-format
@@ -1455,7 +1446,7 @@ msgstr "Unbekannter Benutzer oder Gruppe: %s"
#: dnsmasq.c:535
#, c-format
msgid "process is missing required capability %s"
msgstr ""
msgstr "Prozess benötigt nicht vorhandene Fähigkeit %s"
#: dnsmasq.c:567
#, c-format
@@ -1475,7 +1466,7 @@ msgstr "gestartet, Version %s, Cachegröße %d"
#: dnsmasq.c:822
msgid "cache size greater than 10000 may cause performance issues, and is unlikely to be useful."
msgstr ""
msgstr "Die Cachegröße größer als 10000 kann Performanceprobleme verursachen und der positive Nutzen ist zudem unwahrscheinlich."
#: dnsmasq.c:825
#, c-format
@@ -1500,18 +1491,16 @@ msgid "DBus support enabled: bus connection pending"
msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung"
#: dnsmasq.c:850
#, fuzzy
msgid "UBus support enabled: connected to system bus"
msgstr "DBus-Unterstützung eingeschaltet: mit Systembus verbunden"
msgstr "UBus-Unterstützung aktiviert: Mit Systembus verbunden"
#: dnsmasq.c:852
#, fuzzy
msgid "UBus support enabled: bus connection pending"
msgstr "DBus-Unterstützung eingeschaltet: warte auf Systembus-Verbindung"
msgstr "UBus-Unterstützung aktiviert: BUS-Verbindung wird hergestellt"
#: dnsmasq.c:872
msgid "DNSSEC validation enabled but all unsigned answers are trusted"
msgstr ""
msgstr "DNSSEC-Validierung aktiviert, jedoch wird allen unsignierten Antworten vertraut"
#: dnsmasq.c:874
msgid "DNSSEC validation enabled"
@@ -1528,7 +1517,7 @@ msgstr "DNSSEC Signatur-Zeitstempel werden erst überprüft, sobald die Systemuh
#: dnsmasq.c:884
#, c-format
msgid "configured with trust anchor for %s keytag %u"
msgstr ""
msgstr "konfiguriert mit Vertrauensanker für% s Schlüsselwort % u"
#: dnsmasq.c:890
#, c-format
@@ -1580,9 +1569,8 @@ msgid "secure mode"
msgstr "sicherer Modus"
#: dnsmasq.c:961
#, fuzzy
msgid "single port mode"
msgstr "unzulässige Portnummer"
msgstr "Einzelport-Modus"
#: dnsmasq.c:964
#, c-format
@@ -1762,14 +1750,14 @@ msgid "DHCP relay %s -> %s"
msgstr "DHCP Weiterleitung %s -> %s"
#: lease.c:64
#, fuzzy, c-format
#, c-format
msgid "ignoring invalid line in lease database: %s %s %s %s ..."
msgstr "Fehler beim Parsen der Lease-Datenbank, ungültige Zeile: %s %s %s %s ..."
msgstr "ignoriere fehlerhafte Zeile in Lease-Datenbank: %s %s %s %s ..."
#: lease.c:101
#, c-format
msgid "ignoring invalid line in lease database, bad address: %s"
msgstr ""
msgstr "ignoriere fehlerhafte Zeile in Lease-Datenbank, ungültige Adresse: %s"
#: lease.c:108
msgid "too many stored leases"
@@ -1781,9 +1769,8 @@ msgid "cannot open or create lease file %s: %s"
msgstr "kann Lease-Datei %s nicht öffnen: %s"
#: lease.c:185
#, fuzzy
msgid "failed to parse lease database cleanly"
msgstr "Fehler beim Parsen der Lease-Datenbank, ungültige Zeile: %s %s %s %s ..."
msgstr "Fehler beim korrekten Parsen der Lease-Datenbank"
#: lease.c:188
#, c-format
@@ -2287,12 +2274,12 @@ msgstr "Prüfe jetzt DNSSEC Signatur-Zeitstempel."
#: dnssec.c:902
#, c-format
msgid "Insecure DS reply received for %s, check domain configuration and upstream DNS server DNSSEC support"
msgstr ""
msgstr "Unsichere DS-Antwort für %s, bitte Domainkonfiguration und Upstream DNS-Server für DNSSEC-Unterstützung überprüfen"
#: blockdata.c:55
#, fuzzy, c-format
#, c-format
msgid "pool memory in use %u, max %u, allocated %u"
msgstr "DNSSEC Speicher in Benutzung %u, Max %u, zugewiesen %u"
msgstr "Pool Speicher in Benutzung %u, Max %u, zugewiesen %u"
#: tables.c:61
#, c-format
@@ -2369,65 +2356,63 @@ msgid "inotify, new or changed file %s"
msgstr "inotify, neue oder geänderte Datei %s"
#: dump.c:64
#, fuzzy, c-format
#, c-format
msgid "cannot create %s: %s"
msgstr "kann %s nicht lesen: %s"
msgstr "kann %s nicht erstellen: %s"
#: dump.c:70
#, fuzzy, c-format
#, c-format
msgid "bad header in %s"
msgstr "Adresse in Nutzung"
msgstr "Unzulässiger Header in %s"
#: dump.c:201
#, fuzzy
msgid "failed to write packet dump"
msgstr "Fehlgeschlagen, folgendes Paket zu senden: %s"
msgstr "schreiben des Paketmitschnitt fehlgeschlagen"
#: dump.c:203
#, c-format
msgid "dumping UDP packet %u mask 0x%04x"
msgstr ""
msgstr "Dumpe UDP Paket %u Maske 0x%04x"
#: ubus.c:52
#, c-format
msgid "UBus subscription callback: %s subscriber(s)"
msgstr ""
msgstr "UBus-Subskription Rückruf: %s Teilnehmer"
#: ubus.c:73
#, fuzzy, c-format
#, c-format
msgid "Cannot reconnect to UBus: %s"
msgstr "Kann Logdatei %s nicht öffnen: %s"
msgstr "Kann mit UBus nicht erneut verbinden: %s"
#: ubus.c:89
msgid "Cannot initialize UBus: connection failed"
msgstr ""
msgstr "Kann UBus nicht initialisieren: Verbindung fehlgeschlagen"
#: ubus.c:102
#, fuzzy, c-format
#, c-format
msgid "Cannot add object to UBus: %s"
msgstr "Kann Logdatei %s nicht öffnen: %s"
msgstr "Kann Objekt zu UBus nicht hinzufügen: %s"
#: ubus.c:112
#, fuzzy
msgid "Connected to system UBus"
msgstr "Mit System-DBus verbunden"
msgstr "Mit System-UBus verbunden"
#: ubus.c:122
msgid "Cannot set UBus listeners: no connection"
msgstr ""
msgstr "Kann UBus-Zuhörer nicht setzen: Keine Verbindung"
#: ubus.c:142
msgid "Cannot poll UBus listeners: no connection"
msgstr ""
msgstr "Kann UBus-Zuhörer nicht abfragen: Keine Verbindung"
#: ubus.c:155
msgid "Disconnecting from UBus"
msgstr ""
msgstr "Mit System-UBus trennen"
#: ubus.c:199
#, fuzzy, c-format
#, c-format
msgid "Failed to send UBus event: %s"
msgstr "Fehlgeschlagen, folgendes Paket zu senden: %s"
msgstr "Fehlgeschlagen, folgendes UBus-Event zu senden: %s"
#~ msgid "Specify DHCPv6 prefix class"
#~ msgstr "Spezifiziere DHCPv6 Prefix Klasse"
+13 -9
View File
@@ -628,16 +628,20 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
{
struct name_list *secondary;
newoffset = ansp - (unsigned char *)header;
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
/* Only include the machine running dnsmasq if it's acting as an auth server */
if (daemon->authinterface)
{
if (offset == 0)
offset = newoffset;
if (ns)
anscount++;
else
authcount++;
newoffset = ansp - (unsigned char *)header;
if (add_resource_record(header, limit, &trunc, -offset, &ansp,
daemon->auth_ttl, NULL, T_NS, C_IN, "d", offset == 0 ? authname : NULL, daemon->authserver))
{
if (offset == 0)
offset = newoffset;
if (ns)
anscount++;
else
authcount++;
}
}
if (!subnet)
+17 -4
View File
@@ -472,16 +472,29 @@ void cache_start_insert(void)
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
time_t now, unsigned long ttl, unsigned int flags)
{
/* Don't log DNSSEC records here, done elsewhere */
if (flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV))
#ifdef HAVE_DNSSEC
if (flags & (F_DNSKEY | F_DS))
{
/* The DNSSEC validation process works by getting needed records into the
cache, then retrying the validation until they are all in place.
This can be messed up by very short TTLs, and _really_ messed up by
zero TTLs, so we force the TTL to be at least long enough to do a validation.
Ideally, we should use some kind of reference counting so that records are
locked until the validation that asked for them is complete, but this
is much easier, and just as effective. */
if (ttl < DNSSEC_MIN_TTL)
ttl = DNSSEC_MIN_TTL;
}
else
#endif
{
/* Don't log DNSSEC records here, done elsewhere */
log_query(flags | F_UPSTREAM, name, addr, NULL);
/* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
ttl = daemon->max_cache_ttl;
if (daemon->min_cache_ttl != 0 && daemon->min_cache_ttl > ttl)
ttl = daemon->min_cache_ttl;
}
}
return really_insert(name, addr, class, now, ttl, flags);
}
+12 -1
View File
@@ -40,9 +40,11 @@
#define DHCP_PACKET_MAX 16384 /* hard limit on DHCP packet size */
#define SMALLDNAME 50 /* most domain names are smaller than this */
#define CNAME_CHAIN 10 /* chains longer than this atr dropped for loop protection */
#define DNSSEC_MIN_TTL 60 /* DNSKEY and DS records in cache last at least this long */
#define HOSTSFILE "/etc/hosts"
#define ETHERSFILE "/etc/ethers"
#define DEFLEASE 3600 /* default lease time, 1 hour */
#define DEFLEASE 3600 /* default DHCPv4 lease time, one hour */
#define DEFLEASE6 (3600*24) /* default lease time for DHCPv6. One day. */
#define CHUSER "nobody"
#define CHGRP "dip"
#define TFTP_MAX_CONNECTIONS 50 /* max simultaneous connections */
@@ -50,6 +52,7 @@
#define RANDFILE "/dev/urandom"
#define DNSMASQ_SERVICE "uk.org.thekelleys.dnsmasq" /* Default - may be overridden by config */
#define DNSMASQ_PATH "/uk/org/thekelleys/dnsmasq"
#define DNSMASQ_UBUS_NAME "dnsmasq" /* Default - may be overridden by config */
#define AUTH_TTL 600 /* default TTL for auth DNS */
#define SOA_REFRESH 1200 /* SOA refresh default */
#define SOA_RETRY 180 /* SOA retry default */
@@ -117,6 +120,9 @@ HAVE_AUTH
define this to include the facility to act as an authoritative DNS
server for one or more zones.
HAVE_NETTLEHASH
include just hash function from nettle, but no DNSSEC.
HAVE_DNSSEC
include DNSSEC validator.
@@ -184,6 +190,7 @@ RESOLVFILE
/* #define HAVE_IDN */
/* #define HAVE_LIBIDN2 */
/* #define HAVE_CONNTRACK */
/* #define HAVE_NETTLEHASH */
/* #define HAVE_DNSSEC */
@@ -417,6 +424,10 @@ static char *compile_opts =
"no-"
#endif
"auth "
#if !defined(HAVE_NETTLEHASH) && !defined(HAVE_DNSSEC)
"no-"
#endif
"nettlehash "
#ifndef HAVE_DNSSEC
"no-"
#endif
+7
View File
@@ -25,6 +25,9 @@
#if NETTLE_VERSION_MAJOR == 3 && NETTLE_VERSION_MINOR >= 6
# include <nettle/gostdsa.h>
#endif
#endif
#if defined(HAVE_DNSSEC) || defined(HAVE_NETTLEHASH)
#include <nettle/nettle-meta.h>
#include <nettle/bignum.h>
@@ -167,6 +170,10 @@ int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **diges
return 1;
}
#endif
#ifdef HAVE_DNSSEC
static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
unsigned char *digest, size_t digest_len, int algo)
+1 -1
View File
@@ -237,7 +237,7 @@ static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & SERV_LOOP)
{
prettyprint_addr(&serv->addr, daemon->addrbuff);
(void)prettyprint_addr(&serv->addr, daemon->addrbuff);
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
}
+12 -3
View File
@@ -38,7 +38,7 @@ void dhcp_common_init(void)
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
{
ssize_t sz;
ssize_t sz, new_sz;
while (1)
{
@@ -65,9 +65,18 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
}
}
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
while ((new_sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
/* Some kernels seem to ignore MSG_PEEK, and dequeue the packet anyway.
If that happens we get EAGAIN here because the socket is non-blocking.
Use the result of the original testing recvmsg as long as the buffer
was big enough. There's a small race here that may lose the odd packet,
but it's UDP anyway. */
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
if (new_sz == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))
new_sz = sz;
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
}
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
+41 -33
View File
@@ -58,6 +58,7 @@ int main (int argc, char **argv)
char *bound_device = NULL;
int did_bind = 0;
struct server *serv;
char *netlink_warn;
#endif
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
struct dhcp_context *context;
@@ -89,11 +90,15 @@ int main (int argc, char **argv)
sigaction(SIGPIPE, &sigact, NULL);
umask(022); /* known umask, create leases and pid files as 0644 */
rand_init(); /* Must precede read_opts() */
read_opts(argc, argv, compile_opts);
#ifdef HAVE_LINUX_NETWORK
daemon->kernel_version = kernel_version();
#endif
if (daemon->edns_pktsz < PACKETSZ)
daemon->edns_pktsz = PACKETSZ;
@@ -323,7 +328,7 @@ int main (int argc, char **argv)
#endif
#if defined(HAVE_LINUX_NETWORK)
netlink_init();
netlink_warn = netlink_init();
#elif defined(HAVE_BSD_NETWORK)
route_init();
#endif
@@ -942,6 +947,9 @@ int main (int argc, char **argv)
# ifdef HAVE_LINUX_NETWORK
if (did_bind)
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
if (netlink_warn)
my_syslog(LOG_WARNING, netlink_warn);
# endif
/* after dhcp_construct_contexts */
@@ -1679,7 +1687,7 @@ static int set_dns_listeners(time_t now)
/* will we be able to get memory? */
if (daemon->port != 0)
get_new_frec(now, &wait, 0);
get_new_frec(now, &wait, NULL);
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
poll_listen(serverfdp->fd, POLLIN);
@@ -1816,7 +1824,8 @@ static void check_dns_listeners(time_t now)
addr.addr4 = tcp_addr.in.sin_addr;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index)
if (iface->index == if_index &&
iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
@@ -1855,31 +1864,30 @@ static void check_dns_listeners(time_t now)
else
{
int i;
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
unsigned char a;
read_write(pipefd[0], &a, 1, 1);
#endif
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
{
char a;
(void)a; /* suppress potential unused warning */
daemon->tcp_pids[i] = p;
daemon->tcp_pipes[i] = pipefd[0];
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
retry_send(read(pipefd[0], &a, 1));
#endif
break;
}
}
@@ -1911,16 +1919,16 @@ static void check_dns_listeners(time_t now)
terminate the process. */
if (!option_bool(OPT_DEBUG))
{
char a = 0;
(void)a; /* suppress potential unused warning */
#ifdef HAVE_LINUX_NETWORK
/* See comment above re: netlink socket. */
unsigned char a = 0;
close(daemon->netlinkfd);
read_write(pipefd[1], &a, 1, 0);
#endif
alarm(CHILD_LIFETIME);
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
#ifdef HAVE_LINUX_NETWORK
/* See comment above re netlink socket. */
close(daemon->netlinkfd);
retry_send(write(pipefd[1], &a, 1));
#endif
}
/* start with no upstream connections. */
@@ -1947,8 +1955,10 @@ static void check_dns_listeners(time_t now)
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
if (!option_bool(OPT_DEBUG))
{
close(daemon->pipe_to_parent);
flush_log();
_exit(0);
}
@@ -2108,6 +2118,4 @@ int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
return 0;
}
#endif
#endif /* HAVE_DHCP */
+40 -19
View File
@@ -141,6 +141,7 @@ typedef unsigned long long u64;
#endif
#if defined(HAVE_LINUX_NETWORK)
#include <linux/version.h>
#include <linux/sockios.h>
#include <linux/capability.h>
/* There doesn't seem to be a universally-available
@@ -156,7 +157,7 @@ extern int capget(cap_user_header_t header, cap_user_data_t data);
#include <priv.h>
#endif
#ifdef HAVE_DNSSEC
#if defined(HAVE_DNSSEC) || defined(HAVE_NETTLEHASH)
# include <nettle/nettle-meta.h>
#endif
@@ -571,7 +572,8 @@ struct irec {
};
struct listener {
int fd, tcpfd, tftpfd, family;
int fd, tcpfd, tftpfd, used;
union mysockaddr addr;
struct irec *iface; /* only sometimes valid for non-wildcard */
struct listener *next;
};
@@ -651,23 +653,25 @@ struct hostsfile {
#define FREC_DO_QUESTION 64
#define FREC_ADDED_PHEADER 128
#define FREC_TEST_PKTSZ 256
#define FREC_HAS_EXTRADATA 512
#define FREC_HAS_EXTRADATA 512
#define FREC_HAS_PHEADER 1024
#define FREC_NO_CACHE 2048
#ifdef HAVE_DNSSEC
#define HASH_SIZE 20 /* SHA-1 digest size */
#else
#define HASH_SIZE sizeof(int)
#endif
#define HASH_SIZE 32 /* SHA-256 digest size */
struct frec {
union mysockaddr source;
union all_addr dest;
struct frec_src {
union mysockaddr source;
union all_addr dest;
unsigned int iface, log_id;
unsigned short orig_id;
struct frec_src *next;
} frec_src;
struct server *sentto; /* NULL means free */
struct randfd *rfd4;
struct randfd *rfd6;
unsigned int iface;
unsigned short orig_id, new_id;
int log_id, fd, forwardall, flags;
unsigned short new_id;
int fd, forwardall, flags;
time_t time;
unsigned char *hash[HASH_SIZE];
#ifdef HAVE_DNSSEC
@@ -827,6 +831,7 @@ struct dhcp_opt {
#define DHOPT_RFC3925 2048
#define DHOPT_TAGOK 4096
#define DHOPT_ADDR6 8192
#define DHOPT_VENDOR_PXE 16384
struct dhcp_boot {
char *file, *sname, *tftp_sname;
@@ -850,6 +855,8 @@ struct pxe_service {
struct pxe_service *next;
};
#define DHCP_PXE_DEF_VENDOR "PXEClient"
#define MATCH_VENDOR 1
#define MATCH_USER 2
#define MATCH_CIRCUIT 3
@@ -865,6 +872,11 @@ struct dhcp_vendor {
struct dhcp_vendor *next;
};
struct dhcp_pxe_vendor {
char *data;
struct dhcp_pxe_vendor *next;
};
struct dhcp_mac {
unsigned int mask;
int hwaddr_len, hwaddr_type;
@@ -940,6 +952,7 @@ struct shared_network {
#define CONTEXT_OLD (1u<<16)
#define CONTEXT_V6 (1u<<17)
#define CONTEXT_RA_OFF_LINK (1u<<18)
#define CONTEXT_SETLEASE (1u<<19)
struct ping_result {
struct in_addr addr;
@@ -1037,6 +1050,7 @@ extern struct daemon {
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_pxe_vendor *dhcp_pxe_vendors;
struct dhcp_vendor *dhcp_vendors;
struct dhcp_mac *dhcp_macs;
struct dhcp_boot *boot_config;
@@ -1062,6 +1076,7 @@ extern struct daemon {
unsigned int duid_enterprise, duid_config_len;
unsigned char *duid_config;
char *dbus_name;
char *ubus_name;
char *dump_file;
int dump_mask;
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
@@ -1084,6 +1099,8 @@ extern struct daemon {
int back_to_the_future;
#endif
struct frec *frec_list;
struct frec_src *free_frec_src;
int frec_src_count;
struct serverfd *sfds;
struct irec *interfaces;
struct listener *listeners;
@@ -1108,7 +1125,7 @@ extern struct daemon {
int inotifyfd;
#endif
#if defined(HAVE_LINUX_NETWORK)
int netlinkfd;
int netlinkfd, kernel_version;
#elif defined(HAVE_BSD_NETWORK)
int dhcp_raw_fd, dhcp_icmp_fd, routefd;
#endif
@@ -1216,7 +1233,6 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
struct bogus_addr *baddr, time_t now);
int check_for_ignored_address(struct dns_header *header, size_t qlen, struct bogus_addr *baddr);
int check_for_local_domain(char *name, time_t now);
unsigned int questions_crc(struct dns_header *header, size_t plen, char *name);
size_t resize_packet(struct dns_header *header, size_t plen,
unsigned char *pheader, size_t hlen);
int add_resource_record(struct dns_header *header, char *limit, int *truncp,
@@ -1241,9 +1257,11 @@ int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, ch
int check_unsigned, int *neganswer, int *nons, int *nsec_ttl);
int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen);
size_t filter_rrsigs(struct dns_header *header, size_t plen);
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name);
int setup_timestamp(void);
/* hash_questions.c */
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name);
/* crypto.c */
const struct nettle_hash *hash_find(char *name);
int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp);
@@ -1288,6 +1306,9 @@ int read_write(int fd, unsigned char *packet, int size, int rw);
void close_fds(long max_fd, int spare1, int spare2, int spare3);
int wildcard_match(const char* wildcard, const char* match);
int wildcard_matchn(const char* wildcard, const char* match, int num);
#ifdef HAVE_LINUX_NETWORK
int kernel_version(void);
#endif
/* log.c */
void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN;
@@ -1319,7 +1340,7 @@ void receive_query(struct listener *listen, time_t now);
unsigned char *tcp_request(int confd, time_t now,
union mysockaddr *local_addr, struct in_addr netmask, int auth_dns);
void server_gone(struct server *server);
struct frec *get_new_frec(time_t now, int *wait, int force);
struct frec *get_new_frec(time_t now, int *wait, struct frec *force);
int send_from(int fd, int nowild, char *packet, size_t len,
union mysockaddr *to, union all_addr *source,
unsigned int iface);
@@ -1445,7 +1466,7 @@ void clear_cache_and_reload(time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
void netlink_init(void);
char *netlink_init(void);
void netlink_multicast(void);
#endif
@@ -1638,7 +1659,7 @@ size_t add_pseudoheader(struct dns_header *header, size_t plen, unsigned char *l
unsigned short udp_sz, int optno, unsigned char *opt, size_t optlen, int set_do, int replace);
size_t add_do_bit(struct dns_header *header, size_t plen, unsigned char *limit);
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, time_t now, int *check_subnet);
union mysockaddr *source, time_t now, int *check_subnet, int *cacheable);
int check_source(struct dns_header *header, size_t plen, unsigned char *pseudoheader, union mysockaddr *peer);
/* arp.c */
+175 -159
View File
@@ -223,138 +223,147 @@ static int check_date_range(unsigned long curtime, u32 date_start, u32 date_end)
&& serial_compare_32(curtime, date_end) == SERIAL_LT;
}
/* Return bytes of canonicalised rdata, when the return value is zero, the remaining
data, pointed to by *p, should be used raw. */
static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, int bufflen,
unsigned char **p, u16 **desc)
/* Return bytes of canonicalised rrdata one by one.
Init state->ip with the RR, and state->end with the end of same.
Init state->op to NULL.
Init state->desc to RR descriptor.
Init state->buff with a MAXDNAME * 2 buffer.
After each call which returns 1, state->op points to the next byte of data.
On returning 0, the end has been reached.
*/
struct rdata_state {
u16 *desc;
size_t c;
unsigned char *end, *ip, *op;
char *buff;
};
static int get_rdata(struct dns_header *header, size_t plen, struct rdata_state *state)
{
int d = **desc;
int d;
/* No more data needs mangling */
if (d == (u16)-1)
if (state->op && state->c != 1)
{
/* If there's more data than we have space for, just return what fits,
we'll get called again for more chunks */
if (end - *p > bufflen)
{
memcpy(buff, *p, bufflen);
*p += bufflen;
return bufflen;
}
return 0;
state->op++;
state->c--;
return 1;
}
(*desc)++;
if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
/* domain-name, canonicalise */
return to_wire(buff);
else
{
/* plain data preceding a domain-name, don't run off the end of the data */
if ((end - *p) < d)
d = end - *p;
while (1)
{
d = *(state->desc);
if (d != 0)
if (d == (u16)-1)
{
memcpy(buff, *p, d);
*p += d;
/* all the bytes to the end. */
if ((state->c = state->end - state->ip) != 0)
{
state->op = state->ip;
state->ip = state->end;;
}
else
return 0;
}
else
{
state->desc++;
if (d == (u16)0)
{
/* domain-name, canonicalise */
int len;
if (!extract_name(header, plen, &state->ip, state->buff, 1, 0) ||
(len = to_wire(state->buff)) == 0)
continue;
state->c = len;
state->op = (unsigned char *)state->buff;
}
else
{
/* plain data preceding a domain-name, don't run off the end of the data */
if ((state->end - state->ip) < d)
d = state->end - state->ip;
if (d == 0)
continue;
state->op = state->ip;
state->c = d;
state->ip += d;
}
}
return d;
return 1;
}
}
/* Bubble sort the RRset into the canonical order.
Note that the byte-streams from two RRs may get unsynced: consider
RRs which have two domain-names at the start and then other data.
The domain-names may have different lengths in each RR, but sort equal
------------
|abcde|fghi|
------------
|abcd|efghi|
------------
leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
*/
/* Bubble sort the RRset into the canonical order. */
static int sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx,
unsigned char **rrset, char *buff1, char *buff2)
{
int swap, quit, i, j;
int swap, i, j;
do
{
for (swap = 0, i = 0; i < rrsetidx-1; i++)
{
int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
u16 *dp1, *dp2;
unsigned char *end1, *end2;
int rdlen1, rdlen2;
struct rdata_state state1, state2;
/* Note that these have been determined to be OK previously,
so we don't need to check for NULL return here. */
unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
state1.ip = skip_name(rrset[i], header, plen, 10);
state2.ip = skip_name(rrset[i+1], header, plen, 10);
state1.op = state2.op = NULL;
state1.buff = buff1;
state2.buff = buff2;
state1.desc = state2.desc = rr_desc;
p1 += 8; /* skip class, type, ttl */
GETSHORT(rdlen1, p1);
end1 = p1 + rdlen1;
state1.ip += 8; /* skip class, type, ttl */
GETSHORT(rdlen1, state1.ip);
if (!CHECK_LEN(header, state1.ip, plen, rdlen1))
return rrsetidx; /* short packet */
state1.end = state1.ip + rdlen1;
p2 += 8; /* skip class, type, ttl */
GETSHORT(rdlen2, p2);
end2 = p2 + rdlen2;
dp1 = dp2 = rr_desc;
for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
state2.ip += 8; /* skip class, type, ttl */
GETSHORT(rdlen2, state2.ip);
if (!CHECK_LEN(header, state2.ip, plen, rdlen2))
return rrsetidx; /* short packet */
state2.end = state2.ip + rdlen2;
while (1)
{
if (left1 != 0)
memmove(buff1, buff1 + len1 - left1, left1);
int ok1, ok2;
if ((len1 = get_rdata(header, plen, end1, buff1 + left1, (MAXDNAME * 2) - left1, &p1, &dp1)) == 0)
{
quit = 1;
len1 = end1 - p1;
memcpy(buff1 + left1, p1, len1);
}
len1 += left1;
if (left2 != 0)
memmove(buff2, buff2 + len2 - left2, left2);
if ((len2 = get_rdata(header, plen, end2, buff2 + left2, (MAXDNAME *2) - left2, &p2, &dp2)) == 0)
{
quit = 1;
len2 = end2 - p2;
memcpy(buff2 + left2, p2, len2);
}
len2 += left2;
if (len1 > len2)
left1 = len1 - len2, left2 = 0, len = len2;
else
left2 = len2 - len1, left1 = 0, len = len1;
rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
if (rc > 0 || (rc == 0 && quit && len1 > len2))
{
unsigned char *tmp = rrset[i+1];
rrset[i+1] = rrset[i];
rrset[i] = tmp;
swap = quit = 1;
}
else if (rc == 0 && quit && len1 == len2)
ok1 = get_rdata(header, plen, &state1);
ok2 = get_rdata(header, plen, &state2);
if (!ok1 && !ok2)
{
/* Two RRs are equal, remove one copy. RFC 4034, para 6.3 */
for (j = i+1; j < rrsetidx-1; j++)
rrset[j] = rrset[j+1];
rrsetidx--;
i--;
break;
}
else if (rc < 0)
quit = 1;
else if (ok1 && (!ok2 || *state1.op > *state2.op))
{
unsigned char *tmp = rrset[i+1];
rrset[i+1] = rrset[i];
rrset[i] = tmp;
swap = 1;
break;
}
else if (ok2 && (!ok1 || *state2.op > *state1.op))
break;
/* arrive here when bytes are equal, go round the loop again
and compare the next ones. */
}
}
} while (swap);
@@ -569,15 +578,18 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
wire_len = to_wire(keyname);
hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
from_wire(keyname);
#define RRBUFLEN 128 /* Most RRs are smaller than this. */
for (i = 0; i < rrsetidx; ++i)
{
int seg;
unsigned char *end, *cp;
u16 len, *dp;
int j;
struct rdata_state state;
u16 len;
unsigned char rrbuf[RRBUFLEN];
p = rrset[i];
if (!extract_name(header, plen, &p, name, 1, 10))
return STAT_BOGUS;
@@ -586,12 +598,11 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
/* if more labels than in RRsig name, hash *.<no labels in rrsig labels field> 4035 5.3.2 */
if (labels < name_labels)
{
int k;
for (k = name_labels - labels; k != 0; k--)
for (j = name_labels - labels; j != 0; j--)
{
while (*name_start != '.' && *name_start != 0)
name_start++;
if (k != 1 && *name_start == '.')
if (j != 1 && *name_start == '.')
name_start++;
}
@@ -606,30 +617,66 @@ static int validate_rrset(time_t now, struct dns_header *header, size_t plen, in
hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
hash->update(ctx, 4, p); /* class and type */
hash->update(ctx, 4, (unsigned char *)&nsigttl);
p += 8; /* skip class, type, ttl */
p += 8; /* skip type, class, ttl */
GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen))
return STAT_BOGUS;
end = p + rdlen;
/* canonicalise rdata and calculate length of same, use name buffer as workspace.
Note that name buffer is twice MAXDNAME long in DNSSEC mode. */
cp = p;
dp = rr_desc;
for (len = 0; (seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)) != 0; len += seg);
len += end - cp;
len = htons(len);
hash->update(ctx, 2, (unsigned char *)&len);
/* Now canonicalise again and digest. */
cp = p;
dp = rr_desc;
while ((seg = get_rdata(header, plen, end, name, MAXDNAME * 2, &cp, &dp)))
hash->update(ctx, seg, (unsigned char *)name);
if (cp != end)
hash->update(ctx, end - cp, cp);
/* Optimisation for RR types which need no cannonicalisation.
This includes DNSKEY DS NSEC and NSEC3, which are also long, so
it saves lots of calls to get_rdata, and avoids the pessimal
segmented insertion, even with a small rrbuf[].
If canonicalisation is not needed, a simple insertion into the hash works.
*/
if (*rr_desc == (u16)-1)
{
len = htons(rdlen);
hash->update(ctx, 2, (unsigned char *)&len);
hash->update(ctx, rdlen, p);
}
else
{
/* canonicalise rdata and calculate length of same, use
name buffer as workspace for get_rdata. */
state.ip = p;
state.op = NULL;
state.desc = rr_desc;
state.buff = name;
state.end = p + rdlen;
for (j = 0; get_rdata(header, plen, &state); j++)
if (j < RRBUFLEN)
rrbuf[j] = *state.op;
len = htons((u16)j);
hash->update(ctx, 2, (unsigned char *)&len);
/* If the RR is shorter than RRBUFLEN (most of them, in practice)
then we can just digest it now. If it exceeds RRBUFLEN we have to
go back to the start and do it in chunks. */
if (j >= RRBUFLEN)
{
state.ip = p;
state.op = NULL;
state.desc = rr_desc;
for (j = 0; get_rdata(header, plen, &state); j++)
{
rrbuf[j] = *state.op;
if (j == RRBUFLEN - 1)
{
hash->update(ctx, RRBUFLEN, rrbuf);
j = -1;
}
}
}
if (j != 0)
hash->update(ctx, j, rrbuf);
}
}
hash->digest(ctx, hash->digest_size, digest);
@@ -1003,7 +1050,7 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
cache_end_insert();
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, "no DS");
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS");
}
return STAT_OK;
@@ -2056,35 +2103,4 @@ size_t dnssec_generate_query(struct dns_header *header, unsigned char *end, char
return ret;
}
unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned int len;
unsigned char *p = (unsigned char *)(header+1);
const struct nettle_hash *hash;
void *ctx;
unsigned char *digest;
if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
return NULL;
for (q = ntohs(header->qdcount); q != 0; q--)
{
if (!extract_name(header, plen, &p, name, 1, 4))
break; /* bad packet */
len = to_wire(name);
hash->update(ctx, len, (unsigned char *)name);
/* CRC the class and type as well */
hash->update(ctx, 4, p);
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
break; /* bad packet */
}
hash->digest(ctx, hash->digest_size, digest);
return digest;
}
#endif /* HAVE_DNSSEC */
+47 -28
View File
@@ -264,7 +264,8 @@ static void encoder(unsigned char *in, char *out)
out[3] = char64(in[2]);
}
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep)
{
int maclen, replace = 2; /* can't get mac address, just delete any incoming. */
unsigned char mac[DHCP_CHADDR_MAX];
@@ -273,6 +274,7 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
if ((maclen = find_mac(l3, mac, 1, now)) == 6)
{
replace = 1;
*cacheablep = 0;
if (option_bool(OPT_MAC_HEX))
print_mac(encode, mac, maclen);
@@ -288,14 +290,18 @@ static size_t add_dns_client(struct dns_header *header, size_t plen, unsigned ch
}
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *l3, time_t now)
static size_t add_mac(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *l3, time_t now, int *cacheablep)
{
int maclen;
unsigned char mac[DHCP_CHADDR_MAX];
if ((maclen = find_mac(l3, mac, 1, now)) != 0)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
{
*cacheablep = 0;
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_MAC, mac, maclen, 0, 0);
}
return plen;
}
@@ -313,17 +319,18 @@ static void *get_addrp(union mysockaddr *addr, const short family)
return &addr->in.sin_addr;
}
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source, int *cacheablep)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len;
void *addrp = NULL;
int sa_family = source->sa.sa_family;
int cacheable = 0;
opt->source_netmask = 0;
opt->scope_netmask = 0;
if (source->sa.sa_family == AF_INET6 && daemon->add_subnet6)
{
opt->source_netmask = daemon->add_subnet6->mask;
@@ -331,6 +338,7 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
{
sa_family = daemon->add_subnet6->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet6->addr, sa_family);
cacheable = 1;
}
else
addrp = &source->in6.sin6_addr;
@@ -343,6 +351,7 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
{
sa_family = daemon->add_subnet4->addr.sa.sa_family;
addrp = get_addrp(&daemon->add_subnet4->addr, sa_family);
cacheable = 1; /* Address is constant */
}
else
addrp = &source->in.sin_addr;
@@ -350,8 +359,6 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
opt->family = htons(sa_family == AF_INET6 ? 2 : 1);
len = 0;
if (addrp && opt->source_netmask != 0)
{
len = ((opt->source_netmask - 1) >> 3) + 1;
@@ -359,18 +366,26 @@ static size_t calc_subnet_opt(struct subnet_opt *opt, union mysockaddr *source)
if (opt->source_netmask & 7)
opt->addr[len-1] &= 0xff << (8 - (opt->source_netmask & 7));
}
else
{
cacheable = 1; /* No address ever supplied. */
len = 0;
}
if (cacheablep)
*cacheablep = cacheable;
return len + 4;
}
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source)
static size_t add_source_addr(struct dns_header *header, size_t plen, unsigned char *limit, union mysockaddr *source, int *cacheable)
{
/* http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-02 */
int len;
struct subnet_opt opt;
len = calc_subnet_opt(&opt, source);
len = calc_subnet_opt(&opt, source, cacheable);
return add_pseudoheader(header, plen, (unsigned char *)limit, PACKETSZ, EDNS0_OPTION_CLIENT_SUBNET, (unsigned char *)&opt, len, 0, 0);
}
@@ -383,18 +398,18 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
unsigned char *p;
int code, i, rdlen;
calc_len = calc_subnet_opt(&opt, peer);
calc_len = calc_subnet_opt(&opt, peer, NULL);
if (!(p = skip_name(pseudoheader, header, plen, 10)))
return 1;
p += 8; /* skip UDP length and RCODE */
GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen))
return 1; /* bad packet */
/* check if option there */
if (!(p = skip_name(pseudoheader, header, plen, 10)))
return 1;
p += 8; /* skip UDP length and RCODE */
GETSHORT(rdlen, p);
if (!CHECK_LEN(header, p, plen, rdlen))
return 1; /* bad packet */
/* check if option there */
for (i = 0; i + 4 < rdlen; i += len + 4)
{
GETSHORT(code, p);
@@ -412,24 +427,28 @@ int check_source(struct dns_header *header, size_t plen, unsigned char *pseudohe
return 1;
}
/* Set *check_subnet if we add a client subnet option, which needs to checked
in the reply. Set *cacheable to zero if we add an option which the answer
may depend on. */
size_t add_edns0_config(struct dns_header *header, size_t plen, unsigned char *limit,
union mysockaddr *source, time_t now, int *check_subnet)
union mysockaddr *source, time_t now, int *check_subnet, int *cacheable)
{
*check_subnet = 0;
*cacheable = 1;
if (option_bool(OPT_ADD_MAC))
plen = add_mac(header, plen, limit, source, now);
plen = add_mac(header, plen, limit, source, now, cacheable);
if (option_bool(OPT_MAC_B64) || option_bool(OPT_MAC_HEX))
plen = add_dns_client(header, plen, limit, source, now);
plen = add_dns_client(header, plen, limit, source, now, cacheable);
if (daemon->dns_client_id)
plen = add_pseudoheader(header, plen, limit, PACKETSZ, EDNS0_OPTION_NOMCPEID,
(unsigned char *)daemon->dns_client_id, strlen(daemon->dns_client_id), 0, 1);
if (option_bool(OPT_CLIENT_SUBNET))
{
plen = add_source_addr(header, plen, limit, source);
plen = add_source_addr(header, plen, limit, source, cacheable);
*check_subnet = 1;
}
+214 -103
View File
@@ -16,10 +16,12 @@
#include "dnsmasq.h"
static struct frec *lookup_frec(unsigned short id, void *hash);
static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash);
static struct frec *lookup_frec_by_sender(unsigned short id,
union mysockaddr *addr,
void *hash);
static struct frec *lookup_frec_by_query(void *hash, unsigned int flags);
static unsigned short get_id(void);
static void free_frec(struct frec *f);
@@ -255,20 +257,29 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
int type = SERV_DO_DNSSEC, norebind = 0;
union all_addr *addrp = NULL;
unsigned int flags = 0;
unsigned int fwd_flags = 0;
struct server *start = NULL;
#ifdef HAVE_DNSSEC
void *hash = hash_questions(header, plen, daemon->namebuff);
#ifdef HAVE_DNSSEC
int do_dnssec = 0;
#else
unsigned int crc = questions_crc(header, plen, daemon->namebuff);
void *hash = &crc;
#endif
unsigned int gotname = extract_request(header, plen, daemon->namebuff, NULL);
unsigned char *oph = find_pseudoheader(header, plen, NULL, NULL, NULL, NULL);
(void)do_bit;
if (header->hb4 & HB4_CD)
fwd_flags |= FREC_CHECKING_DISABLED;
if (ad_reqd)
fwd_flags |= FREC_AD_QUESTION;
if (oph)
fwd_flags |= FREC_HAS_PHEADER;
#ifdef HAVE_DNSSEC
if (do_bit)
fwd_flags |= FREC_DO_QUESTION;
#endif
/* may be no servers available. */
if (forward || (hash && (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash))))
if (forward || (forward = lookup_frec_by_sender(ntohs(header->id), udpaddr, hash)))
{
/* If we didn't get an answer advertising a maximal packet in EDNS,
fall back to 1280, which should work everywhere on IPv6.
@@ -339,6 +350,39 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
}
else
{
/* Query from new source, but the same query may be in progress
from another source. If so, just add this client to the
list that will get the reply.*/
if (!option_bool(OPT_ADD_MAC) && !option_bool(OPT_MAC_B64) &&
(forward = lookup_frec_by_query(hash, fwd_flags)))
{
/* Note whine_malloc() zeros memory. */
if (!daemon->free_frec_src &&
daemon->frec_src_count < daemon->ftabsize &&
(daemon->free_frec_src = whine_malloc(sizeof(struct frec_src))))
{
daemon->frec_src_count++;
daemon->free_frec_src->next = NULL;
}
/* If we've been spammed with many duplicates, just drop the query. */
if (daemon->free_frec_src)
{
struct frec_src *new = daemon->free_frec_src;
daemon->free_frec_src = new->next;
new->next = forward->frec_src.next;
forward->frec_src.next = new;
new->orig_id = ntohs(header->id);
new->source = *udpaddr;
new->dest = *dst_addr;
new->log_id = daemon->log_id;
new->iface = dst_iface;
}
return 1;
}
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
@@ -346,22 +390,23 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
do_dnssec = type & SERV_DO_DNSSEC;
#endif
type &= ~SERV_DO_DNSSEC;
if (daemon->servers && !flags)
forward = get_new_frec(now, NULL, 0);
forward = get_new_frec(now, NULL, NULL);
/* table full - flags == 0, return REFUSED */
if (forward)
{
forward->source = *udpaddr;
forward->dest = *dst_addr;
forward->iface = dst_iface;
forward->orig_id = ntohs(header->id);
forward->frec_src.source = *udpaddr;
forward->frec_src.orig_id = ntohs(header->id);
forward->frec_src.dest = *dst_addr;
forward->frec_src.iface = dst_iface;
forward->frec_src.next = NULL;
forward->new_id = get_id();
forward->fd = udpfd;
memcpy(forward->hash, hash, HASH_SIZE);
forward->forwardall = 0;
forward->flags = 0;
forward->flags = fwd_flags;
if (norebind)
forward->flags |= FREC_NOREBIND;
if (header->hb4 & HB4_CD)
@@ -411,18 +456,21 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (!flags && forward)
{
struct server *firstsentto = start;
int subnet, forwarded = 0;
int subnet, cacheable, forwarded = 0;
size_t edns0_len;
unsigned char *pheader;
/* If a query is retried, use the log_id for the retry when logging the answer. */
forward->log_id = daemon->log_id;
forward->frec_src.log_id = daemon->log_id;
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->source, now, &subnet);
plen = add_edns0_config(header, plen, ((unsigned char *)header) + PACKETSZ, &forward->frec_src.source, now, &subnet, &cacheable);
if (subnet)
forward->flags |= FREC_HAS_SUBNET;
if (!cacheable)
forward->flags |= FREC_NO_CACHE;
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && do_dnssec)
{
@@ -490,7 +538,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(&forward->source, &forward->dest, 0, &mark))
if (get_incoming_mark(&forward->frec_src.source, &forward->frec_src.dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
@@ -555,7 +603,7 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
return 1;
/* could not send on, prepare to return */
header->id = htons(forward->orig_id);
header->id = htons(forward->frec_src.orig_id);
free_frec(forward); /* cancel */
}
@@ -606,7 +654,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
}
}
#endif
if ((pheader = find_pseudoheader(header, n, &plen, &sizep, &is_sign, NULL)))
{
/* Get extended RCODE. */
@@ -676,7 +724,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
server && !(server->flags & SERV_WARNED_RECURSIVE))
{
prettyprint_addr(&server->addr, daemon->namebuff);
(void)prettyprint_addr(&server->addr, daemon->namebuff);
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
if (!option_bool(OPT_LOG))
server->flags |= SERV_WARNED_RECURSIVE;
@@ -769,9 +817,6 @@ void reply_query(int fd, int family, time_t now)
size_t nn;
struct server *server;
void *hash;
#ifndef HAVE_DNSSEC
unsigned int crc;
#endif
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -798,14 +843,9 @@ void reply_query(int fd, int family, time_t now)
if (difftime(now, server->pktsz_reduced) > UDP_TEST_TIME)
server->edns_pktsz = daemon->edns_pktsz;
#ifdef HAVE_DNSSEC
hash = hash_questions(header, n, daemon->namebuff);
#else
hash = &crc;
crc = questions_crc(header, n, daemon->namebuff);
#endif
if (!(forward = lookup_frec(ntohs(header->id), hash)))
if (!(forward = lookup_frec(ntohs(header->id), fd, family, hash)))
return;
#ifdef HAVE_DUMPFILE
@@ -815,8 +855,8 @@ void reply_query(int fd, int family, time_t now)
/* log_query gets called indirectly all over the place, so
pass these in global variables - sorry. */
daemon->log_display_id = forward->log_id;
daemon->log_source_addr = &forward->source;
daemon->log_display_id = forward->frec_src.log_id;
daemon->log_source_addr = &forward->frec_src.source;
if (daemon->ignore_addr && RCODE(header) == NOERROR &&
check_for_ignored_address(header, n, daemon->ignore_addr))
@@ -834,7 +874,6 @@ void reply_query(int fd, int family, time_t now)
int is_sign;
#ifdef HAVE_DNSSEC
/* For DNSSEC originated queries, just retry the query to the same server. */
if (forward->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY))
{
struct server *start;
@@ -860,6 +899,8 @@ void reply_query(int fd, int family, time_t now)
}
fd = -1;
if (start->sfd)
fd = start->sfd->fd;
else
@@ -867,19 +908,21 @@ void reply_query(int fd, int family, time_t now)
if (start->addr.sa.sa_family == AF_INET6)
{
/* may have changed family */
if (!forward->rfd6)
forward->rfd6 = allocate_rfd(AF_INET6);
fd = forward->rfd6->fd;
if (forward->rfd6 || (forward->rfd6 = allocate_rfd(AF_INET6)))
fd = forward->rfd6->fd;
}
else
{
/* may have changed family */
if (!forward->rfd4)
forward->rfd4 = allocate_rfd(AF_INET);
fd = forward->rfd4->fd;
if (forward->rfd4 || (forward->rfd4 = allocate_rfd(AF_INET)))
fd = forward->rfd4->fd;
}
}
/* Can't get socket. */
if (fd == -1)
return;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
#endif
@@ -960,7 +1003,7 @@ void reply_query(int fd, int family, time_t now)
{
forward->sentto->edns_pktsz = SAFE_PKTSZ;
forward->sentto->pktsz_reduced = now;
prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
(void)prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
}
@@ -1039,7 +1082,9 @@ void reply_query(int fd, int family, time_t now)
/* Find the original query that started it all.... */
for (orig = forward; orig->dependent; orig = orig->dependent);
if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, 1)))
/* Make sure we don't expire and free the orig frec during the
allocation of a new one. */
if (--orig->work_counter == 0 || !(new = get_new_frec(now, NULL, orig)))
status = STAT_ABANDONED;
else
{
@@ -1086,6 +1131,7 @@ void reply_query(int fd, int family, time_t now)
new->sentto = server;
new->rfd4 = NULL;
new->rfd6 = NULL;
new->frec_src.next = NULL;
new->flags &= ~(FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_HAS_EXTRADATA);
new->forwardall = 0;
@@ -1113,8 +1159,7 @@ void reply_query(int fd, int family, time_t now)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
querystr("dnssec-query", querytype));
if ((hash = hash_questions(header, nn, daemon->namebuff)))
memcpy(new->hash, hash, HASH_SIZE);
memcpy(new->hash, hash_questions(header, nn, daemon->namebuff), HASH_SIZE);
new->new_id = get_id();
header->id = htons(new->new_id);
/* Save query for retransmission */
@@ -1148,7 +1193,7 @@ void reply_query(int fd, int family, time_t now)
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(&orig->source, &orig->dest, 0, &mark))
if (get_incoming_mark(&orig->frec_src.source, &orig->frec_src.dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
@@ -1219,12 +1264,19 @@ void reply_query(int fd, int family, time_t now)
header->hb4 |= HB4_CD;
else
header->hb4 &= ~HB4_CD;
/* Never cache answers which are contingent on the source or MAC address EDSN0 option,
since the cache is ignorant of such things. */
if (forward->flags & FREC_NO_CACHE)
no_cache_dnssec = 1;
if ((nn = process_reply(header, now, forward->sentto, (size_t)n, check_rebind, no_cache_dnssec, cache_secure, bogusanswer,
forward->flags & FREC_AD_QUESTION, forward->flags & FREC_DO_QUESTION,
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->source)))
forward->flags & FREC_ADDED_PHEADER, forward->flags & FREC_HAS_SUBNET, &forward->frec_src.source)))
{
header->id = htons(forward->orig_id);
struct frec_src *src;
header->id = htons(forward->frec_src.orig_id);
header->hb4 |= HB4_RA; /* recursion if available */
#ifdef HAVE_DNSSEC
/* We added an EDNSO header for the purpose of getting DNSSEC RRs, and set the value of the UDP payload size
@@ -1240,13 +1292,26 @@ void reply_query(int fd, int family, time_t now)
}
#endif
for (src = &forward->frec_src; src; src = src->next)
{
header->id = htons(src->orig_id);
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &forward->source);
dump_packet(DUMP_REPLY, daemon->packet, (size_t)nn, NULL, &src->source);
#endif
send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
&forward->source, &forward->dest, forward->iface);
send_from(forward->fd, option_bool(OPT_NOWILD) || option_bool (OPT_CLEVERBIND), daemon->packet, nn,
&src->source, &src->dest, src->iface);
if (option_bool(OPT_EXTRALOG) && src != &forward->frec_src)
{
daemon->log_display_id = src->log_id;
daemon->log_source_addr = &src->source;
log_query(F_UPSTREAM, "query", NULL, "duplicate");
}
}
}
free_frec(forward); /* cancel */
}
}
@@ -1282,8 +1347,9 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
int family = listen->addr.sa.sa_family;
/* Can always get recvd interface for IPv6 */
int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
int check_dst = !option_bool(OPT_NOWILD) || family == AF_INET6;
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -1295,7 +1361,7 @@ void receive_query(struct listener *listen, time_t now)
{
auth_dns = listen->iface->dns_auth;
if (listen->family == AF_INET)
if (family == AF_INET)
{
dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
netmask = listen->iface->netmask;
@@ -1325,9 +1391,9 @@ void receive_query(struct listener *listen, time_t now)
information disclosure. */
memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
source_addr.sa.sa_family = listen->family;
source_addr.sa.sa_family = family;
if (listen->family == AF_INET)
if (family == AF_INET)
{
/* Source-port == 0 is an error, we can't send back to that.
http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
@@ -1347,7 +1413,7 @@ void receive_query(struct listener *listen, time_t now)
{
struct addrlist *addr;
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (addr = daemon->interface_addrs; addr; addr = addr->next)
if ((addr->flags & ADDRLIST_IPV6) &&
@@ -1385,7 +1451,7 @@ void receive_query(struct listener *listen, time_t now)
return;
#if defined(HAVE_LINUX_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
@@ -1398,7 +1464,7 @@ void receive_query(struct listener *listen, time_t now)
if_index = p.p->ipi_ifindex;
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (listen->family == AF_INET)
if (family == AF_INET)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
@@ -1423,7 +1489,7 @@ void receive_query(struct listener *listen, time_t now)
}
#endif
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
@@ -1444,16 +1510,16 @@ void receive_query(struct listener *listen, time_t now)
if (!indextoname(listen->fd, if_index, ifr.ifr_name))
return;
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
if (!iface_check(family, &dst_addr, ifr.ifr_name, &auth_dns))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces(0);
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
!label_exception(if_index, listen->family, &dst_addr))
if (!loopback_exception(listen->fd, family, &dst_addr, ifr.ifr_name) &&
!label_exception(if_index, family, &dst_addr))
return;
}
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
if (family == AF_INET && option_bool(OPT_LOCALISE))
{
struct irec *iface;
@@ -1498,7 +1564,7 @@ void receive_query(struct listener *listen, time_t now)
#endif
char *types = querystr(auth_dns ? "auth" : "query", type);
if (listen->family == AF_INET)
if (family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&source_addr.in.sin_addr, types);
else
@@ -1764,7 +1830,7 @@ unsigned char *tcp_request(int confd, time_t now,
int local_auth = 0;
#endif
int checking_disabled, do_bit, added_pheader = 0, have_pseudoheader = 0;
int check_subnet, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
int check_subnet, cacheable, no_cache_dnssec = 0, cache_secure = 0, bogusanswer = 0;
size_t m;
unsigned short qtype;
unsigned int gotname;
@@ -1935,7 +2001,7 @@ unsigned char *tcp_request(int confd, time_t now,
char *domain = NULL;
unsigned char *oph = find_pseudoheader(header, size, NULL, NULL, NULL, NULL);
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet);
size = add_edns0_config(header, size, ((unsigned char *) header) + 65536, &peer_addr, now, &check_subnet, &cacheable);
if (gotname)
flags = search_servers(now, &addrp, gotname, daemon->namebuff, &type, &domain, &norebind);
@@ -1967,15 +2033,9 @@ unsigned char *tcp_request(int confd, time_t now,
if (!flags && last_server)
{
struct server *firstsendto = NULL;
#ifdef HAVE_DNSSEC
unsigned char *newhash, hash[HASH_SIZE];
if ((newhash = hash_questions(header, (unsigned int)size, daemon->namebuff)))
memcpy(hash, newhash, HASH_SIZE);
else
memset(hash, 0, HASH_SIZE);
#else
unsigned int crc = questions_crc(header, (unsigned int)size, daemon->namebuff);
#endif
unsigned char hash[HASH_SIZE];
memcpy(hash, hash_questions(header, (unsigned int)size, daemon->namebuff), HASH_SIZE);
/* Loop round available servers until we succeed in connecting to one.
Note that this code subtly ensures that consecutive queries on this connection
which can go to the same server, do so. */
@@ -2114,21 +2174,17 @@ unsigned char *tcp_request(int confd, time_t now,
/* If the crc of the question section doesn't match the crc we sent, then
someone might be attempting to insert bogus values into the cache by
sending replies containing questions and bogus answers. */
#ifdef HAVE_DNSSEC
newhash = hash_questions(header, (unsigned int)m, daemon->namebuff);
if (!newhash || memcmp(hash, newhash, HASH_SIZE) != 0)
if (memcmp(hash, hash_questions(header, (unsigned int)m, daemon->namebuff), HASH_SIZE) != 0)
{
m = 0;
break;
}
#else
if (crc != questions_crc(header, (unsigned int)m, daemon->namebuff))
{
m = 0;
break;
}
#endif
/* Never cache answers which are contingent on the source or MAC address EDSN0 option,
since the cache is ignorant of such things. */
if (!cacheable)
no_cache_dnssec = 1;
m = process_reply(header, now, last_server, (unsigned int)m,
option_bool(OPT_NO_REBIND) && !norebind, no_cache_dnssec, cache_secure, bogusanswer,
ad_reqd, do_bit, added_pheader, check_subnet, &peer_addr);
@@ -2223,6 +2279,17 @@ void free_rfd(struct randfd *rfd)
static void free_frec(struct frec *f)
{
struct frec_src *last;
/* add back to freelist if not the record builtin to every frec. */
for (last = f->frec_src.next; last && last->next; last = last->next) ;
if (last)
{
last->next = daemon->free_frec_src;
daemon->free_frec_src = f->frec_src.next;
}
f->frec_src.next = NULL;
free_rfd(f->rfd4);
f->rfd4 = NULL;
f->sentto = NULL;
@@ -2251,9 +2318,10 @@ static void free_frec(struct frec *f)
else return *wait zero if one available, or *wait is delay to
when the oldest in-use record will expire. Impose an absolute
limit of 4*TIMEOUT before we wipe things (for random sockets).
If force is set, always return a result, even if we have
to allocate above the limit. */
struct frec *get_new_frec(time_t now, int *wait, int force)
If force is non-NULL, always return a result, even if we have
to allocate above the limit, and never free the record pointed
to by the force argument. */
struct frec *get_new_frec(time_t now, int *wait, struct frec *force)
{
struct frec *f, *oldest, *target;
int count;
@@ -2270,7 +2338,7 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
/* Don't free DNSSEC sub-queries here, as we may end up with
dangling references to them. They'll go when their "real" query
is freed. */
if (!f->dependent)
if (!f->dependent && f != force)
#endif
{
if (difftime(now, f->time) >= 4*TIMEOUT)
@@ -2334,15 +2402,25 @@ struct frec *get_new_frec(time_t now, int *wait, int force)
return f; /* OK if malloc fails and this is NULL */
}
/* crc is all-ones if not known. */
static struct frec *lookup_frec(unsigned short id, void *hash)
static struct frec *lookup_frec(unsigned short id, int fd, int family, void *hash)
{
struct frec *f;
for(f = daemon->frec_list; f; f = f->next)
if (f->sentto && f->new_id == id &&
(!hash || memcmp(hash, f->hash, HASH_SIZE) == 0))
return f;
(memcmp(hash, f->hash, HASH_SIZE) == 0))
{
/* sent from random port */
if (family == AF_INET && f->rfd4 && f->rfd4->fd == fd)
return f;
if (family == AF_INET6 && f->rfd6 && f->rfd6->fd == fd)
return f;
/* sent to upstream from bound socket. */
if (f->sentto->sfd && f->sentto->sfd->fd == fd)
return f;
}
return NULL;
}
@@ -2352,17 +2430,42 @@ static struct frec *lookup_frec_by_sender(unsigned short id,
void *hash)
{
struct frec *f;
struct frec_src *src;
for (f = daemon->frec_list; f; f = f->next)
if (f->sentto &&
!(f->flags & (FREC_DNSKEY_QUERY | FREC_DS_QUERY)) &&
memcmp(hash, f->hash, HASH_SIZE) == 0)
for (src = &f->frec_src; src; src = src->next)
if (src->orig_id == id &&
sockaddr_isequal(&src->source, addr))
return f;
return NULL;
}
static struct frec *lookup_frec_by_query(void *hash, unsigned int flags)
{
struct frec *f;
/* FREC_DNSKEY and FREC_DS_QUERY are never set in flags, so the test below
ensures that no frec created for internal DNSSEC query can be returned here.
Similarly FREC_NO_CACHE is never set in flags, so a query which is
contigent on a particular source address EDNS0 option will never be matched. */
#define FLAGMASK (FREC_CHECKING_DISABLED | FREC_AD_QUESTION | FREC_DO_QUESTION \
| FREC_HAS_PHEADER | FREC_DNSKEY_QUERY | FREC_DS_QUERY | FREC_NO_CACHE)
for(f = daemon->frec_list; f; f = f->next)
if (f->sentto &&
f->orig_id == id &&
memcmp(hash, f->hash, HASH_SIZE) == 0 &&
sockaddr_isequal(&f->source, addr))
(f->flags & FLAGMASK) == flags &&
memcmp(hash, f->hash, HASH_SIZE) == 0)
return f;
return NULL;
}
/* Send query packet again, if we can. */
void resend_query()
{
@@ -2403,12 +2506,20 @@ void server_gone(struct server *server)
static unsigned short get_id(void)
{
unsigned short ret = 0;
struct frec *f;
do
ret = rand16();
while (lookup_frec(ret, NULL));
return ret;
while (1)
{
ret = rand16();
/* ensure id is unique. */
for (f = daemon->frec_list; f; f = f->next)
if (f->sentto && f->new_id == ret)
break;
if (!f)
return ret;
}
}
+281
View File
@@ -0,0 +1,281 @@
/* Copyright (c) 2012-2020 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* Hash the question section. This is used to safely detect query
retransmission and to detect answers to questions we didn't ask, which
might be poisoning attacks. Note that we decode the name rather
than CRC the raw bytes, since replies might be compressed differently.
We ignore case in the names for the same reason.
The hash used is SHA-256. If we're building with DNSSEC support,
we use the Nettle cypto library. If not, we prefer not to
add a dependency on Nettle, and use a stand-alone implementaion.
*/
#include "dnsmasq.h"
#if defined(HAVE_DNSSEC) || defined(HAVE_NETTLEHASH)
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned char *p = (unsigned char *)(header+1);
const struct nettle_hash *hash;
void *ctx;
unsigned char *digest;
if (!(hash = hash_find("sha256")) || !hash_init(hash, &ctx, &digest))
{
/* don't think this can ever happen. */
static unsigned char dummy[HASH_SIZE];
static int warned = 0;
if (!warned)
my_syslog(LOG_ERR, _("Failed to create SHA-256 hash object"));
warned = 1;
return dummy;
}
for (q = ntohs(header->qdcount); q != 0; q--)
{
char *cp, c;
if (!extract_name(header, plen, &p, name, 1, 4))
break; /* bad packet */
for (cp = name; (c = *cp); cp++)
if (c >= 'A' && c <= 'Z')
*cp += 'a' - 'A';
hash->update(ctx, cp - name, (unsigned char *)name);
/* CRC the class and type as well */
hash->update(ctx, 4, p);
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
break; /* bad packet */
}
hash->digest(ctx, hash->digest_size, digest);
return digest;
}
#else /* HAVE_DNSSEC */
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
typedef unsigned char BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct {
BYTE data[64];
WORD datalen;
unsigned long long bitlen;
WORD state[8];
} SHA256_CTX;
static void sha256_init(SHA256_CTX *ctx);
static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len);
static void sha256_final(SHA256_CTX *ctx, BYTE hash[]);
unsigned char *hash_questions(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned char *p = (unsigned char *)(header+1);
SHA256_CTX ctx;
static BYTE digest[SHA256_BLOCK_SIZE];
sha256_init(&ctx);
for (q = ntohs(header->qdcount); q != 0; q--)
{
char *cp, c;
if (!extract_name(header, plen, &p, name, 1, 4))
break; /* bad packet */
for (cp = name; (c = *cp); cp++)
if (c >= 'A' && c <= 'Z')
*cp += 'a' - 'A';
sha256_update(&ctx, (BYTE *)name, cp - name);
/* CRC the class and type as well */
sha256_update(&ctx, (BYTE *)p, 4);
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
break; /* bad packet */
}
sha256_final(&ctx, digest);
return (unsigned char *)digest;
}
/* Code from here onwards comes from https://github.com/B-Con/crypto-algorithms
and was written by Brad Conte (brad@bradconte.com), to whom all credit is given.
This code is in the public domain, and the copyright notice at the head of this
file does not apply to it.
*/
/****************************** MACROS ******************************/
#define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b))))
#define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b))))
#define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z)))
#define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
#define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22))
#define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25))
#define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3))
#define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10))
/**************************** VARIABLES *****************************/
static const WORD k[64] = {
0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,
0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174,
0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,
0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967,
0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,
0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070,
0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,
0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2
};
/*********************** FUNCTION DEFINITIONS ***********************/
static void sha256_transform(SHA256_CTX *ctx, const BYTE data[])
{
WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64];
for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]);
for ( ; i < 64; ++i)
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
a = ctx->state[0];
b = ctx->state[1];
c = ctx->state[2];
d = ctx->state[3];
e = ctx->state[4];
f = ctx->state[5];
g = ctx->state[6];
h = ctx->state[7];
for (i = 0; i < 64; ++i)
{
t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i];
t2 = EP0(a) + MAJ(a,b,c);
h = g;
g = f;
f = e;
e = d + t1;
d = c;
c = b;
b = a;
a = t1 + t2;
}
ctx->state[0] += a;
ctx->state[1] += b;
ctx->state[2] += c;
ctx->state[3] += d;
ctx->state[4] += e;
ctx->state[5] += f;
ctx->state[6] += g;
ctx->state[7] += h;
}
static void sha256_init(SHA256_CTX *ctx)
{
ctx->datalen = 0;
ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667;
ctx->state[1] = 0xbb67ae85;
ctx->state[2] = 0x3c6ef372;
ctx->state[3] = 0xa54ff53a;
ctx->state[4] = 0x510e527f;
ctx->state[5] = 0x9b05688c;
ctx->state[6] = 0x1f83d9ab;
ctx->state[7] = 0x5be0cd19;
}
static void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len)
{
WORD i;
for (i = 0; i < len; ++i)
{
ctx->data[ctx->datalen] = data[i];
ctx->datalen++;
if (ctx->datalen == 64) {
sha256_transform(ctx, ctx->data);
ctx->bitlen += 512;
ctx->datalen = 0;
}
}
}
static void sha256_final(SHA256_CTX *ctx, BYTE hash[])
{
WORD i;
i = ctx->datalen;
// Pad whatever data is left in the buffer.
if (ctx->datalen < 56)
{
ctx->data[i++] = 0x80;
while (i < 56)
ctx->data[i++] = 0x00;
}
else
{
ctx->data[i++] = 0x80;
while (i < 64)
ctx->data[i++] = 0x00;
sha256_transform(ctx, ctx->data);
memset(ctx->data, 0, 56);
}
// Append to the padding the total message's length in bits and transform.
ctx->bitlen += ctx->datalen * 8;
ctx->data[63] = ctx->bitlen;
ctx->data[62] = ctx->bitlen >> 8;
ctx->data[61] = ctx->bitlen >> 16;
ctx->data[60] = ctx->bitlen >> 24;
ctx->data[59] = ctx->bitlen >> 32;
ctx->data[58] = ctx->bitlen >> 40;
ctx->data[57] = ctx->bitlen >> 48;
ctx->data[56] = ctx->bitlen >> 56;
sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian,
// reverse all the bytes when copying the final state to the output hash.
for (i = 0; i < 4; ++i)
{
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff;
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff;
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff;
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff;
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff;
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff;
}
}
#endif
+1 -16
View File
@@ -22,9 +22,7 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <linux/version.h>
#include <linux/netlink.h>
/* We want to be able to compile against old header files
@@ -87,20 +85,7 @@ static inline void add_attr(struct nlmsghdr *nlh, uint16_t type, size_t len, con
void ipset_init(void)
{
struct utsname utsname;
int version;
char *split;
if (uname(&utsname) < 0)
die(_("failed to find kernel version: %s"), NULL, EC_MISC);
split = strtok(utsname.release, ".");
version = (split ? atoi(split) : 0);
split = strtok(NULL, ".");
version = version * 256 + (split ? atoi(split) : 0);
split = strtok(NULL, ".");
version = version * 256 + (split ? atoi(split) : 0);
old_kernel = (version < KERNEL_VERSION(2,6,32));
old_kernel = (daemon->kernel_version < KERNEL_VERSION(2,6,32));
if (old_kernel && (ipset_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) != -1)
return;
+19 -2
View File
@@ -22,6 +22,15 @@
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
/* Blergh. Radv does this, so that's our excuse. */
#ifndef SOL_NETLINK
#define SOL_NETLINK 270
#endif
#ifndef NETLINK_NO_ENOBUFS
#define NETLINK_NO_ENOBUFS 5
#endif
/* linux 2.6.19 buggers up the headers, patch it up here. */
#ifndef IFA_RTA
# define IFA_RTA(r) \
@@ -40,10 +49,11 @@ static u32 netlink_pid;
static void nl_async(struct nlmsghdr *h);
void netlink_init(void)
char *netlink_init(void)
{
struct sockaddr_nl addr;
socklen_t slen = sizeof(addr);
int opt = 1;
addr.nl_family = AF_NETLINK;
addr.nl_pad = 0;
@@ -74,12 +84,19 @@ void netlink_init(void)
if (daemon->netlinkfd == -1 ||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
/* save pid assigned by bind() and retrieved by getsockname() */
netlink_pid = addr.nl_pid;
iov.iov_len = 100;
iov.iov_base = safe_malloc(iov.iov_len);
if (daemon->kernel_version >= KERNEL_VERSION(2,6,30) &&
setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1)
return _("warning: failed to set NETLINK_NO_ENOBUFS on netlink socket");
return NULL;
}
static ssize_t netlink_recv(void)
+164 -31
View File
@@ -388,10 +388,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
/* check whether the interface IP has been added already
we call this routine multiple times. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr))
if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
{
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
iface->found = 1; /* for garbage collection */
iface->netmask = netmask;
return 1;
}
@@ -532,7 +533,82 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
}
/*
* Clean old interfaces no longer found.
*/
static void clean_interfaces()
{
struct irec *iface;
struct irec **up = &daemon->interfaces;
for (iface = *up; iface; iface = *up)
{
if (!iface->found && !iface->done)
{
*up = iface->next;
free(iface->name);
free(iface);
}
else
{
up = &iface->next;
}
}
}
/** Release listener if no other interface needs it.
*
* @return 1 if released, 0 if still required
*/
static int release_listener(struct listener *l)
{
if (l->used > 1)
{
struct irec *iface;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
{
if (iface->found)
{
/* update listener to point to active interface instead */
if (!l->iface->found)
l->iface = iface;
}
else
{
l->used--;
iface->done = 0;
}
}
/* Someone is still using this listener, skip its deletion */
if (l->used > 0)
return 0;
}
if (l->iface->done)
{
int port;
port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
l->iface->name, l->iface->index, daemon->addrbuff, port);
/* In case it ever returns */
l->iface->done = 0;
}
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
return 1;
}
int enumerate_interfaces(int reset)
{
static struct addrlist *spare = NULL;
@@ -630,6 +706,7 @@ int enumerate_interfaces(int reset)
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
int freed = 0;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{
@@ -637,25 +714,17 @@ int enumerate_interfaces(int reset)
if (!l->iface || l->iface->found)
up = &l->next;
else
else if (release_listener(l))
{
*up = l->next;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
*up = tmp;
freed = 1;
}
}
if (freed)
clean_interfaces();
}
errno = errsave;
spare = param.spare;
@@ -895,10 +964,11 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
{
l = safe_malloc(sizeof(struct listener));
l->next = NULL;
l->family = addr->sa.sa_family;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->tftpfd = tftpfd;
l->addr = *addr;
l->used = 1;
l->iface = NULL;
}
@@ -937,20 +1007,48 @@ void create_wildcard_listeners(void)
daemon->listeners = l;
}
static struct listener *find_listener(union mysockaddr *addr)
{
struct listener *l;
for (l = daemon->listeners; l; l = l->next)
if (sockaddr_isequal(&l->addr, addr))
return l;
return NULL;
}
void create_bound_listeners(int dienow)
{
struct listener *new;
struct irec *iface;
struct iname *if_tmp;
struct listener *existing;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad && iface->found &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
if (!iface->done && !iface->dad && iface->found)
{
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
existing = find_listener(&iface->addr);
if (existing)
{
iface->done = 1;
existing->used++; /* increase usage counter */
}
else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
/* Don't log the initial set of listen addresses created
at startup, since this is happening before the logging
system is initialised and the sign-on printed. */
if (!dienow)
{
int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
iface->name, iface->index, daemon->addrbuff, port);
}
}
}
/* Check for --listen-address options that haven't been used because there's
@@ -970,6 +1068,12 @@ void create_bound_listeners(int dienow)
{
new->next = daemon->listeners;
daemon->listeners = new;
if (!dienow)
{
int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
}
}
}
@@ -1158,17 +1262,46 @@ int random_sock(int family)
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
{
union mysockaddr addr_copy = *addr;
unsigned short port;
int tries = 1, done = 0;
unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
if (addr_copy.sa.sa_family == AF_INET)
port = addr_copy.in.sin_port;
else
port = addr_copy.in6.sin6_port;
/* cannot set source _port_ for TCP connections. */
if (is_tcp)
port = 0;
/* Bind a random port within the range given by min-port and max-port */
if (port == 0)
{
if (addr_copy.sa.sa_family == AF_INET)
addr_copy.in.sin_port = 0;
else
addr_copy.in6.sin6_port = 0;
tries = ports_avail < 30 ? 3 * ports_avail : 100;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
}
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
while (tries--)
{
if (addr_copy.sa.sa_family == AF_INET)
addr_copy.in.sin_port = port;
else
addr_copy.in6.sin6_port = port;
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
{
done = 1;
break;
}
if (errno != EADDRINUSE && errno != EACCES)
return 0;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
}
if (!done)
return 0;
if (!is_tcp && ifindex > 0)
@@ -1301,7 +1434,7 @@ void pre_allocate_sfds(void)
errno != 0 &&
option_bool(OPT_NOWILD))
{
prettyprint_addr(&srv->source_addr, daemon->namebuff);
(void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
if (srv->interface[0] != 0)
{
strcat(daemon->namebuff, " ");
+45 -8
View File
@@ -167,6 +167,7 @@ struct myoption {
#define LOPT_IGNORE_CLID 358
#define LOPT_SINGLE_PORT 359
#define LOPT_SCRIPT_TIME 360
#define LOPT_PXE_VENDOR 361
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -238,7 +239,7 @@ static const struct myoption opts[] =
{ "caa-record", 1, 0 , LOPT_CAA },
{ "dns-rr", 1, 0, LOPT_RR },
{ "enable-dbus", 2, 0, '1' },
{ "enable-ubus", 0, 0, LOPT_UBUS },
{ "enable-ubus", 2, 0, LOPT_UBUS },
{ "bootp-dynamic", 2, 0, '3' },
{ "dhcp-mac", 1, 0, '4' },
{ "no-ping", 0, 0, '5' },
@@ -270,6 +271,7 @@ static const struct myoption opts[] =
{ "dhcp-circuitid", 1, 0, LOPT_CIRCUIT },
{ "dhcp-remoteid", 1, 0, LOPT_REMOTE },
{ "dhcp-subscrid", 1, 0, LOPT_SUBSCR },
{ "dhcp-pxe-vendor", 1, 0, LOPT_PXE_VENDOR },
{ "interface-name", 1, 0, LOPT_INTNAME },
{ "dhcp-hostsfile", 1, 0, LOPT_DHCP_HOST },
{ "dhcp-optsfile", 1, 0, LOPT_DHCP_OPTS },
@@ -383,6 +385,7 @@ static struct {
{ LOPT_CIRCUIT, ARG_DUP, "set:<tag>,<circuit>", gettext_noop("Map RFC3046 circuit-id to tag."), NULL },
{ LOPT_REMOTE, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3046 remote-id to tag."), NULL },
{ LOPT_SUBSCR, ARG_DUP, "set:<tag>,<remote>", gettext_noop("Map RFC3993 subscriber-id to tag."), NULL },
{ LOPT_PXE_VENDOR, ARG_DUP, "<vendor>[,...]", gettext_noop("Specify vendor class to match for PXE requests."), NULL },
{ 'J', ARG_DUP, "tag:<tag>...", gettext_noop("Don't do DHCP for hosts with tag set."), NULL },
{ LOPT_BROADCAST, ARG_DUP, "[=tag:<tag>...]", gettext_noop("Force broadcast replies for hosts with tag set."), NULL },
{ 'k', OPT_NO_FORK, NULL, gettext_noop("Do NOT fork into the background, do NOT run in debug mode."), NULL },
@@ -428,7 +431,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 },
{ LOPT_UBUS, ARG_ONE, "[=<busname>]", 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 },
@@ -1225,7 +1228,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
}
else if (c == '.')
{
is_addr6 = is_dec = is_hex = 0;
is_dec = is_hex = 0;
dots++;
}
else if (c == '-')
@@ -1881,7 +1884,15 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
daemon->dbus_name = DNSMASQ_SERVICE;
break;
case LOPT_UBUS: /* --enable-ubus */
set_option_bool(OPT_UBUS);
if (arg)
daemon->ubus_name = opt_string_alloc(arg);
else
daemon->ubus_name = DNSMASQ_UBUS_NAME;
break;
case '8': /* --log-facility */
/* may be a filename */
if (strchr(arg, '/') || strcmp (arg, "-") == 0)
@@ -2983,7 +2994,6 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
struct dhcp_context *new = opt_malloc(sizeof(struct dhcp_context));
memset (new, 0, sizeof(*new));
new->lease_time = DEFLEASE;
while(1)
{
@@ -3033,6 +3043,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
if (inet_pton(AF_INET, a[0], &new->start))
{
new->next = daemon->dhcp;
new->lease_time = DEFLEASE;
daemon->dhcp = new;
new->end = new->start;
if (strcmp(a[1], "static") == 0)
@@ -3080,6 +3091,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->flags |= CONTEXT_V6;
new->prefix = 64; /* default */
new->end6 = new->start6;
new->lease_time = DEFLEASE6;
new->next = daemon->dhcp6;
daemon->dhcp6 = new;
@@ -3179,7 +3191,10 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
if (strcmp(a[leasepos], "infinite") == 0)
new->lease_time = 0xffffffff;
{
new->lease_time = 0xffffffff;
new->flags |= CONTEXT_SETLEASE;
}
else if (strcmp(a[leasepos], "deprecated") == 0)
new->flags |= CONTEXT_DEPRECATE;
else
@@ -3218,6 +3233,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
ret_err_free(_("bad dhcp-range"), new);
new->lease_time = atoi(a[leasepos]) * fac;
new->flags |= CONTEXT_SETLEASE;
/* Leases of a minute or less confuse
some clients, notably Apple's */
if (new->lease_time < 120)
@@ -3225,6 +3241,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
}
}
break;
}
@@ -3658,8 +3675,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->val = opt_malloc(new->len);
memcpy(new->val + 1, arg, new->len - 1);
new->u.vendor_class = (unsigned char *)"PXEClient";
new->flags = DHOPT_VENDOR;
new->u.vendor_class = NULL;
new->flags = DHOPT_VENDOR | DHOPT_VENDOR_PXE;
if (comma && atoi_check(comma, &timeout))
*(new->val) = timeout;
@@ -3921,6 +3938,19 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->next = daemon->override_relays;
daemon->override_relays = new;
arg = comma;
}
break;
case LOPT_PXE_VENDOR: /* --dhcp-pxe-vendor */
{
while (arg) {
struct dhcp_pxe_vendor *new = opt_malloc(sizeof(struct dhcp_pxe_vendor));
comma = split(arg);
new->data = opt_string_alloc(arg);
new->next = daemon->dhcp_pxe_vendors;
daemon->dhcp_pxe_vendors = new;
arg = comma;
}
}
break;
@@ -5198,6 +5228,13 @@ void read_opts(int argc, char **argv, char *compile_opts)
strcat(buff, daemon->authserver);
daemon->hostmaster = opt_string_alloc(buff);
}
if (!daemon->dhcp_pxe_vendors)
{
daemon->dhcp_pxe_vendors = opt_malloc(sizeof(struct dhcp_pxe_vendor));
daemon->dhcp_pxe_vendors->data = opt_string_alloc(DHCP_PXE_DEF_VENDOR);
daemon->dhcp_pxe_vendors->next = NULL;
}
/* only one of these need be specified: the other defaults to the host-name */
if (option_bool(OPT_LOCALMX) || daemon->mxnames || daemon->mxtarget)
+5 -2
View File
@@ -626,8 +626,11 @@ static int add_prefixes(struct in6_addr *local, int prefix,
real_prefix = context->prefix;
}
/* find floor time, don't reduce below 3 * RA interval. */
if (time > context->lease_time)
/* find floor time, don't reduce below 3 * RA interval.
If the lease time has been left as default, don't
use that as a floor. */
if ((context->flags & CONTEXT_SETLEASE) &&
time > context->lease_time)
{
time = context->lease_time;
if (time < ((unsigned int)(3 * param->adv_interval)))
+23 -56
View File
@@ -333,55 +333,6 @@ unsigned char *skip_section(unsigned char *ansp, int count, struct dns_header *h
return ansp;
}
/* CRC the question section. This is used to safely detect query
retransmission and to detect answers to questions we didn't ask, which
might be poisoning attacks. Note that we decode the name rather
than CRC the raw bytes, since replies might be compressed differently.
We ignore case in the names for the same reason. Return all-ones
if there is not question section. */
#ifndef HAVE_DNSSEC
unsigned int questions_crc(struct dns_header *header, size_t plen, char *name)
{
int q;
unsigned int crc = 0xffffffff;
unsigned char *p1, *p = (unsigned char *)(header+1);
for (q = ntohs(header->qdcount); q != 0; q--)
{
if (!extract_name(header, plen, &p, name, 1, 4))
return crc; /* bad packet */
for (p1 = (unsigned char *)name; *p1; p1++)
{
int i = 8;
char c = *p1;
if (c >= 'A' && c <= 'Z')
c += 'a' - 'A';
crc ^= c << 24;
while (i--)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
}
/* CRC the class and type as well */
for (p1 = p; p1 < p+4; p1++)
{
int i = 8;
crc ^= *p1 << 24;
while (i--)
crc = crc & 0x80000000 ? (crc << 1) ^ 0x04c11db7 : crc << 1;
}
p += 4;
if (!CHECK_LEN(header, p, plen, 0))
return crc; /* bad packet */
}
return crc;
}
#endif
size_t resize_packet(struct dns_header *header, size_t plen, unsigned char *pheader, size_t hlen)
{
unsigned char *ansp = skip_questions(header, plen);
@@ -843,17 +794,31 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
if ((flags & F_IPV4) &&
private_net(addr.addr4, !option_bool(OPT_LOCAL_REBIND)))
return 1;
if ((flags & F_IPV6) &&
IN6_IS_ADDR_V4MAPPED(&addr.addr6))
/* Block IPv4-mapped IPv6 addresses in private IPv4 address space */
if (flags & F_IPV6)
{
struct in_addr v4;
v4.s_addr = ((const uint32_t *) (&addr.addr6))[3];
if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
if (IN6_IS_ADDR_V4MAPPED(&addr.addr6))
{
struct in_addr v4;
v4.s_addr = ((const uint32_t *) (&addr.addr6))[3];
if (private_net(v4, !option_bool(OPT_LOCAL_REBIND)))
return 1;
}
/* Check for link-local (LL) and site-local (ULA) IPv6 addresses */
if (IN6_IS_ADDR_LINKLOCAL(&addr.addr6) ||
IN6_IS_ADDR_SITELOCAL(&addr.addr6))
return 1;
/* Check for the IPv6 loopback address (::1) when
option rebind-localhost-ok is NOT set */
if (!option_bool(OPT_LOCAL_REBIND) &&
IN6_IS_ADDR_LOOPBACK(&addr.addr6))
return 1;
}
}
#ifdef HAVE_IPSET
if (ipsets && (flags & (F_IPV4 | F_IPV6)))
{
@@ -1394,6 +1359,8 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
}
}
else
return 0; /* give up if any cached CNAME in chain can't be used for DNSSEC reasons. */
strcpy(name, cname_target);
}
+71 -26
View File
@@ -30,7 +30,7 @@ static struct in_addr server_id(struct dhcp_context *context, struct in_addr ove
static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
int opt, char *string, int null_term);
int opt, const char *string, int null_term);
static struct in_addr option_addr(unsigned char *opt);
static unsigned int option_uint(unsigned char *opt, int offset, int size);
static void log_packet(char *type, void *addr, unsigned char *ext_mac,
@@ -54,17 +54,19 @@ static void do_options(struct dhcp_context *context,
int vendor_class_len,
time_t now,
unsigned int lease_time,
unsigned short fuzz);
unsigned short fuzz,
const char *pxevendor);
static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid);
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor);
static int prune_vendor_opts(struct dhcp_netid *netid);
static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
struct dhcp_boot *find_boot(struct dhcp_netid *netid);
static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor);
size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
size_t sz, time_t now, int unicast_dest, int loopback,
@@ -76,6 +78,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
struct dhcp_mac *mac;
struct dhcp_netid_list *id_list;
int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
const char *pxevendor = NULL;
struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
unsigned char *end = (unsigned char *)(mess + 1);
unsigned char *real_end = (unsigned char *)(mess + 1);
@@ -647,7 +650,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clear_packet(mess, end);
do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0);
netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0, NULL);
}
}
@@ -835,9 +838,8 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
clid = NULL;
/* Check if client is PXE client. */
if (daemon->enable_pxe &&
(opt = option_find(mess, sz, OPTION_VENDOR_ID, 9)) &&
strncmp(option_ptr(opt, 0), "PXEClient", 9) == 0)
if (daemon->enable_pxe &&
is_pxe_client(mess, sz, &pxevendor))
{
if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
{
@@ -899,7 +901,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
pxe_misc(mess, end, uuid);
pxe_misc(mess, end, uuid, pxevendor);
prune_vendor_opts(tagif_netid);
opt71.val = save71;
@@ -979,7 +981,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
pxe_misc(mess, end, uuid);
pxe_misc(mess, end, uuid, pxevendor);
prune_vendor_opts(tagif_netid);
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);
@@ -1150,7 +1152,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
option_put(mess, end, OPTION_LEASE_TIME, 4, time);
/* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1499,7 +1501,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if (rapid_commit)
option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
}
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1566,7 +1568,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
}
do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0);
netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0, pxevendor);
*is_inform = 1; /* handle reply differently */
return dhcp_packet_size(mess, agent_id, real_end);
@@ -1948,7 +1950,7 @@ static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, in
}
static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
char *string, int null_term)
const char *string, int null_term)
{
unsigned char *p;
size_t len = strlen(string);
@@ -2026,15 +2028,32 @@ static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
dopt->flags &= ~DHOPT_VENDOR_MATCH;
if (opt && (dopt->flags & DHOPT_VENDOR))
{
int i, len = 0;
if (dopt->u.vendor_class)
len = strlen((char *)dopt->u.vendor_class);
for (i = 0; i <= (option_len(opt) - len); i++)
if (len == 0 || memcmp(dopt->u.vendor_class, option_ptr(opt, i), len) == 0)
{
dopt->flags |= DHOPT_VENDOR_MATCH;
break;
}
const struct dhcp_pxe_vendor *pv;
struct dhcp_pxe_vendor dummy_vendor = {
.data = (char *)dopt->u.vendor_class,
.next = NULL,
};
if (dopt->flags & DHOPT_VENDOR_PXE)
pv = daemon->dhcp_pxe_vendors;
else
pv = &dummy_vendor;
for (; pv; pv = pv->next)
{
int i, len = 0, matched = 0;
if (pv->data)
len = strlen(pv->data);
for (i = 0; i <= (option_len(opt) - len); i++)
if (len == 0 || memcmp(pv->data, option_ptr(opt, i), len) == 0)
{
matched = 1;
break;
}
if (matched)
{
dopt->flags |= DHOPT_VENDOR_MATCH;
break;
}
}
}
}
}
@@ -2087,11 +2106,13 @@ static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
return ret;
}
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid)
static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor)
{
unsigned char *p;
option_put_string(mess, end, OPTION_VENDOR_ID, "PXEClient", 0);
if (!pxevendor)
pxevendor="PXEClient";
option_put_string(mess, end, OPTION_VENDOR_ID, pxevendor, 0);
if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
memcpy(p, uuid, 17);
}
@@ -2308,6 +2329,29 @@ struct dhcp_boot *find_boot(struct dhcp_netid *netid)
return boot;
}
static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor)
{
const unsigned char *opt = NULL;
ssize_t conf_len = 0;
const struct dhcp_pxe_vendor *conf = daemon->dhcp_pxe_vendors;
opt = option_find(mess, sz, OPTION_VENDOR_ID, 0);
if (!opt)
return 0;
for (; conf; conf = conf->next)
{
conf_len = strlen(conf->data);
if (option_len(opt) < conf_len)
continue;
if (strncmp(option_ptr(opt, 0), conf->data, conf_len) == 0)
{
if (pxe_vendor)
*pxe_vendor = conf->data;
return 1;
}
}
return 0;
}
static void do_options(struct dhcp_context *context,
struct dhcp_packet *mess,
unsigned char *end,
@@ -2322,7 +2366,8 @@ static void do_options(struct dhcp_context *context,
int vendor_class_len,
time_t now,
unsigned int lease_time,
unsigned short fuzz)
unsigned short fuzz,
const char *pxevendor)
{
struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
struct dhcp_boot *boot;
@@ -2696,7 +2741,7 @@ static void do_options(struct dhcp_context *context,
if (context && pxe_arch != -1)
{
pxe_misc(mess, end, uuid);
pxe_misc(mess, end, uuid, pxevendor);
if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
}
+18 -17
View File
@@ -61,8 +61,9 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
union all_addr addra;
int family = listen->addr.sa.sa_family;
/* Can always get recvd interface for IPv6 */
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
int check_dest = !option_bool(OPT_NOWILD) || family == AF_INET6;
union {
struct cmsghdr align; /* this ensures alignment */
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
@@ -121,10 +122,10 @@ void tftp_request(struct listener *listen, time_t now)
if (msg.msg_controllen < sizeof(struct cmsghdr))
return;
addr.sa.sa_family = listen->family;
addr.sa.sa_family = family;
#if defined(HAVE_LINUX_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
@@ -138,7 +139,7 @@ void tftp_request(struct listener *listen, time_t now)
}
#elif defined(HAVE_SOLARIS_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
union {
@@ -154,7 +155,7 @@ void tftp_request(struct listener *listen, time_t now)
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
union {
@@ -171,7 +172,7 @@ void tftp_request(struct listener *listen, time_t now)
#endif
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
@@ -194,7 +195,7 @@ void tftp_request(struct listener *listen, time_t now)
addra.addr4 = addr.in.sin_addr;
if (listen->family == AF_INET6)
if (family == AF_INET6)
addra.addr6 = addr.in6.sin6_addr;
if (daemon->tftp_interfaces)
@@ -210,12 +211,12 @@ void tftp_request(struct listener *listen, time_t now)
else
{
/* Do the same as DHCP */
if (!iface_check(listen->family, &addra, name, NULL))
if (!iface_check(family, &addra, name, NULL))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces(0);
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
!label_exception(if_index, listen->family, &addra))
if (!loopback_exception(listen->tftpfd, family, &addra, name) &&
!label_exception(if_index, family, &addra))
return;
}
@@ -281,7 +282,7 @@ void tftp_request(struct listener *listen, time_t now)
prefix = pref->prefix;
}
if (listen->family == AF_INET)
if (family == AF_INET)
{
addr.in.sin_port = htons(port);
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -304,7 +305,7 @@ void tftp_request(struct listener *listen, time_t now)
if (option_bool(OPT_SINGLE_PORT))
transfer->sockfd = listen->tftpfd;
else if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
else if ((transfer->sockfd = socket(family, SOCK_DGRAM, 0)) == -1)
{
free(transfer);
return;
@@ -322,7 +323,7 @@ void tftp_request(struct listener *listen, time_t now)
transfer->opt_blocksize = transfer->opt_transize = 0;
transfer->netascii = transfer->carrylf = 0;
prettyprint_addr(&peer, daemon->addrbuff);
(void)prettyprint_addr(&peer, daemon->addrbuff);
/* if we have a nailed-down range, iterate until we find a free one. */
while (!option_bool(OPT_SINGLE_PORT))
@@ -337,7 +338,7 @@ void tftp_request(struct listener *listen, time_t now)
{
if (++port <= daemon->end_tftp_port)
{
if (listen->family == AF_INET)
if (family == AF_INET)
addr.in.sin_port = htons(port);
else
addr.in6.sin6_port = htons(port);
@@ -375,7 +376,7 @@ void tftp_request(struct listener *listen, time_t now)
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
{
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
int overhead = (listen->family == AF_INET) ? 32 : 52;
int overhead = (family == AF_INET) ? 32 : 52;
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
transfer->blocksize = 1;
@@ -624,7 +625,7 @@ void check_tftp_listeners(time_t now)
{
strcpy(daemon->namebuff, transfer->file->filename);
sanitise(daemon->namebuff);
prettyprint_addr(&transfer->peer, daemon->addrbuff);
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
/* unlink */
*up = tmp;
@@ -667,7 +668,7 @@ static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
char *end = daemon->packet + len;
char *err = next(&p, end);
prettyprint_addr(&transfer->peer, daemon->addrbuff);
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
/* Sanitise error message */
if (!err)
+3 -1
View File
@@ -38,7 +38,7 @@ static struct ubus_object_type ubus_object_type =
UBUS_OBJECT_TYPE("dnsmasq", ubus_object_methods);
static struct ubus_object ubus_object = {
.name = "dnsmasq",
.name = NULL,
.type = &ubus_object_type,
.methods = ubus_object_methods,
.n_methods = ARRAY_SIZE(ubus_object_methods),
@@ -94,6 +94,7 @@ void ubus_init()
return;
}
ubus_object.name = daemon->ubus_name;
ret = ubus_add_object(ubus, &ubus_object);
if (ret)
{
@@ -102,6 +103,7 @@ void ubus_init()
my_syslog(LOG_ERR, _("Cannot add object to UBus: %s"), ubus_strerror(ret));
error_logged = 1;
}
ubus_destroy(ubus);
return;
}
+23
View File
@@ -30,6 +30,10 @@
#include <idna.h>
#endif
#ifdef HAVE_LINUX_NETWORK
#include <sys/utsname.h>
#endif
/* SURF random number generator */
static u32 seed[32];
@@ -782,3 +786,22 @@ int wildcard_matchn(const char* wildcard, const char* match, int num)
return (!num) || (*wildcard == *match);
}
#ifdef HAVE_LINUX_NETWORK
int kernel_version(void)
{
struct utsname utsname;
int version;
char *split;
if (uname(&utsname) < 0)
die(_("failed to find kernel version: %s"), NULL, EC_MISC);
split = strtok(utsname.release, ".");
version = (split ? atoi(split) : 0);
split = strtok(NULL, ".");
version = version * 256 + (split ? atoi(split) : 0);
split = strtok(NULL, ".");
return version * 256 + (split ? atoi(split) : 0);
}
#endif
+1 -2
View File
@@ -1,9 +1,8 @@
# The root DNSSEC trust anchor, valid as at 10/02/2017
# The root DNSSEC trust anchor, valid as at 11/01/2019
# Note that this is a DS record (ie a hash of the root Zone Signing Key)
# If was downloaded from https://data.iana.org/root-anchors/root-anchors.xml
trust-anchor=.,19036,8,2,49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDDE32F24E8FB5
trust-anchor=.,20326,8,2,E06D44B80B8F1D39A95C0B0D7C65D08458E880409BBC683457104237C7F8EC8D