Compare commits
29 Commits
2732-set-s
...
v9.17.14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1530bf8b55 | ||
|
|
2f2cd937bb | ||
|
|
c9ee795246 | ||
|
|
ef810d8b1a | ||
|
|
765b5794f4 | ||
|
|
8dce3f7649 | ||
|
|
64bf0083bd | ||
|
|
4f574a5ee4 | ||
|
|
be01f589d9 | ||
|
|
7e59b8a4a1 | ||
|
|
7fef01201d | ||
|
|
af95cb8ccc | ||
|
|
d242ccfbdf | ||
|
|
66d1df57cb | ||
|
|
5bd7caba9c | ||
|
|
02726cb66e | ||
|
|
0dded90ae4 | ||
|
|
22aa929aac | ||
|
|
f14d870d15 | ||
|
|
5e1a48a605 | ||
|
|
cbdea694e8 | ||
|
|
715dc196e2 | ||
|
|
5547003a3d | ||
|
|
c70d9c4e9a | ||
|
|
67afea6cfc | ||
|
|
479dc58877 | ||
|
|
d67e16ae3c | ||
|
|
2fc89e0353 | ||
|
|
35d0027f36 |
@@ -13,6 +13,7 @@ extraction:
|
||||
- "libidn2-dev"
|
||||
- "libmaxminddb-dev"
|
||||
- "libuv1-dev"
|
||||
- "libnghttp2-dev"
|
||||
configure:
|
||||
command:
|
||||
- "autoreconf -fi"
|
||||
|
||||
69
CHANGES
69
CHANGES
@@ -1,48 +1,59 @@
|
||||
5651. [func] Refactor zone dumping to be processed asynchronously
|
||||
via the uv_work_t thread pool API. [GL #2732]
|
||||
--- 9.17.14 released ---
|
||||
|
||||
5650. [bug] Prevent a crash that could occur if serve-stale
|
||||
was enabled and a prefetch was triggered during a
|
||||
query restart. [GL #2733]
|
||||
5652. [bug] A copy-and-paste error in change 5584 caused the
|
||||
IP_DONTFRAG socket option to be enabled instead of
|
||||
disabled. This has been fixed. [GL #2746]
|
||||
|
||||
5649. [bug] If a query was answered with stale data on a server
|
||||
with DNS64 enabled, an assertion could occur if a
|
||||
non-stale answer arrived afterward. [GL #2731]
|
||||
5651. [func] Refactor zone dumping to be processed asynchronously via
|
||||
the uv_work_t thread pool API. [GL #2732]
|
||||
|
||||
5648. [bug] The calculation of the estimated IXFR transaction
|
||||
size by dns_journal_iter_init() was invalid. [GL #2685]
|
||||
5650. [bug] Prevent a crash that could occur if serve-stale was
|
||||
enabled and a prefetch was triggered during a query
|
||||
restart. [GL #2733]
|
||||
|
||||
5647. [func] The interfacemgr has been refactored to use fewer
|
||||
clientmgr objects, which in turn use fewer memory
|
||||
contexts and tasks. This should result in less
|
||||
5649. [bug] If a query was answered with stale data on a server with
|
||||
DNS64 enabled, an assertion could occur if a non-stale
|
||||
answer arrived afterward. [GL #2731]
|
||||
|
||||
5648. [bug] The calculation of the estimated IXFR transaction size
|
||||
in dns_journal_iter_init() was invalid. [GL #2685]
|
||||
|
||||
5647. [func] The interface manager has been refactored to use fewer
|
||||
client manager objects, which in turn use fewer memory
|
||||
contexts and tasks. This should result in less
|
||||
fragmented memory and better startup performance.
|
||||
[GL #2433]
|
||||
|
||||
5646. [bug] The default TCP timeout for rndc has been increased
|
||||
to 60 seconds. This was its original value, but it
|
||||
had been inadvertently lowered to 10. [GL #2643]
|
||||
5646. [bug] The default TCP timeout for rndc has been increased to
|
||||
60 seconds. This was its original value, but it had been
|
||||
inadvertently lowered to 10 when rndc was updated to use
|
||||
the network manager. [GL #2643]
|
||||
|
||||
5645. [cleanup] Remove the rarely-used dns_name_copy() function
|
||||
and rename dns_name_copynf() to dns_name_copy().
|
||||
[GL !5081]
|
||||
5645. [cleanup] Remove the rarely-used dns_name_copy() function and
|
||||
rename dns_name_copynf() to dns_name_copy(). [GL !5081]
|
||||
|
||||
5644. [bug] Fix a race condition in reading and writing key files
|
||||
for KASP zones in multiple views. [GL #1875]
|
||||
for zones using KASP and configured in multiple views.
|
||||
[GL #1875]
|
||||
|
||||
5643. [placeholder]
|
||||
|
||||
5642. [bug] Check "key-directory" conflicts in "named.conf" for
|
||||
zones in multiple views with different "dnssec-policy".
|
||||
[GL #2463].
|
||||
5642. [bug] Zones which are configured in multiple views with
|
||||
different values set for "dnssec-policy" and with
|
||||
identical values set for "key-directory" are now
|
||||
detected and treated as a configuration error.
|
||||
[GL #2463]
|
||||
|
||||
5641. [bug] Address potential memory leak in dst_key_fromnamedfile.
|
||||
[GL #2689]
|
||||
5641. [bug] Address a potential memory leak in
|
||||
dst_key_fromnamedfile(). [GL #2689]
|
||||
|
||||
5640. [func] Add new configuration option to set the operating system
|
||||
receive and send buffers. [GL #2313]
|
||||
5640. [func] Add new configuration options for setting the size of
|
||||
receive and send buffers in the operating system:
|
||||
"tcp-receive-buffer", "tcp-send-buffer",
|
||||
"udp-receive-buffer", and "udp-send-buffer". [GL #2313]
|
||||
|
||||
5639. [bug] Check that the first and last SOA record of an AXFR
|
||||
are consistent. [GL #2528]
|
||||
5639. [bug] Check that the first and last SOA record of an AXFR are
|
||||
consistent. [GL #2528]
|
||||
|
||||
--- 9.17.13 released ---
|
||||
|
||||
|
||||
@@ -80,6 +80,34 @@ sub reply_handler {
|
||||
$rr = new Net::DNS::RR("$synth2 $ttl $qclass DNAME .");
|
||||
push @ans, $rr;
|
||||
$rcode = "NOERROR";
|
||||
# The following three code branches referring to the "example.dname"
|
||||
# zone are necessary for the resolver variant of the CVE-2021-25215
|
||||
# regression test to work. A named instance cannot be used for
|
||||
# serving the DNAME records below as a version of BIND vulnerable to
|
||||
# CVE-2021-25215 would crash while answering the queries asked by
|
||||
# the tested resolver.
|
||||
} elsif ($qname eq "ns3.example.dname") {
|
||||
if ($qtype eq "A") {
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass A 10.53.0.3");
|
||||
push @ans, $rr;
|
||||
}
|
||||
if ($qtype eq "AAAA") {
|
||||
my $rr = new Net::DNS::RR("example.dname. $ttl $qclass SOA . . 0 0 0 0 $ttl");
|
||||
push @auth, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "self.example.self.example.dname") {
|
||||
my $rr = new Net::DNS::RR("self.example.dname. $ttl $qclass DNAME dname.");
|
||||
push @ans, $rr;
|
||||
$rr = new Net::DNS::RR("$qname $ttl $qclass CNAME self.example.dname.");
|
||||
push @ans, $rr;
|
||||
$rcode = "NOERROR";
|
||||
} elsif ($qname eq "self.example.dname") {
|
||||
if ($qtype eq "DNAME") {
|
||||
my $rr = new Net::DNS::RR("$qname $ttl $qclass DNAME dname.");
|
||||
push @ans, $rr;
|
||||
}
|
||||
$rcode = "NOERROR";
|
||||
} else {
|
||||
$rcode = "REFUSED";
|
||||
}
|
||||
|
||||
@@ -24,6 +24,10 @@ ns2.example. A 10.53.0.2
|
||||
example.broken. NS ns3.example.broken.
|
||||
ns3.example.broken. A 10.53.0.3
|
||||
|
||||
; for the resolver variant of the CVE-2021-25215 regression test
|
||||
example.dname. NS ns3.example.dname.
|
||||
ns3.example.dname. A 10.53.0.3
|
||||
|
||||
domain0.nil. NS ns2.domain0.nil
|
||||
domain1.nil. NS ns2.domain0.nil
|
||||
domain2.nil. NS ns2.domain0.nil
|
||||
|
||||
@@ -16,3 +16,5 @@ ns2 86400 AAAA fd92:7065:b8e:ffff::2
|
||||
@ 86400 AAAA 1:2:3::4
|
||||
* 86400 A 1.2.3.4
|
||||
* 86400 AAAA 1:2:3::4
|
||||
; CVE-2021-25215 regression test data
|
||||
self 86400 DNAME nil.
|
||||
|
||||
@@ -295,5 +295,23 @@ grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
# Regression test for CVE-2021-25215 (authoritative server).
|
||||
n=`expr $n + 1`
|
||||
echo_i "checking DNAME resolution via itself (authoritative) ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS @10.53.0.2 DNAME self.domain0.self.domain0.nil. > dig.out.2.$n 2>&1
|
||||
grep 'status: NOERROR' dig.out.2.$n > /dev/null 2>&1 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
# Regression test for CVE-2021-25215 (recursive resolver).
|
||||
n=`expr $n + 1`
|
||||
echo_i "checking DNAME resolution via itself (recursive) ($n)"
|
||||
ret=0
|
||||
$DIG $DIGOPTS @10.53.0.7 DNAME self.example.self.example.dname. > dig.out.7.$n 2>&1
|
||||
grep 'status: NOERROR' dig.out.7.$n > /dev/null 2>&1 || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=`expr $status + $ret`
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
||||
@@ -108,7 +108,7 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing AXFR fallback after IXFR failure ($n)"
|
||||
echo_i "testing AXFR fallback after IXFR failure (not exact error) ($n)"
|
||||
ret=0
|
||||
|
||||
# Provide a broken IXFR response and a working fallback AXFR response
|
||||
@@ -142,6 +142,66 @@ $DIG $DIGOPTS @10.53.0.1 nil. TXT | grep 'fallback AXFR' >/dev/null || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing AXFR fallback after IXFR failure (bad SOA owner) ($n)"
|
||||
ret=0
|
||||
|
||||
# Prepare for checking the logs later on.
|
||||
nextpart ns1/named.run >/dev/null
|
||||
|
||||
# Provide a broken IXFR response and a working fallback AXFR response.
|
||||
sendcmd <<EOF
|
||||
/SOA/
|
||||
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
/IXFR/
|
||||
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
nil. 300 SOA ns.nil. root.nil. 3 300 300 604800 300
|
||||
bad-owner. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
test.nil. 300 TXT "serial 4, malformed IXFR"
|
||||
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
/AXFR/
|
||||
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
/AXFR/
|
||||
nil. 300 NS ns.nil.
|
||||
test.nil. 300 TXT "serial 4, fallback AXFR"
|
||||
/AXFR/
|
||||
nil. 300 SOA ns.nil. root.nil. 4 300 300 604800 300
|
||||
EOF
|
||||
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
|
||||
|
||||
# A broken server would accept the malformed IXFR and apply its contents to the
|
||||
# zone. A fixed one would reject the IXFR and fall back to AXFR. Both IXFR and
|
||||
# AXFR above bring the nil. zone up to serial 4, but we cannot reliably query
|
||||
# for the SOA record to check whether the transfer was finished because a broken
|
||||
# server would send back SERVFAIL responses to SOA queries after accepting the
|
||||
# malformed IXFR. Instead, check transfer progress by querying for a TXT record
|
||||
# at test.nil. which is present in both IXFR and AXFR (with different contents).
|
||||
_wait_until_transfer_is_finished() {
|
||||
$DIG $DIGOPTS +tries=1 +time=1 @10.53.0.1 test.nil. TXT > dig.out.test$n.1 &&
|
||||
grep -q -F "serial 4" dig.out.test$n.1
|
||||
}
|
||||
if ! retry_quiet 10 _wait_until_transfer_is_finished; then
|
||||
echo_i "timed out waiting for version 4 of zone nil. to be transferred"
|
||||
ret=1
|
||||
fi
|
||||
|
||||
# At this point a broken server would be serving a zone with no SOA records.
|
||||
# Try crashing it by triggering a SOA refresh query.
|
||||
$RNDCCMD 10.53.0.1 refresh nil | sed 's/^/ns1 /' | cat_i
|
||||
|
||||
# Do not wait until the zone refresh completes - even if a crash has not
|
||||
# happened by now, a broken server would never serve the record which is only
|
||||
# present in the fallback AXFR, so checking for that is enough to verify if a
|
||||
# server is broken or not; if it is, it is bound to crash shortly anyway.
|
||||
$DIG $DIGOPTS test.nil. TXT @10.53.0.1 > dig.out.test$n.2 || ret=1
|
||||
grep -q -F "serial 4, fallback AXFR" dig.out.test$n.2 || ret=1
|
||||
|
||||
# Ensure the expected error is logged.
|
||||
nextpart ns1/named.run | grep -q -F "SOA name mismatch" || ret=1
|
||||
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "testing ixfr-from-differences option ($n)"
|
||||
# ns3 is primary; ns4 is secondary
|
||||
|
||||
@@ -1705,20 +1705,25 @@ n=$((n+1))
|
||||
echo_i "check not in cache longttl.example times out (stale-answer-client-timeout 1.8) ($n)"
|
||||
ret=0
|
||||
wait_for_log 3 "longttl.example client timeout, stale answer unavailable" ns3/named.run || ret=1
|
||||
waitfile() {
|
||||
check_results() {
|
||||
[ -s "$1" ] || return 1
|
||||
grep "connection timed out" "$1" > /dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
retry_quiet 3 waitfile dig.out.test$n || ret=1
|
||||
grep "connection timed out" dig.out.test$n > /dev/null || ret=1
|
||||
retry_quiet 3 check_results dig.out.test$n || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
n=$((n+1))
|
||||
echo_i "check not in cache longttl.example comes from authoritative (stale-answer-client-timeout 1.8) ($n)"
|
||||
ret=0
|
||||
retry_quiet 7 waitfile dig.out.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.test$n > /dev/null || ret=1
|
||||
grep "ANSWER: 1," dig.out.test$n > /dev/null || ret=1
|
||||
check_results() {
|
||||
[ -s "$1" ] || return 1
|
||||
grep "status: NOERROR" "$1" > /dev/null || return 1
|
||||
grep "ANSWER: 1," "$1" > /dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
retry_quiet 7 check_results dig.out.test$n || ret=1
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status+ret))
|
||||
|
||||
|
||||
@@ -22,7 +22,8 @@ from helper import fmt
|
||||
# JSON helper functions
|
||||
def fetch_zones_json(statsip, statsport):
|
||||
|
||||
r = requests.get("http://{}:{}/json/v1/zones".format(statsip, statsport))
|
||||
r = requests.get("http://{}:{}/json/v1/zones".format(statsip, statsport),
|
||||
timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
data = r.json()
|
||||
@@ -31,7 +32,8 @@ def fetch_zones_json(statsip, statsport):
|
||||
|
||||
def fetch_traffic_json(statsip, statsport):
|
||||
|
||||
r = requests.get("http://{}:{}/json/v1/traffic".format(statsip, statsport))
|
||||
r = requests.get("http://{}:{}/json/v1/traffic".format(statsip, statsport),
|
||||
timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
data = r.json()
|
||||
|
||||
@@ -23,7 +23,8 @@ from helper import fmt
|
||||
# XML helper functions
|
||||
def fetch_zones_xml(statsip, statsport):
|
||||
|
||||
r = requests.get("http://{}:{}/xml/v3/zones".format(statsip, statsport))
|
||||
r = requests.get("http://{}:{}/xml/v3/zones".format(statsip, statsport),
|
||||
timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
root = ET.fromstring(r.text)
|
||||
@@ -47,7 +48,8 @@ def fetch_traffic_xml(statsip, statsport):
|
||||
|
||||
return out
|
||||
|
||||
r = requests.get("http://{}:{}/xml/v3/traffic".format(statsip, statsport))
|
||||
r = requests.get("http://{}:{}/xml/v3/traffic".format(statsip, statsport),
|
||||
timeout=600)
|
||||
assert r.status_code == 200
|
||||
|
||||
root = ET.fromstring(r.text)
|
||||
|
||||
14
configure.ac
14
configure.ac
@@ -14,7 +14,7 @@
|
||||
#
|
||||
m4_define([bind_VERSION_MAJOR], 9)dnl
|
||||
m4_define([bind_VERSION_MINOR], 17)dnl
|
||||
m4_define([bind_VERSION_PATCH], 13)dnl
|
||||
m4_define([bind_VERSION_PATCH], 14)dnl
|
||||
m4_define([bind_VERSION_EXTRA], )dnl
|
||||
m4_define([bind_DESCRIPTION], [(Development Release)])dnl
|
||||
m4_define([bind_SRCID], [m4_esyscmd_s([git rev-parse --short HEAD | cut -b1-7])])dnl
|
||||
@@ -593,18 +593,6 @@ AC_CHECK_HEADERS([pthread_np.h], [], [], [#include <pthread.h>])
|
||||
AC_MSG_CHECKING([for libuv])
|
||||
PKG_CHECK_MODULES([LIBUV], [libuv >= 1.0.0], [],
|
||||
[AC_MSG_ERROR([libuv not found])])
|
||||
AX_SAVE_FLAGS([libuv])
|
||||
|
||||
CFLAGS="$CFLAGS $LIBUV_CFLAGS"
|
||||
LIBS="$LIBS $LIBUV_LIBS"
|
||||
|
||||
# Those functions are only provided in newer versions of libuv, we'll be emulating them
|
||||
# for now
|
||||
AC_CHECK_FUNCS([uv_handle_get_data uv_handle_set_data])
|
||||
AC_CHECK_FUNCS([uv_req_get_data uv_req_set_data])
|
||||
AC_CHECK_FUNCS([uv_udp_connect uv_translate_sys_error uv_sleep])
|
||||
AC_CHECK_FUNCS([uv_os_getenv uv_os_setenv])
|
||||
AX_RESTORE_FLAGS([libuv])
|
||||
|
||||
# libnghttp2
|
||||
AC_MSG_CHECKING([for libnghttp2])
|
||||
|
||||
@@ -52,7 +52,7 @@ https://www.isc.org/download/. There you will find additional
|
||||
information about each release, source code, and pre-compiled versions
|
||||
for Microsoft Windows operating systems.
|
||||
|
||||
.. include:: ../notes/notes-current.rst
|
||||
.. include:: ../notes/notes-9.17.14.rst
|
||||
.. include:: ../notes/notes-9.17.13.rst
|
||||
.. include:: ../notes/notes-9.17.12.rst
|
||||
.. include:: ../notes/notes-9.17.11.rst
|
||||
|
||||
63
doc/notes/notes-9.17.14.rst
Normal file
63
doc/notes/notes-9.17.14.rst
Normal file
@@ -0,0 +1,63 @@
|
||||
..
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
|
||||
Notes for BIND 9.17.14
|
||||
----------------------
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- New configuration options, ``tcp-receive-buffer``,
|
||||
``tcp-send-buffer``, ``udp-receive-buffer``, and ``udp-send-buffer``,
|
||||
have been added. These options allow the operator to fine-tune the
|
||||
receiving and sending buffers in the operating system. On busy
|
||||
servers, increasing the size of the receive buffers can prevent the
|
||||
server from dropping packets during short traffic spikes, and
|
||||
decreasing it can prevent the server from becoming clogged with
|
||||
queries that are too old and have already timed out. :gl:`#2313`
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- Zone dumping tasks are now run on separate asynchronous thread pools.
|
||||
This change prevents zone dumping from blocking network I/O.
|
||||
:gl:`#2732`
|
||||
|
||||
- The interface handling code has been refactored to use fewer
|
||||
resources, which should lead to less memory fragmentation and better
|
||||
startup performance. :gl:`#2433`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- The calculation of the estimated IXFR transaction size in
|
||||
``dns_journal_iter_init()`` was invalid. This resulted in excessive
|
||||
AXFR-style IXFR responses. :gl:`#2685`
|
||||
|
||||
- Fixed an assertion failure that could occur if stale data was used to
|
||||
answer a query, and then a prefetch was triggered after the query was
|
||||
restarted (for example, to follow a CNAME). :gl:`#2733`
|
||||
|
||||
- If a query was answered with stale data on a server with DNS64
|
||||
enabled, an assertion could occur if a non-stale answer arrived
|
||||
afterward. This has been fixed. :gl:`#2731`
|
||||
|
||||
- Fixed an error which caused the ``IP_DONTFRAG`` socket option to be
|
||||
enabled instead of disabled, leading to errors when sending oversized
|
||||
UDP packets. :gl:`#2746`
|
||||
|
||||
- Zones which are configured in multiple views, with different values
|
||||
set for ``dnssec-policy`` and with identical values set for
|
||||
``key-directory``, are now detected and treated as a configuration
|
||||
error. :gl:`#2463`
|
||||
|
||||
- A race condition could occur when reading and writing key files for
|
||||
zones using KASP and configured in multiple views. This has been
|
||||
fixed. :gl:`#1875`
|
||||
@@ -1,74 +0,0 @@
|
||||
..
|
||||
Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See the COPYRIGHT file distributed with this work for additional
|
||||
information regarding copyright ownership.
|
||||
|
||||
Notes for BIND 9.17.14
|
||||
----------------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Known Issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- New configuration options, ``tcp-receive-buffer``, ``tcp-send-buffer``,
|
||||
``udp-receive-buffer``, and ``udp-send-buffer``, have been added. These
|
||||
options allows the operator to fine tune the receiving and sending
|
||||
buffers in the operating system. On busy servers, increasing the value
|
||||
of the receive buffers can prevent the server from dropping the packets
|
||||
during short spikes, and decreasing the value would prevent the server to
|
||||
became clogged up with queries that are too old and have already timeouted
|
||||
on the receiving side. :gl:`#2313`
|
||||
|
||||
- Run zone dumping tasks on separate asynchronous thread pools. This change
|
||||
makes zone dumping no longer block networking I/O. :gl:`#2732`
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- The interface handling code has been refactored to use fewer resources,
|
||||
which should lead to less memory fragmentation and better startup
|
||||
performance. :gl:`#2433`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- Fix a race condition in reading and writing key files for KASP zones in
|
||||
multiple views. :gl:`#1875`
|
||||
|
||||
- Check ``key-directory`` conflicts in ``named.conf`` for zones in multiple
|
||||
views with different ``dnssec-policy``. Using the same ``key-directory`` for
|
||||
such zones is not allowed. :gl:`#2463`
|
||||
|
||||
- ``named-checkconf`` now complains if zones with ``dnssec-policy`` reference
|
||||
the same zone file more than once. :gl:`#2603`
|
||||
|
||||
- The calculation of the estimated IXFR transaction size by
|
||||
`dns_journal_iter_init()` was invalid. This resulted in excessive
|
||||
AXFR-style-IXFR responses. :gl:`#2685`
|
||||
|
||||
- If a query was answered with stale data on a server with DNS64 enabled,
|
||||
an assertion could occur if a non-stale answer arrived afterward. This
|
||||
has been fixed. :gl:`#2731`
|
||||
|
||||
- Fixed an assertion failure that could occur if stale data was used
|
||||
to answer a query, and then a prefetch was triggered after the query
|
||||
was restarted (for example, to follow a CNAME). :gl:`#2733`
|
||||
@@ -254,7 +254,6 @@ struct dns_dumpctx {
|
||||
isc_mutex_t lock;
|
||||
isc_refcount_t references;
|
||||
atomic_bool canceled;
|
||||
bool first;
|
||||
bool do_date;
|
||||
isc_stdtime_t now;
|
||||
FILE *f;
|
||||
@@ -1578,7 +1577,6 @@ dumpctx_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *version,
|
||||
dctx->done = NULL;
|
||||
dctx->done_arg = NULL;
|
||||
dctx->task = NULL;
|
||||
dctx->first = true;
|
||||
atomic_init(&dctx->canceled, false);
|
||||
dctx->file = NULL;
|
||||
dctx->tmpfile = NULL;
|
||||
@@ -1737,7 +1735,6 @@ dumptostream(dns_dumpctx_t *dctx) {
|
||||
char *bufmem;
|
||||
dns_name_t *name;
|
||||
dns_fixedname_t fixname;
|
||||
isc_time_t start;
|
||||
|
||||
bufmem = isc_mem_get(dctx->mctx, initial_buffer_length);
|
||||
|
||||
@@ -1745,32 +1742,24 @@ dumptostream(dns_dumpctx_t *dctx) {
|
||||
|
||||
name = dns_fixedname_initname(&fixname);
|
||||
|
||||
if (dctx->first) {
|
||||
CHECK(writeheader(dctx));
|
||||
CHECK(writeheader(dctx));
|
||||
|
||||
/*
|
||||
* Fast format is not currently written incrementally,
|
||||
* so we make the call to dns_db_serialize() here.
|
||||
* If the database is anything other than an rbtdb,
|
||||
* this should result in not implemented
|
||||
*/
|
||||
if (dctx->format == dns_masterformat_map) {
|
||||
result = dns_db_serialize(dctx->db, dctx->version,
|
||||
dctx->f);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = dns_dbiterator_first(dctx->dbiter);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
dctx->first = false;
|
||||
} else {
|
||||
result = ISC_R_SUCCESS;
|
||||
/*
|
||||
* Fast format is not currently written incrementally,
|
||||
* so we make the call to dns_db_serialize() here.
|
||||
* If the database is anything other than an rbtdb,
|
||||
* this should result in not implemented
|
||||
*/
|
||||
if (dctx->format == dns_masterformat_map) {
|
||||
result = dns_db_serialize(dctx->db, dctx->version, dctx->f);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
result = dns_dbiterator_first(dctx->dbiter);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
isc_time_now(&start);
|
||||
while (result == ISC_R_SUCCESS) {
|
||||
dns_rdatasetiter_t *rdsiter = NULL;
|
||||
dns_dbnode_t *node = NULL;
|
||||
@@ -1790,6 +1779,10 @@ dumptostream(dns_dumpctx_t *dctx) {
|
||||
}
|
||||
dctx->tctx.neworigin = origin;
|
||||
}
|
||||
|
||||
result = dns_dbiterator_pause(dctx->dbiter);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
result = dns_db_allrdatasets(dctx->db, node, dctx->version,
|
||||
dctx->now, &rdsiter);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <isc/print.h>
|
||||
#include <isc/tls.h>
|
||||
#include <isc/url.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include "netmgr-int.h"
|
||||
|
||||
@@ -58,6 +59,19 @@
|
||||
#define MIN_SUCCESSFUL_HTTP_STATUS (200)
|
||||
#define MAX_SUCCESSFUL_HTTP_STATUS (299)
|
||||
|
||||
/* This definition sets the upper limit of pending write buffer to an
|
||||
* adequate enough value. That is done mostly to fight a limitation
|
||||
* for a max TLS record size in flamethrower (2K). In a perfect world
|
||||
* this constant should not be required, if we ever move closer to
|
||||
* that state, the constant, and corresponding code, should be
|
||||
* removed. For now the limit seems adequate enough to fight
|
||||
* "tinygrams" problem. */
|
||||
#define FLUSH_HTTP_WRITE_BUFFER_AFTER (1536)
|
||||
|
||||
/* This switch is here mostly to test the code interoperability with
|
||||
* buggy implementations */
|
||||
#define ENABLE_HTTP_WRITE_BUFFERING 1
|
||||
|
||||
#define SUCCESSFUL_HTTP_STATUS(code) \
|
||||
((code) >= MIN_SUCCESSFUL_HTTP_STATUS && \
|
||||
(code) <= MAX_SUCCESSFUL_HTTP_STATUS)
|
||||
@@ -104,6 +118,8 @@ typedef struct http_cstream {
|
||||
#define HTTP2_SESSION_MAGIC ISC_MAGIC('H', '2', 'S', 'S')
|
||||
#define VALID_HTTP2_SESSION(t) ISC_MAGIC_VALID(t, HTTP2_SESSION_MAGIC)
|
||||
|
||||
typedef ISC_LIST(isc__nm_uvreq_t) isc__nm_http_pending_callbacks_t;
|
||||
|
||||
struct isc_nm_http_session {
|
||||
unsigned int magic;
|
||||
isc_refcount_t references;
|
||||
@@ -130,6 +146,9 @@ struct isc_nm_http_session {
|
||||
size_t bufsize;
|
||||
|
||||
isc_tlsctx_t *tlsctx;
|
||||
|
||||
isc__nm_http_pending_callbacks_t pending_write_callbacks;
|
||||
isc_buffer_t *pending_write_data;
|
||||
};
|
||||
|
||||
typedef enum isc_http_error_responses {
|
||||
@@ -151,6 +170,7 @@ typedef struct isc_http_send_req {
|
||||
isc_region_t data;
|
||||
isc_nm_cb_t cb;
|
||||
void *cbarg;
|
||||
isc__nm_http_pending_callbacks_t pending_write_callbacks;
|
||||
} isc_http_send_req_t;
|
||||
|
||||
static bool
|
||||
@@ -187,6 +207,10 @@ finish_http_session(isc_nm_http_session_t *session);
|
||||
static void
|
||||
http_transpost_tcp_nodelay(isc_nmhandle_t *transphandle);
|
||||
|
||||
static void
|
||||
call_pending_callbacks(isc__nm_http_pending_callbacks_t pending_callbacks,
|
||||
isc_result_t result);
|
||||
|
||||
static bool
|
||||
http_session_active(isc_nm_http_session_t *session) {
|
||||
REQUIRE(VALID_HTTP2_SESSION(session));
|
||||
@@ -251,6 +275,7 @@ new_session(isc_mem_t *mctx, isc_tlsctx_t *tctx,
|
||||
isc_mem_attach(mctx, &session->mctx);
|
||||
ISC_LIST_INIT(session->cstreams);
|
||||
ISC_LIST_INIT(session->sstreams);
|
||||
ISC_LIST_INIT(session->pending_write_callbacks);
|
||||
|
||||
*sessionp = session;
|
||||
}
|
||||
@@ -431,6 +456,15 @@ finish_http_session(isc_nm_http_session_t *session) {
|
||||
} else {
|
||||
server_call_failed_read_cb(ISC_R_UNEXPECTED, session);
|
||||
}
|
||||
|
||||
call_pending_callbacks(session->pending_write_callbacks,
|
||||
ISC_R_UNEXPECTED);
|
||||
ISC_LIST_INIT(session->pending_write_callbacks);
|
||||
|
||||
if (session->pending_write_data != NULL) {
|
||||
isc_buffer_free(&session->pending_write_data);
|
||||
}
|
||||
|
||||
isc_nmhandle_detach(&session->handle);
|
||||
}
|
||||
|
||||
@@ -890,6 +924,18 @@ http_readcb(isc_nmhandle_t *handle, isc_result_t result, isc_region_t *region,
|
||||
http_do_bio(session, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
call_pending_callbacks(isc__nm_http_pending_callbacks_t pending_callbacks,
|
||||
isc_result_t result) {
|
||||
isc__nm_uvreq_t *cbreq = ISC_LIST_HEAD(pending_callbacks);
|
||||
while (cbreq != NULL) {
|
||||
isc__nm_uvreq_t *next = ISC_LIST_NEXT(cbreq, link);
|
||||
ISC_LIST_UNLINK(pending_callbacks, cbreq, link);
|
||||
isc__nm_sendcb(cbreq->handle->sock, cbreq, result, false);
|
||||
cbreq = next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
http_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isc_http_send_req_t *req = (isc_http_send_req_t *)arg;
|
||||
@@ -903,6 +949,8 @@ http_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
INSIST(session->handle == handle);
|
||||
}
|
||||
|
||||
call_pending_callbacks(req->pending_write_callbacks, result);
|
||||
|
||||
if (req->cb != NULL) {
|
||||
req->cb(req->httphandle, result, req->cbarg);
|
||||
isc_nmhandle_detach(&req->httphandle);
|
||||
@@ -911,8 +959,8 @@ http_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isc_mem_put(session->mctx, req->data.base, req->data.length);
|
||||
isc_mem_put(session->mctx, req, sizeof(*req));
|
||||
|
||||
http_do_bio(session, NULL, NULL, NULL);
|
||||
session->sending--;
|
||||
http_do_bio(session, NULL, NULL, NULL);
|
||||
isc_nmhandle_detach(&transphandle);
|
||||
if (result != ISC_R_SUCCESS && session->sending == 0) {
|
||||
finish_http_session(session);
|
||||
@@ -920,31 +968,187 @@ http_writecb(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
|
||||
isc__nm_httpsession_detach(&session);
|
||||
}
|
||||
|
||||
static void
|
||||
move_pending_send_callbacks(isc_nm_http_session_t *session,
|
||||
isc_http_send_req_t *send) {
|
||||
STATIC_ASSERT(
|
||||
sizeof(session->pending_write_callbacks) ==
|
||||
sizeof(send->pending_write_callbacks),
|
||||
"size of pending writes requests callbacks lists differs");
|
||||
memmove(&send->pending_write_callbacks,
|
||||
&session->pending_write_callbacks,
|
||||
sizeof(session->pending_write_callbacks));
|
||||
ISC_LIST_INIT(session->pending_write_callbacks);
|
||||
}
|
||||
|
||||
static bool
|
||||
http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
|
||||
isc_nm_cb_t cb, void *cbarg) {
|
||||
isc_http_send_req_t *send = NULL;
|
||||
const uint8_t *data = NULL;
|
||||
size_t pending;
|
||||
size_t total = 0;
|
||||
uint8_t tmp_data[8192] = { 0 };
|
||||
uint8_t *prepared_data = &tmp_data[0];
|
||||
#ifdef ENABLE_HTTP_WRITE_BUFFERING
|
||||
size_t max_total_write_size = 0;
|
||||
#endif /* ENABLE_HTTP_WRITE_BUFFERING */
|
||||
|
||||
if (!http_session_active(session) ||
|
||||
!nghttp2_session_want_write(session->ngsession))
|
||||
(!nghttp2_session_want_write(session->ngsession) &&
|
||||
session->pending_write_data == NULL))
|
||||
{
|
||||
return (false);
|
||||
}
|
||||
|
||||
pending = nghttp2_session_mem_send(session->ngsession, &data);
|
||||
if (pending == 0) {
|
||||
while (nghttp2_session_want_write(session->ngsession)) {
|
||||
const uint8_t *data = NULL;
|
||||
const size_t pending =
|
||||
nghttp2_session_mem_send(session->ngsession, &data);
|
||||
const size_t new_total = total + pending;
|
||||
|
||||
/* reallocate buffer if required */
|
||||
if (new_total > sizeof(tmp_data)) {
|
||||
uint8_t *old_prepared_data = prepared_data;
|
||||
const bool allocated = prepared_data != tmp_data;
|
||||
|
||||
prepared_data = isc_mem_get(session->mctx, new_total);
|
||||
memmove(prepared_data, old_prepared_data, total);
|
||||
if (allocated) {
|
||||
isc_mem_put(session->mctx, old_prepared_data,
|
||||
total);
|
||||
}
|
||||
}
|
||||
memmove(&prepared_data[total], data, pending);
|
||||
total = new_total;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_HTTP_WRITE_BUFFERING
|
||||
max_total_write_size = total;
|
||||
if (session->pending_write_data != NULL) {
|
||||
max_total_write_size +=
|
||||
isc_buffer_usedlength(session->pending_write_data);
|
||||
}
|
||||
|
||||
/* Here we are trying to flush the pending writes buffer earlier
|
||||
* to avoid hitting unnecessary limitations on a TLS record size
|
||||
* within some tools (e.g. flamethrower). */
|
||||
if (max_total_write_size >= FLUSH_HTTP_WRITE_BUFFER_AFTER) {
|
||||
/* Case 1: We have equal or more than
|
||||
* FLUSH_HTTP_WRITE_BUFFER_AFTER bytes to send. Let's put the
|
||||
* data which we have just obtained from nghttp2 into the
|
||||
* pending write buffer and flush it. */
|
||||
|
||||
/* Let's allocate a new write buffer if there is none. */
|
||||
if (session->pending_write_data == NULL) {
|
||||
isc_buffer_allocate(session->mctx,
|
||||
&session->pending_write_data,
|
||||
max_total_write_size);
|
||||
}
|
||||
|
||||
isc_buffer_putmem(session->pending_write_data, prepared_data,
|
||||
total);
|
||||
if (prepared_data != &tmp_data[0]) {
|
||||
isc_mem_put(session->mctx, prepared_data, total);
|
||||
}
|
||||
|
||||
total = max_total_write_size;
|
||||
prepared_data = isc_buffer_base(session->pending_write_data);
|
||||
} else if (session->sending > 0 && total > 0) {
|
||||
/* Case 2: There is one or more write requests in flight and
|
||||
* we have some new data form nghttp2 to send. Let's put the
|
||||
* write callback (if any) into the pending write callbacks
|
||||
* list and add the new data into the pending write
|
||||
* buffer. Then let's return from the function: as soon as the
|
||||
* "in-flight" write callback get's called or we have reached
|
||||
* FLUSH_HTTP_WRITE_BUFFER_AFTER bytes in the write buffer, we
|
||||
* will flush the buffer. */
|
||||
if (cb != NULL) {
|
||||
isc__nm_uvreq_t *newcb = isc__nm_uvreq_get(
|
||||
httphandle->sock->mgr, httphandle->sock);
|
||||
|
||||
INSIST(VALID_NMHANDLE(httphandle));
|
||||
newcb->cb.send = cb;
|
||||
newcb->cbarg = cbarg;
|
||||
isc_nmhandle_attach(httphandle, &newcb->handle);
|
||||
ISC_LIST_APPEND(session->pending_write_callbacks, newcb,
|
||||
link);
|
||||
}
|
||||
|
||||
if (session->pending_write_data == NULL) {
|
||||
isc_buffer_allocate(session->mctx,
|
||||
&session->pending_write_data,
|
||||
total);
|
||||
isc_buffer_setautorealloc(session->pending_write_data,
|
||||
true);
|
||||
}
|
||||
|
||||
isc_buffer_putmem(session->pending_write_data, prepared_data,
|
||||
total);
|
||||
if (prepared_data != &tmp_data[0]) {
|
||||
isc_mem_put(session->mctx, prepared_data, total);
|
||||
}
|
||||
return (false);
|
||||
} else if (session->sending == 0 && total == 0 &&
|
||||
session->pending_write_data != NULL)
|
||||
{
|
||||
/* Case 3: There is no write in flight and we haven't got
|
||||
* anything new from nghttp2, but there is some data pending
|
||||
* in the write buffer. Let's flush the buffer. */
|
||||
isc_region_t region = { 0 };
|
||||
total = isc_buffer_usedlength(session->pending_write_data);
|
||||
INSIST(total > 0);
|
||||
INSIST(prepared_data == &tmp_data[0]);
|
||||
isc_buffer_usedregion(session->pending_write_data, ®ion);
|
||||
INSIST(total == region.length);
|
||||
prepared_data = region.base;
|
||||
} else {
|
||||
/* The other cases are, uninteresting, fall-through ones. */
|
||||
/* In the following cases (4-6) we will just bail out. */
|
||||
/* Case 4: There is nothing new to send, nor anything in the
|
||||
* write buffer. */
|
||||
/* Case 5: There is nothing new to send and there is write
|
||||
* request(s) in flight. */
|
||||
/* Case 6: There is nothing new to send nor there are any
|
||||
* write requests in flight. */
|
||||
|
||||
/* Case 7: There is some new data to send and there are no any
|
||||
* write requests in flight: Let's send the data.*/
|
||||
INSIST((total == 0 && session->pending_write_data == NULL) ||
|
||||
(total == 0 && session->sending > 0) ||
|
||||
(total == 0 && session->sending == 0) ||
|
||||
(total > 0 && session->sending == 0));
|
||||
}
|
||||
#else
|
||||
INSIST(session->pending_write_data == NULL);
|
||||
INSIST(ISC_LIST_EMPTY(session->pending_write_callbacks));
|
||||
#endif /* ENABLE_HTTP_WRITE_BUFFERING */
|
||||
|
||||
if (total == 0) {
|
||||
INSIST(prepared_data == &tmp_data[0]);
|
||||
/* No data returned */
|
||||
return (false);
|
||||
}
|
||||
|
||||
send = isc_mem_get(session->mctx, sizeof(*send));
|
||||
*send = (isc_http_send_req_t){
|
||||
.data.base = isc_mem_get(session->mctx, pending),
|
||||
.data.length = pending,
|
||||
};
|
||||
memmove(send->data.base, data, pending);
|
||||
if (prepared_data == &tmp_data[0]) {
|
||||
*send = (isc_http_send_req_t){
|
||||
.data.base = isc_mem_get(session->mctx, total),
|
||||
.data.length = total,
|
||||
};
|
||||
memmove(send->data.base, tmp_data, total);
|
||||
} else if (session->pending_write_data != NULL) {
|
||||
*send = (isc_http_send_req_t){
|
||||
.data.base = isc_mem_get(session->mctx, total),
|
||||
.data.length = total,
|
||||
};
|
||||
memmove(send->data.base,
|
||||
isc_buffer_base(session->pending_write_data), total);
|
||||
isc_buffer_free(&session->pending_write_data);
|
||||
} else {
|
||||
*send = (isc_http_send_req_t){
|
||||
.data.base = prepared_data,
|
||||
.data.length = total,
|
||||
};
|
||||
}
|
||||
isc_nmhandle_attach(session->handle, &send->transphandle);
|
||||
isc__nm_httpsession_attach(session, &send->session);
|
||||
|
||||
@@ -955,6 +1159,8 @@ http_send_outgoing(isc_nm_http_session_t *session, isc_nmhandle_t *httphandle,
|
||||
isc_nmhandle_attach(httphandle, &send->httphandle);
|
||||
}
|
||||
|
||||
move_pending_send_callbacks(session, send);
|
||||
|
||||
session->sending++;
|
||||
isc_nm_send(session->handle, &send->data, http_writecb, send);
|
||||
return (true);
|
||||
@@ -975,8 +1181,9 @@ http_do_bio(isc_nm_http_session_t *session, isc_nmhandle_t *send_httphandle,
|
||||
finish_http_session(session);
|
||||
}
|
||||
return;
|
||||
} else if ((nghttp2_session_want_read(session->ngsession) == 0 &&
|
||||
nghttp2_session_want_write(session->ngsession) == 0))
|
||||
} else if (nghttp2_session_want_read(session->ngsession) == 0 &&
|
||||
nghttp2_session_want_write(session->ngsession) == 0 &&
|
||||
session->pending_write_data == NULL)
|
||||
{
|
||||
session->closing = true;
|
||||
return;
|
||||
|
||||
@@ -2985,7 +2985,7 @@ isc__nm_closesocket(uv_os_sock_t sock) {
|
||||
setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
|
||||
|
||||
#define setsockopt_off(socket, level, name) \
|
||||
setsockopt(socket, level, name, &(int){ 1 }, sizeof(int))
|
||||
setsockopt(socket, level, name, &(int){ 0 }, sizeof(int))
|
||||
|
||||
isc_result_t
|
||||
isc__nm_socket_freebind(uv_os_sock_t fd, sa_family_t sa_family) {
|
||||
|
||||
@@ -578,7 +578,7 @@ udp_send_direct(isc_nmsocket_t *sock, isc__nm_uvreq_t *req,
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
#ifdef HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
/*
|
||||
* If we used uv_udp_connect() (and not the shim version for
|
||||
* older versions of libuv), then the peer address has to be
|
||||
|
||||
@@ -36,11 +36,11 @@ isc_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) {
|
||||
#ifdef WIN32
|
||||
return (uv_translate_sys_error(err));
|
||||
#else /* WIN32 */
|
||||
#ifdef HAVE_UV_TRANSLATE_SYS_ERROR
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 10, 0)
|
||||
return (uv_translate_sys_error(errno));
|
||||
#else
|
||||
return (-errno);
|
||||
#endif /* HAVE_UV_TRANSLATE_SYS_ERROR */
|
||||
#endif /* UV_VERSION_HEX >= UV_VERSION(1, 10, 0) */
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
|
||||
@@ -694,7 +694,7 @@ mock_udpconnect_uv_udp_bind(void **state __attribute__((unused))) {
|
||||
RESET_RETURN;
|
||||
}
|
||||
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
static void
|
||||
mock_udpconnect_uv_udp_connect(void **state __attribute__((unused))) {
|
||||
WILL_RETURN(uv_udp_connect, UV_ENOMEM);
|
||||
@@ -2730,7 +2730,7 @@ main(void) {
|
||||
nm_setup, nm_teardown),
|
||||
cmocka_unit_test_setup_teardown(mock_udpconnect_uv_udp_bind,
|
||||
nm_setup, nm_teardown),
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
cmocka_unit_test_setup_teardown(mock_udpconnect_uv_udp_connect,
|
||||
nm_setup, nm_teardown),
|
||||
#endif
|
||||
|
||||
@@ -155,25 +155,38 @@ set_global_error(isc_result_t result) {
|
||||
}
|
||||
|
||||
static void
|
||||
subthread_assert_true(bool expected) {
|
||||
subthread_assert_true(bool expected, const char *file, unsigned int line) {
|
||||
if (!expected) {
|
||||
printf("# %s:%u subthread_assert_true\n", file, line);
|
||||
set_global_error(ISC_R_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
#define subthread_assert_true(expected) \
|
||||
subthread_assert_true(expected, __FILE__, __LINE__)
|
||||
|
||||
static void
|
||||
subthread_assert_int_equal(int observed, int expected) {
|
||||
subthread_assert_int_equal(int observed, int expected, const char *file,
|
||||
unsigned int line) {
|
||||
if (observed != expected) {
|
||||
printf("# %s:%u subthread_assert_int_equal(%d != %d)\n", file,
|
||||
line, observed, expected);
|
||||
set_global_error(ISC_R_UNEXPECTED);
|
||||
}
|
||||
}
|
||||
#define subthread_assert_int_equal(observed, expected) \
|
||||
subthread_assert_int_equal(observed, expected, __FILE__, __LINE__)
|
||||
|
||||
static void
|
||||
subthread_assert_result_equal(isc_result_t result, isc_result_t expected) {
|
||||
subthread_assert_result_equal(isc_result_t result, isc_result_t expected,
|
||||
const char *file, unsigned int line) {
|
||||
if (result != expected) {
|
||||
printf("# %s:%u subthread_assert_result_equal(%u != %u)\n",
|
||||
file, line, result, expected);
|
||||
set_global_error(result);
|
||||
}
|
||||
}
|
||||
#define subthread_assert_result_equal(observed, expected) \
|
||||
subthread_assert_result_equal(observed, expected, __FILE__, __LINE__)
|
||||
|
||||
static void
|
||||
ticktock(isc_task_t *task, isc_event_t *event) {
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#define UNIT_TESTING
|
||||
#include <cmocka.h>
|
||||
|
||||
#include "../netmgr/uv-compat.h"
|
||||
|
||||
/* uv_udp_t */
|
||||
|
||||
int
|
||||
@@ -33,13 +35,13 @@ __wrap_uv_udp_open(uv_udp_t *handle, uv_os_sock_t sock);
|
||||
int
|
||||
__wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr,
|
||||
unsigned int flags);
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
int
|
||||
__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr);
|
||||
int
|
||||
__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name,
|
||||
int *namelen);
|
||||
#endif /* HAVE_UV_UDP_CONNECT */
|
||||
#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */
|
||||
int
|
||||
__wrap_uv_udp_getsockname(const uv_udp_t *handle, struct sockaddr *name,
|
||||
int *namelen);
|
||||
@@ -114,7 +116,7 @@ __wrap_uv_udp_bind(uv_udp_t *handle, const struct sockaddr *addr,
|
||||
static atomic_int __state_uv_udp_connect
|
||||
__attribute__((unused)) = ATOMIC_VAR_INIT(0);
|
||||
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
int
|
||||
__wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) {
|
||||
if (atomic_load(&__state_uv_udp_connect) == 0) {
|
||||
@@ -122,12 +124,12 @@ __wrap_uv_udp_connect(uv_udp_t *handle, const struct sockaddr *addr) {
|
||||
}
|
||||
return (atomic_load(&__state_uv_udp_connect));
|
||||
}
|
||||
#endif /* HAVE_UV_UDP_CONNECT */
|
||||
#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */
|
||||
|
||||
static atomic_int __state_uv_udp_getpeername
|
||||
__attribute__((unused)) = ATOMIC_VAR_INIT(0);
|
||||
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
int
|
||||
__wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name,
|
||||
int *namelen) {
|
||||
@@ -136,7 +138,7 @@ __wrap_uv_udp_getpeername(const uv_udp_t *handle, struct sockaddr *name,
|
||||
}
|
||||
return (atomic_load(&__state_uv_udp_getpeername));
|
||||
}
|
||||
#endif /* HAVE_UV_UDP_CONNECT */
|
||||
#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */
|
||||
|
||||
static atomic_int __state_uv_udp_getsockname = ATOMIC_VAR_INIT(0);
|
||||
int
|
||||
@@ -274,10 +276,10 @@ __wrap_uv_fileno(const uv_handle_t *handle, uv_os_fd_t *fd) {
|
||||
|
||||
#define uv_udp_open(...) __wrap_uv_udp_open(__VA_ARGS__)
|
||||
#define uv_udp_bind(...) __wrap_uv_udp_bind(__VA_ARGS__)
|
||||
#if HAVE_UV_UDP_CONNECT
|
||||
#if UV_VERSION_HEX >= UV_VERSION(1, 27, 0)
|
||||
#define uv_udp_connect(...) __wrap_uv_udp_connect(__VA_ARGS__)
|
||||
#define uv_udp_getpeername(...) __wrap_uv_udp_getpeername(__VA_ARGS__)
|
||||
#endif /* HAVE_UV_UDP_CONNECT */
|
||||
#endif /* UV_VERSION_HEX >= UV_VERSION(1, 27, 0) */
|
||||
#define uv_udp_getsockname(...) __wrap_uv_udp_getsockname(__VA_ARGS__)
|
||||
#define uv_udp_send(...) __wrap_uv_udp_send(__VA_ARGS__)
|
||||
#define uv_udp_recv_start(...) __wrap_uv_udp_recv_start(__VA_ARGS__)
|
||||
|
||||
Reference in New Issue
Block a user