Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f289188a3 |
@@ -1,63 +1,3 @@
|
||||
--- 9.18.25 released ---
|
||||
|
||||
6356. [bug] Create the pruning task in the dns_cache_flush(), so
|
||||
the cache pruning still works after the flush.
|
||||
[GL #4621]
|
||||
|
||||
6353. [bug] Improve the TTL-based cleaning by removing the expired
|
||||
headers from the heap, so they don't block the next
|
||||
cleaning round and clean more than a single item for
|
||||
each new addition to the RBTDB. [GL #4591]
|
||||
|
||||
6352. [bug] Revert change 6319 and decrease lock contention during
|
||||
RBTDB tree pruning by not cleaning up nodes recursively
|
||||
within a single prune_tree() call. [GL #4596]
|
||||
|
||||
6350. [bug] Address use after free in expire_lru_headers. [GL #4495]
|
||||
|
||||
--- 9.18.24 released ---
|
||||
|
||||
6343. [bug] Fix case insensitive setting for isc_ht hashtable.
|
||||
[GL #4568]
|
||||
|
||||
--- 9.18.23 released ---
|
||||
|
||||
6322. [security] Specific DNS answers could cause a denial-of-service
|
||||
condition due to DNS validation taking a long time.
|
||||
(CVE-2023-50387) [GL #4424]
|
||||
|
||||
6321. [security] Change 6315 inadvertently introduced regressions that
|
||||
could cause named to crash. [GL #4234]
|
||||
|
||||
6320. [bug] Under some circumstances, the DoT code in client
|
||||
mode could process more than one message at a time when
|
||||
that was not expected. That has been fixed. [GL #4487]
|
||||
|
||||
--- 9.18.22 released ---
|
||||
|
||||
6319. [func] Limit isc_task_send() overhead for RBTDB tree pruning.
|
||||
[GL #4383]
|
||||
|
||||
6317. [security] Restore DNS64 state when handling a serve-stale timeout.
|
||||
(CVE-2023-5679) [GL #4334]
|
||||
|
||||
6316. [security] Specific queries could trigger an assertion check with
|
||||
nxdomain-redirect enabled. (CVE-2023-5517) [GL #4281]
|
||||
|
||||
6315. [security] Speed up parsing of DNS messages with many different
|
||||
names. (CVE-2023-4408) [GL #4234]
|
||||
|
||||
6314. [bug] Address race conditions in dns_tsigkey_find().
|
||||
[GL #4182]
|
||||
|
||||
6312. [bug] Conversion from NSEC3 signed to NSEC signed could
|
||||
temporarily put the zone into a state where it was
|
||||
treated as unsigned until the NSEC chain was built.
|
||||
Additionally conversion from one set of NSEC3 parameters
|
||||
to another could also temporarily put the zone into a
|
||||
state where it was treated as unsigned until the new
|
||||
NSEC3 chain was built. [GL #1794] [GL #4495]
|
||||
|
||||
6310. [bug] Memory leak in zone.c:sign_zone. When named signed a
|
||||
zone it could leak dst_keys due to a misplaced
|
||||
'continue'. [GL #4488]
|
||||
@@ -74,10 +14,6 @@
|
||||
message that was emitted even when the feature was
|
||||
explicitly disabled. [GL #4497]
|
||||
|
||||
6300. [bug] Fix statistics export to use full 64 bit signed numbers
|
||||
instead of truncating values to unsigned 32 bits.
|
||||
[GL #4467]
|
||||
|
||||
6299. [port] NetBSD has added 'hmac' to libc which collides with our
|
||||
use of 'hmac'. [GL #4478]
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ rm -f ./ns1/redirect.db
|
||||
rm -f ./ns2/redirect.db
|
||||
rm -f ./ns2/redirect.bk
|
||||
rm -f ./ns3/redirect.db
|
||||
rm -f ./ns*/managed-keys.bind* ns*/*.mkeys*
|
||||
rm -f ./ns*/managed-keys.bind* ./ns*/*.mkeys*
|
||||
rm -f ./ns*/*.jnl
|
||||
rm -f ./ns*/K*.key ./ns*/K*.private ./ns*/K*.state
|
||||
rm -f ./nzd2nzf.out.*
|
||||
rm -f ./wait_for_message.*
|
||||
|
||||
@@ -192,14 +192,6 @@ $KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out
|
||||
$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out
|
||||
$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out
|
||||
|
||||
#
|
||||
# NSEC3->NSEC3 transition test zone.
|
||||
#
|
||||
setup nsec3-to-nsec3.example
|
||||
$KEYGEN -q -a $DEFAULT_ALGORITHM -fk $zone >kg.out 2>&1 || dumpit kg.out
|
||||
$KEYGEN -q -a $DEFAULT_ALGORITHM $zone >kg.out 2>&1 || dumpit kg.out
|
||||
$SIGNER -S -3 beef -A -o $zone -f $zonefile $infile >s.out || dumpit s.out
|
||||
|
||||
#
|
||||
# secure-to-insecure transition test zone; used to test removal of
|
||||
# keys via nsupdate
|
||||
|
||||
@@ -186,14 +186,6 @@ zone "secure-to-insecure2.example" {
|
||||
dnssec-secure-to-insecure yes;
|
||||
};
|
||||
|
||||
zone "nsec3-to-nsec3.example" {
|
||||
type primary;
|
||||
file "nsec3-to-nsec3.example.db";
|
||||
allow-update { any; };
|
||||
inline-signing no;
|
||||
max-journal-size 10M;
|
||||
};
|
||||
|
||||
zone "oldsigs.example" {
|
||||
type primary;
|
||||
file "oldsigs.example.db";
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
; Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
;
|
||||
; SPDX-License-Identifier: MPL-2.0
|
||||
;
|
||||
; 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.
|
||||
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
2009102722 ; serial
|
||||
20 ; refresh (20 seconds)
|
||||
20 ; retry (20 seconds)
|
||||
1814400 ; expire (3 weeks)
|
||||
3600 ; minimum (1 hour)
|
||||
)
|
||||
NS ns
|
||||
ns A 10.53.0.3
|
||||
|
||||
a A 10.0.0.1
|
||||
b A 10.0.0.2
|
||||
d A 10.0.0.4
|
||||
x CNAME a
|
||||
@@ -177,9 +177,6 @@ status=$((status + ret))
|
||||
echo_i "Convert optout-with-ent from nsec to nsec3"
|
||||
($RNDCCMD 10.53.0.2 signing -nsec3param 1 1 1 - optout-with-ent 2>&1 | sed 's/^/ns2 /' | cat_i) || ret=1
|
||||
|
||||
echo_i "Convert nsec3-to-nsec3.example from having salt 'beef' to no salt"
|
||||
($RNDCCMD 10.53.0.3 signing -nsec3param 1 1 1 - nsec3-to-nsec3.example 2>&1 | sed 's/^/ns3 /' | cat_i) || ret=1
|
||||
|
||||
echo_i "Initial counts of RRSIG expiry fields values for auto signed zones"
|
||||
for z in .; do
|
||||
echo_i zone $z
|
||||
@@ -1183,8 +1180,7 @@ checkprivate private.secure.example 10.53.0.3 2 || ret=1 # pre-signed
|
||||
checkprivate nsec3.example 10.53.0.3 || ret=1
|
||||
checkprivate nsec3.nsec3.example 10.53.0.3 || ret=1
|
||||
checkprivate nsec3.optout.example 10.53.0.3 || ret=1
|
||||
checkprivate nsec3-to-nsec.example 10.53.0.3 2 || ret=1 # automatically removed
|
||||
checkprivate nsec3-to-nsec3.example 10.53.0.3 2 || ret=1 # automatically removed
|
||||
checkprivate nsec3-to-nsec.example 10.53.0.3 2 || ret=1 # automatically removed
|
||||
if $SHELL ../testcrypto.sh -q RSASHA1; then
|
||||
checkprivate nsec-only.example 10.53.0.3 || ret=1
|
||||
fi
|
||||
@@ -1810,32 +1806,5 @@ n=$((n + 1))
|
||||
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "check that NSEC3 to NSEC builds the NSEC chain first ($n)"
|
||||
ret=0
|
||||
$JOURNALPRINT ns3/nsec3-to-nsec.example.db.jnl \
|
||||
| awk 'BEGIN { nsec3param=0; nsec=0 }
|
||||
$1 == "del" && $5 == "SOA" { if (nsec3param || nsec) { if (nsec3param && !nsec) { exit(1); } else { exit(0); } } }
|
||||
$1 == "del" && $5 == "NSEC3PARAM" { nsec3param=1 }
|
||||
$1 == "add" && $2 == "nsec3-to-nsec.example." && $5 == "NSEC" { nsec=1 }
|
||||
END { if (nsec3param || nsec) { if (nsec3param && !nsec) { exit(1); } else { exit(0); } } else { exit(1); } }
|
||||
' || ret=1
|
||||
n=$((n + 1))
|
||||
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "check that NSEC3 to NSEC3 builds the new NSEC3 chain first ($n)"
|
||||
ret=0
|
||||
$JOURNALPRINT ns3/nsec3-to-nsec3.example.db.jnl \
|
||||
| awk 'BEGIN { addnsec3param=0; delnsec3param=0; nsec3=0 }
|
||||
$1 == "del" && $5 == "SOA" { if (delnsec3param || nsec3 || addnsec3param) { if (delnsec3param && (!nsec3 || !addnsec3param)) { exit(1); } else { exit(0); } } }
|
||||
$1 == "del" && $5 == "NSEC3PARAM" { delnsec3param=1 }
|
||||
$1 == "add" && $5 == "NSEC3PARAM" { addnsec3param=1 }
|
||||
$1 == "add" && $5 == "NSEC3" { nsec3=1 }
|
||||
END { if (delnsec3param || nsec3 || addnsec3param) { if (delnsec3param && (!nsec3 || !addnsec3param)) { exit(1); } else { exit(0); } } else { exit(1); } }
|
||||
' || ret=1
|
||||
n=$((n + 1))
|
||||
if [ "$ret" -ne 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
||||
@@ -22,14 +22,9 @@ my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
|
||||
print $pidf "$$\n" or die "cannot write pid file: $!";
|
||||
$pidf->close or die "cannot close pid file: $!";
|
||||
sub rmpid { unlink "ans.pid"; exit 1; };
|
||||
sub term { };
|
||||
|
||||
$SIG{INT} = \&rmpid;
|
||||
if ($Net::DNS::VERSION > 1.41) {
|
||||
$SIG{TERM} = \&term;
|
||||
} else {
|
||||
$SIG{TERM} = \&rmpid;
|
||||
}
|
||||
$SIG{TERM} = \&rmpid;
|
||||
|
||||
my $localaddr = "10.53.0.3";
|
||||
|
||||
@@ -133,11 +128,4 @@ my $ns = Net::DNS::Nameserver->new(
|
||||
Verbose => $verbose,
|
||||
);
|
||||
|
||||
if ($Net::DNS::VERSION >= 1.42) {
|
||||
$ns->start_server();
|
||||
select(undef, undef, undef, undef);
|
||||
$ns->stop_server();
|
||||
unlink "ans.pid";
|
||||
} else {
|
||||
$ns->main_loop;
|
||||
}
|
||||
$ns->main_loop;
|
||||
|
||||
@@ -47,8 +47,3 @@ rrsigonly A 10.0.0.29
|
||||
cnameandkey CNAME @
|
||||
cnamenokey CNAME @
|
||||
dnameandkey DNAME @
|
||||
|
||||
mixedcase A 10.0.0.30
|
||||
mixedCASE TXT "mixed case"
|
||||
MIXEDcase AAAA 2002::
|
||||
mIxEdCaSe LOC 37 52 56.788 N 121 54 55.02 W 1120m 10m 100m 10m
|
||||
|
||||
@@ -87,9 +87,7 @@ keyname=$("$KEYGEN" -q -a "$DEFAULT_ALGORITHM" -b "$DEFAULT_BITS" -n zone "$zone
|
||||
|
||||
cat "$infile" "$cnameandkey.key" "$dnameandkey.key" "$keyname.key" >"$zonefile"
|
||||
|
||||
"$SIGNER" -z -D -o "$zone" "$zonefile" >/dev/null
|
||||
cat "$zonefile" "$zonefile".signed >"$zonefile".tmp
|
||||
mv "$zonefile".tmp "$zonefile".signed
|
||||
"$SIGNER" -z -o "$zone" "$zonefile" >/dev/null
|
||||
|
||||
zone=bogus.example.
|
||||
infile=bogus.example.db.in
|
||||
|
||||
@@ -766,21 +766,6 @@ n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking mixed-case positive validation ($n)"
|
||||
ret=0
|
||||
for type in a txt aaaa loc; do
|
||||
dig_with_opts +noauth mixedcase.secure.example. \
|
||||
@10.53.0.3 $type >dig.out.$type.ns3.test$n || ret=1
|
||||
dig_with_opts +noauth mixedcase.secure.example. \
|
||||
@10.53.0.4 $type >dig.out.$type.ns4.test$n || ret=1
|
||||
digcomp --lc dig.out.$type.ns3.test$n dig.out.$type.ns4.test$n || ret=1
|
||||
grep "status: NOERROR" dig.out.$type.ns4.test$n >/dev/null || ret=1
|
||||
grep "flags:.*ad.*QUERY" dig.out.$type.ns4.test$n >/dev/null || ret=1
|
||||
done
|
||||
n=$((n + 1))
|
||||
test "$ret" -eq 0 || echo_i "failed"
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking multi-stage positive validation NSEC/NSEC3 ($n)"
|
||||
ret=0
|
||||
dig_with_opts +noauth a.nsec3.example. \
|
||||
@@ -2735,7 +2720,7 @@ rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example >/dev/null 2>&1
|
||||
rndccmd 10.53.0.3 status >/dev/null || ret=1
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
|
||||
[ "$salt" != "-" ] && [ "${#salt}" -eq 16 ] && break
|
||||
[ -n "$salt" ] && [ "$salt" != "-" ] && break
|
||||
echo_i "sleeping ...."
|
||||
sleep 1
|
||||
done
|
||||
@@ -2752,7 +2737,7 @@ rndccmd 10.53.0.3 signing -nsec3param 1 0 0 auto inline.example >/dev/null 2>&1
|
||||
rndccmd 10.53.0.3 status >/dev/null || ret=1
|
||||
for i in 1 2 3 4 5 6 7 8 9 10; do
|
||||
salt=$(dig_with_opts +nodnssec +short nsec3param inline.example. @10.53.0.3 | awk '{print $4}')
|
||||
[ "$salt" != "$oldsalt" ] && [ "${#salt}" -eq 16 ] && break
|
||||
[ -n "$salt" ] && [ "$salt" != "$oldsalt" ] && break
|
||||
echo_i "sleeping ...."
|
||||
sleep 1
|
||||
done
|
||||
|
||||
@@ -420,12 +420,12 @@ overmem(dns_db_t *db, bool over) {
|
||||
}
|
||||
|
||||
static void
|
||||
settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
settask(dns_db_t *db, isc_task_t *task) {
|
||||
sampledb_t *sampledb = (sampledb_t *)db;
|
||||
|
||||
REQUIRE(VALID_SAMPLEDB(sampledb));
|
||||
|
||||
dns_db_settask(sampledb->rbtdb, task, prunetask);
|
||||
dns_db_settask(sampledb->rbtdb, task);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
|
||||
@@ -22,14 +22,9 @@ my $pidf = new IO::File "ans.pid", "w" or die "cannot open pid file: $!";
|
||||
print $pidf "$$\n" or die "cannot write pid file: $!";
|
||||
$pidf->close or die "cannot close pid file: $!";
|
||||
sub rmpid { unlink "ans.pid"; exit 1; };
|
||||
sub term { };
|
||||
|
||||
$SIG{INT} = \&rmpid;
|
||||
if ($Net::DNS::VERSION >= 1.42) {
|
||||
$SIG{TERM} = \&term;
|
||||
} else {
|
||||
$SIG{TERM} = \&rmpid;
|
||||
}
|
||||
$SIG{TERM} = \&rmpid;
|
||||
|
||||
my $count = 0;
|
||||
|
||||
@@ -78,11 +73,4 @@ my $ns = Net::DNS::Nameserver->new(
|
||||
Verbose => $verbose,
|
||||
);
|
||||
|
||||
if ($Net::DNS::VERSION >= 1.42) {
|
||||
$ns->start_server();
|
||||
select(undef, undef, undef, undef);
|
||||
$ns->stop_server();
|
||||
unlink "ans.pid";
|
||||
} else {
|
||||
$ns->main_loop;
|
||||
}
|
||||
$ns->main_loop;
|
||||
|
||||
+2
-2
@@ -16,8 +16,8 @@
|
||||
#
|
||||
m4_define([bind_VERSION_MAJOR], 9)dnl
|
||||
m4_define([bind_VERSION_MINOR], 18)dnl
|
||||
m4_define([bind_VERSION_PATCH], 25)dnl
|
||||
m4_define([bind_VERSION_EXTRA], )dnl
|
||||
m4_define([bind_VERSION_PATCH], 22)dnl
|
||||
m4_define([bind_VERSION_EXTRA], -dev)dnl
|
||||
m4_define([bind_DESCRIPTION], [(Extended Support Version)])dnl
|
||||
m4_define([bind_SRCID], [m4_esyscmd_s([git rev-parse --short HEAD | cut -b1-7])])dnl
|
||||
m4_define([bind_PKG_VERSION], [[bind_VERSION_MAJOR.bind_VERSION_MINOR.bind_VERSION_PATCH]bind_VERSION_EXTRA])dnl
|
||||
|
||||
+4
-6
@@ -347,18 +347,18 @@ if changes_added_lines:
|
||||
# MR.
|
||||
|
||||
release_notes_regex = re.compile(r"doc/(arm|notes)/notes-.*\.(rst|xml)")
|
||||
release_notes_changed = list(filter(release_notes_regex.match, affected_files))
|
||||
release_notes_changed = list(filter(release_notes_regex.match, modified_files))
|
||||
release_notes_label_set = "Release Notes" in mr_labels
|
||||
if not release_notes_changed:
|
||||
if release_notes_label_set:
|
||||
fail(
|
||||
"This merge request has the *Release Notes* label set. "
|
||||
"Update release notes or unset the *Release Notes* label."
|
||||
"Add a release note or unset the *Release Notes* label."
|
||||
)
|
||||
elif "Customer" in mr_labels:
|
||||
warn(
|
||||
"This merge request has the *Customer* label set. "
|
||||
"Update release notes unless the changes introduced are trivial."
|
||||
"Add a release note unless the changes introduced are trivial."
|
||||
)
|
||||
if release_notes_changed and not release_notes_label_set:
|
||||
fail(
|
||||
@@ -367,9 +367,7 @@ if release_notes_changed and not release_notes_label_set:
|
||||
)
|
||||
|
||||
if release_notes_changed:
|
||||
modified_or_new_files = danger.git.modified_files + danger.git.created_files
|
||||
release_notes_added = list(filter(release_notes_regex.match, modified_or_new_files))
|
||||
notes_added_lines = added_lines(target_branch, release_notes_added)
|
||||
notes_added_lines = added_lines(target_branch, release_notes_changed)
|
||||
identifiers_found = filter(relnotes_issue_or_mr_id_regex.search, notes_added_lines)
|
||||
if notes_added_lines and not any(identifiers_found):
|
||||
warn("No valid issue/MR identifiers found in added release notes.")
|
||||
|
||||
+1
-4
@@ -35,10 +35,7 @@ information about each release, and source code.
|
||||
|
||||
.. include:: ../notes/notes-known-issues.rst
|
||||
|
||||
.. include:: ../notes/notes-9.18.25.rst
|
||||
.. include:: ../notes/notes-9.18.24.rst
|
||||
.. include:: ../notes/notes-9.18.23.rst
|
||||
.. include:: ../notes/notes-9.18.22.rst
|
||||
.. include:: ../notes/notes-current.rst
|
||||
.. include:: ../notes/notes-9.18.21.rst
|
||||
.. include:: ../notes/notes-9.18.20.rst
|
||||
.. include:: ../notes/notes-9.18.19.rst
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Make Read the Docs use the exact same package versions as in
|
||||
# registry.gitlab.isc.org/isc-projects/images/bind9:debian-bookworm-amd64
|
||||
Sphinx==7.2.6
|
||||
docutils==0.20.1
|
||||
sphinx_rtd_theme==2.0.0
|
||||
docutils==0.18.1
|
||||
sphinx_rtd_theme==1.3.0
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. 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.18.23
|
||||
----------------------
|
||||
|
||||
.. note::
|
||||
|
||||
The BIND 9.18.23 release was withdrawn after the discovery of a
|
||||
regression in a security fix in it during pre-release testing. ISC
|
||||
would like to acknowledge the assistance of Vinzenz Vogel and Daniel
|
||||
Stirnimann of SWITCH.
|
||||
@@ -1,65 +0,0 @@
|
||||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. 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.18.24
|
||||
----------------------
|
||||
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
- Validating DNS messages containing a lot of DNSSEC signatures could
|
||||
cause excessive CPU load, leading to a denial-of-service condition.
|
||||
This has been fixed. :cve:`2023-50387`
|
||||
|
||||
ISC would like to thank Elias Heftrig, Haya Schulmann, Niklas Vogel,
|
||||
and Michael Waidner from the German National Research Center for
|
||||
Applied Cybersecurity ATHENE for bringing this vulnerability to our
|
||||
attention. :gl:`#4424`
|
||||
|
||||
- Preparing an NSEC3 closest encloser proof could cause excessive CPU
|
||||
load, leading to a denial-of-service condition. This has been fixed.
|
||||
:cve:`2023-50868` :gl:`#4459`
|
||||
|
||||
- Parsing DNS messages with many different names could cause excessive
|
||||
CPU load. This has been fixed. :cve:`2023-4408`
|
||||
|
||||
ISC would like to thank Shoham Danino from Reichman University, Anat
|
||||
Bremler-Barr from Tel-Aviv University, Yehuda Afek from Tel-Aviv
|
||||
University, and Yuval Shavitt from Tel-Aviv University for bringing
|
||||
this vulnerability to our attention. :gl:`#4234`
|
||||
|
||||
- Specific queries could cause :iscman:`named` to crash with an
|
||||
assertion failure when :any:`nxdomain-redirect` was enabled. This has
|
||||
been fixed. :cve:`2023-5517` :gl:`#4281`
|
||||
|
||||
- A bad interaction between DNS64 and serve-stale could cause
|
||||
:iscman:`named` to crash with an assertion failure, when both of these
|
||||
features were enabled. This has been fixed. :cve:`2023-5679`
|
||||
:gl:`#4334`
|
||||
|
||||
- Under certain circumstances, the DNS-over-TLS client code incorrectly
|
||||
attempted to process more than one DNS message at a time, which could
|
||||
cause :iscman:`named` to crash with an assertion failure. This has
|
||||
been fixed. :gl:`#4487`
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- The counters exported via the statistics channel were changed back to
|
||||
64-bit signed values; they were being inadvertently truncated to
|
||||
unsigned 32-bit values since BIND 9.15.0. :gl:`#4467`
|
||||
|
||||
Known Issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- There are no new known issues with this release. See :ref:`above
|
||||
<relnotes_known_issues>` for a list of all known issues affecting this
|
||||
BIND 9 branch.
|
||||
@@ -1,44 +0,0 @@
|
||||
.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
||||
..
|
||||
.. SPDX-License-Identifier: MPL-2.0
|
||||
..
|
||||
.. 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.18.25
|
||||
----------------------
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- A regression in cache-cleaning code enabled memory use to grow
|
||||
significantly more quickly than before, until the configured
|
||||
:any:`max-cache-size` limit was reached. This has been fixed.
|
||||
:gl:`#4596`
|
||||
|
||||
- Using :option:`rndc flush` inadvertently caused cache cleaning to
|
||||
become less effective. This could ultimately lead to the configured
|
||||
:any:`max-cache-size` limit being exceeded and has now been fixed.
|
||||
:gl:`#4621`
|
||||
|
||||
- The logic for cleaning up expired cached DNS records was
|
||||
tweaked to be more aggressive. This change helps with enforcing
|
||||
:any:`max-cache-ttl` and :any:`max-ncache-ttl` in a timely manner.
|
||||
:gl:`#4591`
|
||||
|
||||
- It was possible to trigger a use-after-free assertion when the overmem cache
|
||||
cleaning was initiated. This has been fixed. :gl:`#4595`
|
||||
|
||||
ISC would like to thank Jinmei Tatuya of Infoblox for bringing
|
||||
this issue to our attention.
|
||||
|
||||
Known Issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- There are no new known issues with this release. See :ref:`above
|
||||
<relnotes_known_issues>` for a list of all known issues affecting this
|
||||
BIND 9 branch.
|
||||
@@ -12,8 +12,34 @@
|
||||
Notes for BIND 9.18.22
|
||||
----------------------
|
||||
|
||||
.. note::
|
||||
Security Fixes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
The BIND 9.18.22 release was withdrawn after the discovery of a
|
||||
regression in a security fix in it during pre-release testing. ISC
|
||||
would like to acknowledge the assistance of Curtis Tuplin of SaskTel.
|
||||
- None.
|
||||
|
||||
New Features
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Removed Features
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Feature Changes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Bug Fixes
|
||||
~~~~~~~~~
|
||||
|
||||
- None.
|
||||
|
||||
Known Issues
|
||||
~~~~~~~~~~~~
|
||||
|
||||
- There are no new known issues with this release. See :ref:`above
|
||||
<relnotes_known_issues>` for a list of all known issues affecting this
|
||||
BIND 9 branch.
|
||||
+16
-51
@@ -129,7 +129,6 @@ struct dns_cache {
|
||||
isc_mutex_t lock;
|
||||
isc_mem_t *mctx; /* Main cache memory */
|
||||
isc_mem_t *hmctx; /* Heap memory */
|
||||
isc_taskmgr_t *taskmgr;
|
||||
char *name;
|
||||
isc_refcount_t references;
|
||||
isc_refcount_t live_tasks;
|
||||
@@ -170,47 +169,13 @@ water(void *arg, int mark);
|
||||
static isc_result_t
|
||||
cache_create_db(dns_cache_t *cache, dns_db_t **db) {
|
||||
isc_result_t result;
|
||||
isc_task_t *dbtask = NULL;
|
||||
isc_task_t *prunetask = NULL;
|
||||
|
||||
result = dns_db_create(cache->mctx, cache->db_type, dns_rootname,
|
||||
dns_dbtype_cache, cache->rdclass, cache->db_argc,
|
||||
cache->db_argv, db);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_db_setservestalettl(*db, cache->serve_stale_ttl);
|
||||
dns_db_setservestalerefresh(*db, cache->serve_stale_refresh);
|
||||
}
|
||||
|
||||
dns_db_setservestalettl(*db, cache->serve_stale_ttl);
|
||||
dns_db_setservestalerefresh(*db, cache->serve_stale_refresh);
|
||||
|
||||
if (cache->taskmgr == NULL) {
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
result = isc_task_create(cache->taskmgr, 1, &dbtask);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_db;
|
||||
}
|
||||
isc_task_setname(dbtask, "cache_dbtask", NULL);
|
||||
|
||||
result = isc_task_create(cache->taskmgr, UINT_MAX, &prunetask);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_dbtask;
|
||||
}
|
||||
isc_task_setname(prunetask, "cache_prunetask", NULL);
|
||||
|
||||
dns_db_settask(*db, dbtask, prunetask);
|
||||
|
||||
isc_task_detach(&prunetask);
|
||||
isc_task_detach(&dbtask);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup_dbtask:
|
||||
isc_task_detach(&dbtask);
|
||||
cleanup_db:
|
||||
dns_db_detach(db);
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -222,12 +187,12 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
|
||||
isc_result_t result;
|
||||
dns_cache_t *cache;
|
||||
int i, extra = 0;
|
||||
isc_task_t *dbtask;
|
||||
|
||||
REQUIRE(cachep != NULL);
|
||||
REQUIRE(*cachep == NULL);
|
||||
REQUIRE(cmctx != NULL);
|
||||
REQUIRE(hmctx != NULL);
|
||||
REQUIRE(taskmgr != NULL || strcmp(db_type, "rbt") != 0);
|
||||
REQUIRE(cachename != NULL);
|
||||
|
||||
cache = isc_mem_get(cmctx, sizeof(*cache));
|
||||
@@ -236,11 +201,6 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
|
||||
isc_mem_attach(cmctx, &cache->mctx);
|
||||
isc_mem_attach(hmctx, &cache->hmctx);
|
||||
|
||||
cache->taskmgr = NULL;
|
||||
if (taskmgr != NULL) {
|
||||
isc_taskmgr_attach(taskmgr, &cache->taskmgr);
|
||||
}
|
||||
|
||||
cache->name = NULL;
|
||||
if (cachename != NULL) {
|
||||
cache->name = isc_mem_strdup(cmctx, cachename);
|
||||
@@ -297,6 +257,18 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_dbargv;
|
||||
}
|
||||
if (taskmgr != NULL) {
|
||||
dbtask = NULL;
|
||||
result = isc_task_create(taskmgr, 1, &dbtask);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup_db;
|
||||
}
|
||||
|
||||
isc_task_setname(dbtask, "cache_dbtask", NULL);
|
||||
dns_db_settask(cache->db, dbtask);
|
||||
isc_task_detach(&dbtask);
|
||||
}
|
||||
|
||||
cache->magic = CACHE_MAGIC;
|
||||
|
||||
/*
|
||||
@@ -340,9 +312,6 @@ cleanup_lock:
|
||||
if (cache->name != NULL) {
|
||||
isc_mem_free(cmctx, cache->name);
|
||||
}
|
||||
if (cache->taskmgr != NULL) {
|
||||
isc_taskmgr_detach(&cache->taskmgr);
|
||||
}
|
||||
isc_mem_detach(&cache->hmctx);
|
||||
isc_mem_putanddetach(&cache->mctx, cache, sizeof(*cache));
|
||||
return (result);
|
||||
@@ -409,10 +378,6 @@ cache_free(dns_cache_t *cache) {
|
||||
isc_stats_detach(&cache->stats);
|
||||
}
|
||||
|
||||
if (cache->taskmgr != NULL) {
|
||||
isc_taskmgr_detach(&cache->taskmgr);
|
||||
}
|
||||
|
||||
isc_mutex_destroy(&cache->lock);
|
||||
|
||||
cache->magic = 0;
|
||||
|
||||
+2
-2
@@ -829,10 +829,10 @@ dns_db_hashsize(dns_db_t *db) {
|
||||
}
|
||||
|
||||
void
|
||||
dns_db_settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
dns_db_settask(dns_db_t *db, isc_task_t *task) {
|
||||
REQUIRE(DNS_DB_VALID(db));
|
||||
|
||||
(db->methods->settask)(db, task, prunetask);
|
||||
(db->methods->settask)(db, task);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
|
||||
+8
-19
@@ -164,8 +164,7 @@ computeid(dst_key_t *key);
|
||||
static isc_result_t
|
||||
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
||||
unsigned int protocol, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
|
||||
dst_key_t **keyp);
|
||||
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
|
||||
|
||||
static isc_result_t
|
||||
algorithm_status(unsigned int alg);
|
||||
@@ -754,13 +753,6 @@ dst_key_todns(const dst_key_t *key, isc_buffer_t *target) {
|
||||
isc_result_t
|
||||
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
|
||||
return (dst_key_fromdns_ex(name, rdclass, source, mctx, false, keyp));
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
|
||||
dst_key_t **keyp) {
|
||||
uint8_t alg, proto;
|
||||
uint32_t flags, extflags;
|
||||
dst_key_t *key = NULL;
|
||||
@@ -791,7 +783,7 @@ dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
}
|
||||
|
||||
result = frombuffer(name, alg, flags, proto, rdclass, source, mctx,
|
||||
no_rdata, &key);
|
||||
&key);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
@@ -812,7 +804,7 @@ dst_key_frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
||||
REQUIRE(dst_initialized);
|
||||
|
||||
result = frombuffer(name, alg, flags, protocol, rdclass, source, mctx,
|
||||
false, &key);
|
||||
&key);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
return (result);
|
||||
}
|
||||
@@ -2359,8 +2351,7 @@ computeid(dst_key_t *key) {
|
||||
static isc_result_t
|
||||
frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
||||
unsigned int protocol, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
|
||||
dst_key_t **keyp) {
|
||||
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp) {
|
||||
dst_key_t *key;
|
||||
isc_result_t ret;
|
||||
|
||||
@@ -2385,12 +2376,10 @@ frombuffer(const dns_name_t *name, unsigned int alg, unsigned int flags,
|
||||
return (DST_R_UNSUPPORTEDALG);
|
||||
}
|
||||
|
||||
if (!no_rdata) {
|
||||
ret = key->func->fromdns(key, source);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
dst_key_free(&key);
|
||||
return (ret);
|
||||
}
|
||||
ret = key->func->fromdns(key, source);
|
||||
if (ret != ISC_R_SUCCESS) {
|
||||
dst_key_free(&key);
|
||||
return (ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,20 +61,25 @@ dns_cache_create(isc_mem_t *cmctx, isc_mem_t *hmctx, isc_taskmgr_t *taskmgr,
|
||||
const char *cachename, const char *db_type,
|
||||
unsigned int db_argc, char **db_argv, dns_cache_t **cachep);
|
||||
/*%<
|
||||
* Create a new named DNS cache using two separate memory contexts, one for
|
||||
* cache data which can be cleaned and a separate one for memory allocated for
|
||||
* the heap (which can grow without an upper limit and has no mechanism for
|
||||
* shrinking).
|
||||
* Create a new DNS cache.
|
||||
*
|
||||
* dns_cache_create2() will create a named cache.
|
||||
*
|
||||
* dns_cache_create3() will create a named cache using two separate memory
|
||||
* contexts, one for cache data which can be cleaned and a separate one for
|
||||
* memory allocated for the heap (which can grow without an upper limit and
|
||||
* has no mechanism for shrinking).
|
||||
*
|
||||
* dns_cache_create() is a backward compatible version that internally
|
||||
* specifies an empty cache name and a single memory context.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'cmctx' and 'hmctx' are valid memory contexts.
|
||||
*
|
||||
*\li 'taskmgr' is a valid task manager (if 'db_type' is "rbt").
|
||||
*\li 'cmctx' (and 'hmctx' if applicable) is a valid memory context.
|
||||
*
|
||||
*\li 'taskmgr' is a valid task manager and 'timermgr' is a valid timer
|
||||
* manager, or both are NULL (if 'db_type' is not "rbt"). If NULL, no
|
||||
* periodic cleaning of the cache will take place.
|
||||
* manager, or both are NULL. If NULL, no periodic cleaning of the
|
||||
* cache will take place.
|
||||
*
|
||||
*\li 'cachename' is a valid string. This must not be NULL.
|
||||
*
|
||||
|
||||
@@ -139,7 +139,7 @@ typedef struct dns_dbmethods {
|
||||
unsigned int (*nodecount)(dns_db_t *db, dns_dbtree_t);
|
||||
bool (*ispersistent)(dns_db_t *db);
|
||||
void (*overmem)(dns_db_t *db, bool overmem);
|
||||
void (*settask)(dns_db_t *db, isc_task_t *, isc_task_t *);
|
||||
void (*settask)(dns_db_t *db, isc_task_t *);
|
||||
isc_result_t (*getoriginnode)(dns_db_t *db, dns_dbnode_t **nodep);
|
||||
void (*transfernode)(dns_db_t *db, dns_dbnode_t **sourcep,
|
||||
dns_dbnode_t **targetp);
|
||||
@@ -1389,14 +1389,13 @@ dns_db_hashsize(dns_db_t *db);
|
||||
*/
|
||||
|
||||
void
|
||||
dns_db_settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask);
|
||||
dns_db_settask(dns_db_t *db, isc_task_t *task);
|
||||
/*%<
|
||||
* If task is set then the final detach maybe performed asynchronously.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'db' is a valid database.
|
||||
* \li 'task' to be valid or NULL (default task to send events to).
|
||||
* \li 'prunetask' to be valid or NULL (task to send tree-pruning events to).
|
||||
* \li 'task' to be valid or NULL.
|
||||
*/
|
||||
|
||||
bool
|
||||
|
||||
@@ -856,6 +856,44 @@ dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type,
|
||||
*\li #ISC_R_NOTFOUND -- the desired type does not exist.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t type, dns_rdatatype_t covers,
|
||||
dns_rdataset_t **rdataset);
|
||||
/*%<
|
||||
* Search the name for the specified rdclass and type. If it is found,
|
||||
* *rdataset is filled in with a pointer to that rdataset.
|
||||
*
|
||||
* Requires:
|
||||
*\li if '**rdataset' is non-NULL, *rdataset needs to be NULL.
|
||||
*
|
||||
*\li 'type' be a valid type, and NOT dns_rdatatype_any.
|
||||
*
|
||||
*\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type.
|
||||
* Otherwise it should be 0.
|
||||
*
|
||||
* Returns:
|
||||
*\li #ISC_R_SUCCESS -- all is well.
|
||||
*\li #ISC_R_NOTFOUND -- the desired type does not exist.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_message_movename(dns_message_t *msg, dns_name_t *name,
|
||||
dns_section_t fromsection, dns_section_t tosection);
|
||||
/*%<
|
||||
* Move a name from one section to another.
|
||||
*
|
||||
* Requires:
|
||||
*
|
||||
*\li 'msg' be valid.
|
||||
*
|
||||
*\li 'name' must be a name already in 'fromsection'.
|
||||
*
|
||||
*\li 'fromsection' must be a valid section.
|
||||
*
|
||||
*\li 'tosection' must be a valid section.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_message_addname(dns_message_t *msg, dns_name_t *name,
|
||||
dns_section_t section);
|
||||
|
||||
+20
-17
@@ -68,7 +68,6 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <isc/ht.h>
|
||||
#include <isc/lang.h>
|
||||
#include <isc/magic.h>
|
||||
#include <isc/region.h> /* Required for storage size of dns_label_t. */
|
||||
@@ -112,7 +111,6 @@ struct dns_name {
|
||||
isc_buffer_t *buffer;
|
||||
ISC_LINK(dns_name_t) link;
|
||||
ISC_LIST(dns_rdataset_t) list;
|
||||
isc_ht_t *ht;
|
||||
};
|
||||
|
||||
#define DNS_NAME_MAGIC ISC_MAGIC('D', 'N', 'S', 'n')
|
||||
@@ -168,24 +166,30 @@ extern const dns_name_t *dns_wildcardname;
|
||||
* unsigned char offsets[] = { 0, 6 };
|
||||
* dns_name_t value = DNS_NAME_INITABSOLUTE(data, offsets);
|
||||
*/
|
||||
#define DNS_NAME_INITNONABSOLUTE(A, B) \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \
|
||||
DNS_NAMEATTR_READONLY, B, NULL, \
|
||||
{ (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \
|
||||
#define DNS_NAME_INITNONABSOLUTE(A, B) \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, A, (sizeof(A) - 1), sizeof(B), \
|
||||
DNS_NAMEATTR_READONLY, B, NULL, \
|
||||
{ (void *)-1, (void *)-1 }, { \
|
||||
NULL, NULL \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DNS_NAME_INITABSOLUTE(A, B) \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \
|
||||
DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \
|
||||
NULL, { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \
|
||||
#define DNS_NAME_INITABSOLUTE(A, B) \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, A, sizeof(A), sizeof(B), \
|
||||
DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, B, \
|
||||
NULL, { (void *)-1, (void *)-1 }, { \
|
||||
NULL, NULL \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DNS_NAME_INITEMPTY \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \
|
||||
{ (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \
|
||||
#define DNS_NAME_INITEMPTY \
|
||||
{ \
|
||||
DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \
|
||||
{ (void *)-1, (void *)-1 }, { \
|
||||
NULL, NULL \
|
||||
} \
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1326,7 +1330,6 @@ ISC_LANG_ENDDECLS
|
||||
_n->buffer = NULL; \
|
||||
ISC_LINK_INIT(_n, link); \
|
||||
ISC_LIST_INIT(_n->list); \
|
||||
_n->ht = NULL; \
|
||||
} while (0)
|
||||
|
||||
#define DNS_NAME_RESET(n) \
|
||||
|
||||
@@ -148,7 +148,6 @@ struct dns_validator {
|
||||
unsigned int depth;
|
||||
unsigned int authcount;
|
||||
unsigned int authfail;
|
||||
bool failed;
|
||||
isc_stdtime_t start;
|
||||
};
|
||||
|
||||
|
||||
@@ -482,10 +482,6 @@ dst_key_tofile(const dst_key_t *key, int type, const char *directory);
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
dst_key_fromdns_ex(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, bool no_rdata,
|
||||
dst_key_t **keyp);
|
||||
isc_result_t
|
||||
dst_key_fromdns(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
isc_buffer_t *source, isc_mem_t *mctx, dst_key_t **keyp);
|
||||
/*%<
|
||||
|
||||
+133
-239
@@ -22,8 +22,6 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <isc/buffer.h>
|
||||
#include <isc/hash.h>
|
||||
#include <isc/ht.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/print.h>
|
||||
#include <isc/result.h>
|
||||
@@ -495,11 +493,9 @@ msgresetsigs(dns_message_t *msg, bool replying) {
|
||||
} else {
|
||||
dns_rdataset_disassociate(msg->tsig);
|
||||
isc_mempool_put(msg->rdspool, msg->tsig);
|
||||
msg->tsig = NULL;
|
||||
if (msg->querytsig != NULL) {
|
||||
dns_rdataset_disassociate(msg->querytsig);
|
||||
isc_mempool_put(msg->rdspool, msg->querytsig);
|
||||
msg->querytsig = NULL;
|
||||
}
|
||||
}
|
||||
dns_message_puttempname(msg, &msg->tsigname);
|
||||
@@ -794,18 +790,6 @@ dns_message_detach(dns_message_t **messagep) {
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
name_hash_add(isc_ht_t *ht, dns_name_t *name, dns_name_t **foundp) {
|
||||
isc_result_t result = isc_ht_find(ht, name->ndata, name->length,
|
||||
(void **)foundp);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return (ISC_R_EXISTS);
|
||||
}
|
||||
result = isc_ht_add(ht, name->ndata, name->length, (void *)name);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
findname(dns_name_t **foundname, const dns_name_t *target,
|
||||
dns_namelist_t *section) {
|
||||
@@ -825,26 +809,29 @@ findname(dns_name_t **foundname, const dns_name_t *target,
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
typedef struct __attribute__((__packed__)) rds_key {
|
||||
dns_rdataclass_t rdclass;
|
||||
dns_rdatatype_t type;
|
||||
dns_rdatatype_t covers;
|
||||
} rds_key_t;
|
||||
isc_result_t
|
||||
dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t type, dns_rdatatype_t covers,
|
||||
dns_rdataset_t **rdataset) {
|
||||
dns_rdataset_t *curr;
|
||||
|
||||
static isc_result_t
|
||||
rds_hash_add(isc_ht_t *ht, dns_rdataset_t *rds, dns_rdataset_t **foundp) {
|
||||
rds_key_t key = { .rdclass = rds->rdclass,
|
||||
.type = rds->type,
|
||||
.covers = rds->covers };
|
||||
isc_result_t result = isc_ht_find(ht, (const unsigned char *)&key,
|
||||
sizeof(key), (void **)foundp);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
return (ISC_R_EXISTS);
|
||||
REQUIRE(name != NULL);
|
||||
REQUIRE(rdataset == NULL || *rdataset == NULL);
|
||||
|
||||
for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
|
||||
curr = ISC_LIST_PREV(curr, link))
|
||||
{
|
||||
if (curr->rdclass == rdclass && curr->type == type &&
|
||||
curr->covers == covers)
|
||||
{
|
||||
if (rdataset != NULL) {
|
||||
*rdataset = curr;
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
}
|
||||
result = isc_ht_add(ht, (const unsigned char *)&key, sizeof(key),
|
||||
(void *)rds);
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@@ -971,18 +958,6 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void
|
||||
cleanup_name_hashmaps(dns_namelist_t *section) {
|
||||
dns_name_t *name = NULL;
|
||||
for (name = ISC_LIST_HEAD(*section); name != NULL;
|
||||
name = ISC_LIST_NEXT(name, link))
|
||||
{
|
||||
if (name->ht != NULL) {
|
||||
isc_ht_destroy(&name->ht);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
unsigned int options) {
|
||||
@@ -992,19 +967,13 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
dns_name_t *name2 = NULL;
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
dns_rdatalist_t *rdatalist = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_result_t result;
|
||||
dns_rdatatype_t rdtype;
|
||||
dns_rdataclass_t rdclass;
|
||||
dns_namelist_t *section = &msg->sections[DNS_SECTION_QUESTION];
|
||||
bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0);
|
||||
bool seen_problem = false;
|
||||
bool free_name = false;
|
||||
bool free_ht = false;
|
||||
isc_ht_t *name_map = NULL;
|
||||
|
||||
if (msg->counts[DNS_SECTION_QUESTION] > 1) {
|
||||
isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) {
|
||||
name = NULL;
|
||||
@@ -1025,19 +994,13 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* If there is only one QNAME, skip the duplicity checks */
|
||||
if (name_map == NULL) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto skip_name_check;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the section, looking to see if this name
|
||||
* is already there. If it is found, put back the allocated
|
||||
* name since we no longer need it, and set our name pointer
|
||||
* to point to the name we found.
|
||||
*/
|
||||
result = name_hash_add(name_map, name, &name2);
|
||||
result = findname(&name2, name, section);
|
||||
|
||||
/*
|
||||
* If it is the first name in the section, accept it.
|
||||
@@ -1049,25 +1012,19 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
* this should be legal or not. In either case we no longer
|
||||
* need this name pointer.
|
||||
*/
|
||||
skip_name_check:
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
if (!ISC_LIST_EMPTY(*section)) {
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
break;
|
||||
case ISC_R_EXISTS:
|
||||
free_name = false;
|
||||
} else {
|
||||
dns_message_puttempname(msg, &name);
|
||||
name = name2;
|
||||
name2 = NULL;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
free_name = false;
|
||||
}
|
||||
|
||||
free_name = false;
|
||||
|
||||
/*
|
||||
* Get type and class.
|
||||
*/
|
||||
@@ -1097,6 +1054,14 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
msg->tkey = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't ask the same question twice.
|
||||
*/
|
||||
result = dns_message_find(name, rdclass, rdtype, 0, NULL);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new rdatalist.
|
||||
*/
|
||||
@@ -1106,7 +1071,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
goto cleanup;
|
||||
}
|
||||
rdataset = isc_mempool_get(msg->rdspool);
|
||||
dns_rdataset_init(rdataset);
|
||||
|
||||
/*
|
||||
* Convert rdatalist to rdataset, and attach the latter to
|
||||
@@ -1114,6 +1078,8 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
*/
|
||||
rdatalist->type = rdtype;
|
||||
rdatalist->rdclass = rdclass;
|
||||
|
||||
dns_rdataset_init(rdataset);
|
||||
result = dns_rdatalist_tordataset(rdatalist, rdataset);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto cleanup;
|
||||
@@ -1121,66 +1087,24 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
|
||||
rdataset->attributes |= DNS_RDATASETATTR_QUESTION;
|
||||
|
||||
/*
|
||||
* Skip the duplicity check for first rdataset
|
||||
*/
|
||||
if (ISC_LIST_EMPTY(name->list)) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto skip_rds_check;
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't ask the same question twice.
|
||||
*/
|
||||
if (name->ht == NULL) {
|
||||
isc_ht_init(&name->ht, msg->mctx, 1,
|
||||
ISC_HT_CASE_SENSITIVE);
|
||||
free_ht = true;
|
||||
|
||||
INSIST(ISC_LIST_HEAD(name->list) ==
|
||||
ISC_LIST_TAIL(name->list));
|
||||
|
||||
dns_rdataset_t *old_rdataset =
|
||||
ISC_LIST_HEAD(name->list);
|
||||
|
||||
result = rds_hash_add(name->ht, old_rdataset, NULL);
|
||||
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
}
|
||||
result = rds_hash_add(name->ht, rdataset, NULL);
|
||||
if (result == ISC_R_EXISTS) {
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
skip_rds_check:
|
||||
ISC_LIST_APPEND(name->list, rdataset, link);
|
||||
|
||||
rdataset = NULL;
|
||||
}
|
||||
|
||||
if (seen_problem) {
|
||||
result = DNS_R_RECOVERABLE;
|
||||
return (DNS_R_RECOVERABLE);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
if (rdataset != NULL) {
|
||||
if (dns_rdataset_isassociated(rdataset)) {
|
||||
dns_rdataset_disassociate(rdataset);
|
||||
}
|
||||
INSIST(!dns_rdataset_isassociated(rdataset));
|
||||
isc_mempool_put(msg->rdspool, rdataset);
|
||||
}
|
||||
if (free_name) {
|
||||
dns_message_puttempname(msg, &name);
|
||||
}
|
||||
|
||||
if (free_ht) {
|
||||
cleanup_name_hashmaps(section);
|
||||
}
|
||||
|
||||
if (name_map != NULL) {
|
||||
isc_ht_destroy(&name_map);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -1260,24 +1184,17 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
dns_name_t *name = NULL;
|
||||
dns_name_t *name2 = NULL;
|
||||
dns_rdataset_t *rdataset = NULL;
|
||||
dns_rdataset_t *found_rdataset = NULL;
|
||||
dns_rdatalist_t *rdatalist = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_result_t result;
|
||||
dns_rdatatype_t rdtype, covers;
|
||||
dns_rdataclass_t rdclass;
|
||||
dns_rdata_t *rdata = NULL;
|
||||
dns_ttl_t ttl;
|
||||
dns_namelist_t *section = &msg->sections[sectionid];
|
||||
bool free_name = false, seen_problem = false;
|
||||
bool free_ht = false;
|
||||
bool free_name = false, free_rdataset = false, seen_problem = false;
|
||||
bool preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0);
|
||||
bool best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0);
|
||||
bool isedns, issigzero, istsig;
|
||||
isc_ht_t *name_map = NULL;
|
||||
|
||||
if (msg->counts[sectionid] > 1) {
|
||||
isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
for (count = 0; count < msg->counts[sectionid]; count++) {
|
||||
int recstart = source->current;
|
||||
@@ -1285,10 +1202,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
|
||||
skip_name_search = false;
|
||||
skip_type_search = false;
|
||||
free_rdataset = false;
|
||||
isedns = false;
|
||||
issigzero = false;
|
||||
istsig = false;
|
||||
found_rdataset = NULL;
|
||||
|
||||
name = NULL;
|
||||
result = dns_message_gettempname(msg, &name);
|
||||
@@ -1328,8 +1245,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
if (msg->rdclass_set == 0 &&
|
||||
rdtype != dns_rdatatype_opt && /* class is UDP SIZE */
|
||||
rdtype != dns_rdatatype_tsig && /* class is ANY */
|
||||
rdtype != dns_rdatatype_tkey) /* class is undefined */
|
||||
{
|
||||
rdtype != dns_rdatatype_tkey)
|
||||
{ /* class is undefined */
|
||||
msg->rdclass = rdclass;
|
||||
msg->rdclass_set = 1;
|
||||
}
|
||||
@@ -1436,6 +1353,10 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
* Then put the meta-class back into the finished rdata.
|
||||
*/
|
||||
rdata = newrdata(msg);
|
||||
if (rdata == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
if (msg->opcode == dns_opcode_update &&
|
||||
update(sectionid, rdclass))
|
||||
{
|
||||
@@ -1524,62 +1445,34 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
free_name = false;
|
||||
}
|
||||
} else {
|
||||
if (name_map == NULL) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto skip_name_check;
|
||||
}
|
||||
|
||||
/*
|
||||
* Run through the section, looking to see if this name
|
||||
* is already there. If it is found, put back the
|
||||
* allocated name since we no longer need it, and set
|
||||
* our name pointer to point to the name we found.
|
||||
*/
|
||||
result = name_hash_add(name_map, name, &name2);
|
||||
result = findname(&name2, name, section);
|
||||
|
||||
/*
|
||||
* If it is a new name, append to the section.
|
||||
*/
|
||||
skip_name_check:
|
||||
switch (result) {
|
||||
case ISC_R_SUCCESS:
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
break;
|
||||
case ISC_R_EXISTS:
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_message_puttempname(msg, &name);
|
||||
name = name2;
|
||||
name2 = NULL;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
} else {
|
||||
ISC_LIST_APPEND(*section, name, link);
|
||||
}
|
||||
free_name = false;
|
||||
}
|
||||
|
||||
rdatalist = newrdatalist(msg);
|
||||
rdatalist->type = rdtype;
|
||||
rdatalist->covers = covers;
|
||||
rdatalist->rdclass = rdclass;
|
||||
rdatalist->ttl = ttl;
|
||||
|
||||
dns_message_gettemprdataset(msg, &rdataset);
|
||||
RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
|
||||
ISC_R_SUCCESS);
|
||||
dns_rdataset_setownercase(rdataset, name);
|
||||
rdatalist = NULL;
|
||||
|
||||
/*
|
||||
* Search name for the particular type and class.
|
||||
* Skip this stage if in update mode or this is a meta-type.
|
||||
*/
|
||||
if (isedns || istsig || issigzero) {
|
||||
/* Skip adding the rdataset to the tables */
|
||||
} else if (preserve_order || msg->opcode == dns_opcode_update ||
|
||||
skip_type_search)
|
||||
if (preserve_order || msg->opcode == dns_opcode_update ||
|
||||
skip_type_search)
|
||||
{
|
||||
result = ISC_R_SUCCESS;
|
||||
|
||||
ISC_LIST_APPEND(name->list, rdataset, link);
|
||||
result = ISC_R_NOTFOUND;
|
||||
} else {
|
||||
/*
|
||||
* If this is a type that can only occur in
|
||||
@@ -1589,71 +1482,59 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
|
||||
if (ISC_LIST_EMPTY(name->list)) {
|
||||
result = ISC_R_SUCCESS;
|
||||
goto skip_rds_check;
|
||||
}
|
||||
|
||||
if (name->ht == NULL) {
|
||||
isc_ht_init(&name->ht, msg->mctx, 1,
|
||||
ISC_HT_CASE_SENSITIVE);
|
||||
free_ht = true;
|
||||
|
||||
INSIST(ISC_LIST_HEAD(name->list) ==
|
||||
ISC_LIST_TAIL(name->list));
|
||||
|
||||
dns_rdataset_t *old_rdataset =
|
||||
ISC_LIST_HEAD(name->list);
|
||||
|
||||
result = rds_hash_add(name->ht, old_rdataset,
|
||||
NULL);
|
||||
|
||||
INSIST(result == ISC_R_SUCCESS);
|
||||
}
|
||||
found_rdataset = NULL;
|
||||
result = rds_hash_add(name->ht, rdataset,
|
||||
&found_rdataset);
|
||||
|
||||
/*
|
||||
* If we found an rdataset that matches, we need to
|
||||
* append this rdata to that set. If we did not, we
|
||||
* need to create a new rdatalist, store the important
|
||||
* bits there, convert it to an rdataset, and link the
|
||||
* latter to the name. Yuck. When appending, make
|
||||
* certain that the type isn't a singleton type, such as
|
||||
* SOA or CNAME.
|
||||
*
|
||||
* Note that this check will be bypassed when preserving
|
||||
* order, the opcode is an update, or the type search is
|
||||
* skipped.
|
||||
*/
|
||||
skip_rds_check:
|
||||
switch (result) {
|
||||
case ISC_R_EXISTS:
|
||||
/* Free the rdataset we used as the key */
|
||||
dns_rdataset_disassociate(rdataset);
|
||||
isc_mempool_put(msg->rdspool, rdataset);
|
||||
result = ISC_R_SUCCESS;
|
||||
rdataset = found_rdataset;
|
||||
|
||||
if (!dns_rdatatype_issingleton(rdtype)) {
|
||||
break;
|
||||
}
|
||||
rdataset = NULL;
|
||||
result = dns_message_find(name, rdclass, rdtype, covers,
|
||||
&rdataset);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found an rdataset that matches, we need to
|
||||
* append this rdata to that set. If we did not, we need
|
||||
* to create a new rdatalist, store the important bits there,
|
||||
* convert it to an rdataset, and link the latter to the name.
|
||||
* Yuck. When appending, make certain that the type isn't
|
||||
* a singleton type, such as SOA or CNAME.
|
||||
*
|
||||
* Note that this check will be bypassed when preserving order,
|
||||
* the opcode is an update, or the type search is skipped.
|
||||
*/
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (dns_rdatatype_issingleton(rdtype)) {
|
||||
dns_rdata_t *first;
|
||||
dns_rdatalist_fromrdataset(rdataset,
|
||||
&rdatalist);
|
||||
dns_rdata_t *first =
|
||||
ISC_LIST_HEAD(rdatalist->rdata);
|
||||
first = ISC_LIST_HEAD(rdatalist->rdata);
|
||||
INSIST(first != NULL);
|
||||
if (dns_rdata_compare(rdata, first) != 0) {
|
||||
DO_ERROR(DNS_R_FORMERR);
|
||||
}
|
||||
break;
|
||||
case ISC_R_SUCCESS:
|
||||
}
|
||||
}
|
||||
|
||||
if (result == ISC_R_NOTFOUND) {
|
||||
rdataset = isc_mempool_get(msg->rdspool);
|
||||
free_rdataset = true;
|
||||
|
||||
rdatalist = newrdatalist(msg);
|
||||
if (rdatalist == NULL) {
|
||||
result = ISC_R_NOMEMORY;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rdatalist->type = rdtype;
|
||||
rdatalist->covers = covers;
|
||||
rdatalist->rdclass = rdclass;
|
||||
rdatalist->ttl = ttl;
|
||||
|
||||
dns_rdataset_init(rdataset);
|
||||
RUNTIME_CHECK(
|
||||
dns_rdatalist_tordataset(rdatalist, rdataset) ==
|
||||
ISC_R_SUCCESS);
|
||||
dns_rdataset_setownercase(rdataset, name);
|
||||
|
||||
if (!isedns && !istsig && !issigzero) {
|
||||
ISC_LIST_APPEND(name->list, rdataset, link);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
free_rdataset = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1688,6 +1569,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
dns_rcode_t ercode;
|
||||
|
||||
msg->opt = rdataset;
|
||||
rdataset = NULL;
|
||||
free_rdataset = false;
|
||||
ercode = (dns_rcode_t)((msg->opt->ttl &
|
||||
DNS_MESSAGE_EDNSRCODE_MASK) >>
|
||||
20);
|
||||
@@ -1698,6 +1581,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
msg->sig0 = rdataset;
|
||||
msg->sig0name = name;
|
||||
msg->sigstart = recstart;
|
||||
rdataset = NULL;
|
||||
free_rdataset = false;
|
||||
free_name = false;
|
||||
} else if (istsig) {
|
||||
msg->tsig = rdataset;
|
||||
@@ -1707,17 +1592,22 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
* Windows doesn't like TSIG names to be compressed.
|
||||
*/
|
||||
msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS;
|
||||
rdataset = NULL;
|
||||
free_rdataset = false;
|
||||
free_name = false;
|
||||
}
|
||||
rdataset = NULL;
|
||||
|
||||
if (seen_problem) {
|
||||
if (free_name) {
|
||||
dns_message_puttempname(msg, &name);
|
||||
}
|
||||
free_name = false;
|
||||
if (free_rdataset) {
|
||||
isc_mempool_put(msg->rdspool, rdataset);
|
||||
}
|
||||
free_name = free_rdataset = false;
|
||||
}
|
||||
INSIST(!free_name);
|
||||
INSIST(!free_rdataset);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1735,24 +1625,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx,
|
||||
}
|
||||
|
||||
if (seen_problem) {
|
||||
result = DNS_R_RECOVERABLE;
|
||||
return (DNS_R_RECOVERABLE);
|
||||
}
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
cleanup:
|
||||
if (rdataset != NULL && rdataset != found_rdataset) {
|
||||
dns_rdataset_disassociate(rdataset);
|
||||
isc_mempool_put(msg->rdspool, rdataset);
|
||||
}
|
||||
if (free_name) {
|
||||
dns_message_puttempname(msg, &name);
|
||||
}
|
||||
|
||||
if (free_ht) {
|
||||
cleanup_name_hashmaps(section);
|
||||
}
|
||||
|
||||
if (name_map != NULL) {
|
||||
isc_ht_destroy(&name_map);
|
||||
if (free_rdataset) {
|
||||
isc_mempool_put(msg->rdspool, rdataset);
|
||||
}
|
||||
|
||||
return (result);
|
||||
@@ -2570,7 +2452,7 @@ dns_message_findname(dns_message_t *msg, dns_section_t section,
|
||||
const dns_name_t *target, dns_rdatatype_t type,
|
||||
dns_rdatatype_t covers, dns_name_t **name,
|
||||
dns_rdataset_t **rdataset) {
|
||||
dns_name_t *foundname = NULL;
|
||||
dns_name_t *foundname;
|
||||
isc_result_t result;
|
||||
|
||||
/*
|
||||
@@ -2617,6 +2499,22 @@ dns_message_findname(dns_message_t *msg, dns_section_t section,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dns_message_movename(dns_message_t *msg, dns_name_t *name,
|
||||
dns_section_t fromsection, dns_section_t tosection) {
|
||||
REQUIRE(msg != NULL);
|
||||
REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER);
|
||||
REQUIRE(name != NULL);
|
||||
REQUIRE(VALID_NAMED_SECTION(fromsection));
|
||||
REQUIRE(VALID_NAMED_SECTION(tosection));
|
||||
|
||||
/*
|
||||
* Unlink the name from the old section
|
||||
*/
|
||||
ISC_LIST_UNLINK(msg->sections[fromsection], name, link);
|
||||
ISC_LIST_APPEND(msg->sections[tosection], name, link);
|
||||
}
|
||||
|
||||
void
|
||||
dns_message_addname(dns_message_t *msg, dns_name_t *name,
|
||||
dns_section_t section) {
|
||||
@@ -2693,10 +2591,6 @@ dns_message_puttempname(dns_message_t *msg, dns_name_t **itemp) {
|
||||
REQUIRE(!ISC_LINK_LINKED(item, link));
|
||||
REQUIRE(ISC_LIST_HEAD(item->list) == NULL);
|
||||
|
||||
if (item->ht != NULL) {
|
||||
isc_ht_destroy(&item->ht);
|
||||
}
|
||||
|
||||
/*
|
||||
* we need to check this in case dns_name_dup() was used.
|
||||
*/
|
||||
|
||||
@@ -188,7 +188,6 @@ dns_name_invalidate(dns_name_t *name) {
|
||||
name->offsets = NULL;
|
||||
name->buffer = NULL;
|
||||
ISC_LINK_INIT(name, link);
|
||||
INSIST(name->ht == NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
@@ -1138,6 +1138,12 @@ dns_nsec3param_deletechains(dns_db_t *db, dns_dbversion_t *ver,
|
||||
dns_rdata_t private = DNS_RDATA_INIT;
|
||||
|
||||
dns_rdataset_current(&rdataset, &rdata);
|
||||
|
||||
CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL, origin,
|
||||
rdataset.ttl, &rdata, &tuple));
|
||||
CHECK(do_one_tuple(&tuple, db, ver, diff));
|
||||
INSIST(tuple == NULL);
|
||||
|
||||
dns_nsec3param_toprivate(&rdata, &private, privatetype, buf,
|
||||
sizeof(buf));
|
||||
buf[2] = DNS_NSEC3FLAG_REMOVE;
|
||||
|
||||
+64
-132
@@ -351,14 +351,6 @@ hash_32(uint32_t val, unsigned int bits) {
|
||||
#define DEFAULT_CACHE_NODE_LOCK_COUNT 17
|
||||
#endif /* DNS_RBTDB_CACHE_NODE_LOCK_COUNT */
|
||||
|
||||
/*
|
||||
* This defines the number of headers that we try to expire each time the
|
||||
* expire_ttl_headers() is run. The number should be small enough, so the
|
||||
* TTL-based header expiration doesn't take too long, but it should be large
|
||||
* enough, so we expire enough headers if their TTL is clustered.
|
||||
*/
|
||||
#define DNS_RBTDB_EXPIRE_TTL_COUNT 10
|
||||
|
||||
typedef struct {
|
||||
nodelock_t lock;
|
||||
/* Protected in the refcount routines. */
|
||||
@@ -462,7 +454,6 @@ struct dns_rbtdb {
|
||||
rbtdb_version_t *future_version;
|
||||
rbtdb_versionlist_t open_versions;
|
||||
isc_task_t *task;
|
||||
isc_task_t *prunetask;
|
||||
dns_dbnode_t *soanode;
|
||||
dns_dbnode_t *nsnode;
|
||||
|
||||
@@ -913,10 +904,6 @@ set_ttl(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, dns_ttl_t newttl) {
|
||||
} else {
|
||||
isc_heap_decreased(heap, header->heap_index);
|
||||
}
|
||||
|
||||
if (newttl == 0) {
|
||||
isc_heap_delete(heap, header->heap_index);
|
||||
}
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1164,9 +1151,6 @@ free_rbtdb(dns_rbtdb_t *rbtdb, bool log, isc_event_t *event) {
|
||||
if (rbtdb->task != NULL) {
|
||||
isc_task_detach(&rbtdb->task);
|
||||
}
|
||||
if (rbtdb->prunetask != NULL) {
|
||||
isc_task_detach(&rbtdb->prunetask);
|
||||
}
|
||||
|
||||
RBTDB_DESTROYLOCK(&rbtdb->lock);
|
||||
rbtdb->common.magic = 0;
|
||||
@@ -1836,9 +1820,8 @@ delete_node(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node) {
|
||||
*/
|
||||
static void
|
||||
new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t nlocktype) {
|
||||
if (nlocktype == isc_rwlocktype_write &&
|
||||
ISC_LINK_LINKED(node, deadlink))
|
||||
isc_rwlocktype_t locktype) {
|
||||
if (locktype == isc_rwlocktype_write && ISC_LINK_LINKED(node, deadlink))
|
||||
{
|
||||
ISC_LIST_UNLINK(rbtdb->deadnodes[node->locknum], node,
|
||||
deadlink);
|
||||
@@ -1854,24 +1837,24 @@ new_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
* The tree lock must be held for the result to be valid.
|
||||
*/
|
||||
static bool
|
||||
is_last_node_on_its_level(dns_rbtnode_t *node) {
|
||||
is_leaf(dns_rbtnode_t *node) {
|
||||
return (node->parent != NULL && node->parent->down == node &&
|
||||
node->left == NULL && node->right == NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
send_to_prune_tree(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
isc_rwlocktype_t nlocktype) {
|
||||
isc_rwlocktype_t locktype) {
|
||||
isc_event_t *ev;
|
||||
dns_db_t *db;
|
||||
|
||||
ev = isc_event_allocate(rbtdb->common.mctx, NULL, DNS_EVENT_RBTPRUNE,
|
||||
prune_tree, node, sizeof(isc_event_t));
|
||||
new_reference(rbtdb, node, nlocktype);
|
||||
new_reference(rbtdb, node, locktype);
|
||||
db = NULL;
|
||||
attach((dns_db_t *)rbtdb, &db);
|
||||
ev->ev_sender = db;
|
||||
isc_task_send(rbtdb->prunetask, &ev);
|
||||
isc_task_send(rbtdb->task, &ev);
|
||||
}
|
||||
|
||||
/*%
|
||||
@@ -1904,7 +1887,7 @@ cleanup_dead_nodes(dns_rbtdb_t *rbtdb, int bucketnum) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_last_node_on_its_level(node) && rbtdb->task != NULL) {
|
||||
if (is_leaf(node) && rbtdb->task != NULL) {
|
||||
send_to_prune_tree(rbtdb, node, isc_rwlocktype_write);
|
||||
} else if (node->down == NULL && node->data == NULL) {
|
||||
/*
|
||||
@@ -2088,31 +2071,29 @@ decrement_reference(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,
|
||||
|
||||
if (write_locked) {
|
||||
/*
|
||||
* If this node is the only one left on its RBTDB level,
|
||||
* attempt pruning the RBTDB (i.e. deleting empty nodes that
|
||||
* are ancestors of 'node' and are not interior nodes) starting
|
||||
* from this node (see prune_tree()). The main reason this is
|
||||
* not done immediately, but asynchronously, is that the
|
||||
* ancestors of 'node' are almost guaranteed to belong to
|
||||
* different node buckets and we don't want to do juggle locks
|
||||
* right now.
|
||||
*
|
||||
* Since prune_tree() also calls decrement_reference(), check
|
||||
* the value of the 'pruning' parameter (which is only set to
|
||||
* 'true' in the decrement_reference() call present in
|
||||
* prune_tree()) to prevent an infinite loop and to allow a
|
||||
* node sent to prune_tree() to be deleted by the delete_node()
|
||||
* call in the code branch below.
|
||||
* We can now delete the node.
|
||||
*/
|
||||
if (!pruning && is_last_node_on_its_level(node) &&
|
||||
rbtdb->task != NULL)
|
||||
{
|
||||
|
||||
/*
|
||||
* If this node is the only one in the level it's in, deleting
|
||||
* this node may recursively make its parent the only node in
|
||||
* the parent level; if so, and if no one is currently using
|
||||
* the parent node, this is almost the only opportunity to
|
||||
* clean it up. But the recursive cleanup is not that trivial
|
||||
* since the child and parent may be in different lock buckets,
|
||||
* which would cause a lock order reversal problem. To avoid
|
||||
* the trouble, we'll dispatch a separate event for batch
|
||||
* cleaning. We need to check whether we're deleting the node
|
||||
* as a result of pruning to avoid infinite dispatching.
|
||||
* Note: pruning happens only when a task has been set for the
|
||||
* rbtdb. If the user of the rbtdb chooses not to set a task,
|
||||
* it's their responsibility to purge stale leaves (e.g. by
|
||||
* periodic walk-through).
|
||||
*/
|
||||
if (!pruning && is_leaf(node) && rbtdb->task != NULL) {
|
||||
send_to_prune_tree(rbtdb, node, isc_rwlocktype_write);
|
||||
no_reference = false;
|
||||
} else {
|
||||
/*
|
||||
* The node can now be deleted.
|
||||
*/
|
||||
delete_node(rbtdb, node);
|
||||
}
|
||||
} else {
|
||||
@@ -2148,57 +2129,37 @@ restore_locks:
|
||||
}
|
||||
|
||||
/*
|
||||
* Prune the RBTDB tree of trees. Start by attempting to delete a node that is
|
||||
* the only one left on its RBTDB level (see the send_to_prune_tree() call in
|
||||
* decrement_reference()). Then, if the node has a parent (which can either
|
||||
* exist on the same RBTDB level or on an upper RBTDB level), check whether the
|
||||
* latter is an interior node (i.e. a node with a non-NULL 'down' pointer). If
|
||||
* the parent node is not an interior node, attempt deleting the parent node as
|
||||
* well and then move on to examining the parent node's parent, etc. Continue
|
||||
* traversing the RBTDB tree until a node is encountered that is still an
|
||||
* interior node after the previously-processed node gets deleted.
|
||||
*
|
||||
* It is acceptable for a node sent to this function to NOT be deleted in the
|
||||
* process (e.g. if it gets reactivated in the meantime). Furthermore, node
|
||||
* deletion is not a prerequisite for continuing RBTDB traversal.
|
||||
*
|
||||
* This function gets called once for every "starting node" and it continues
|
||||
* traversing the RBTDB until the stop condition is met. In the worst case,
|
||||
* the number of nodes processed by a single execution of this function is the
|
||||
* number of tree levels, which is at most the maximum number of domain name
|
||||
* labels (127); however, it should be much smaller in practice and deleting
|
||||
* empty RBTDB nodes is critical to keeping the amount of memory used by the
|
||||
* cache memory context within the configured limit anyway.
|
||||
* Prune the tree by recursively cleaning-up single leaves. In the worst
|
||||
* case, the number of iteration is the number of tree levels, which is at
|
||||
* most the maximum number of domain name labels, i.e, 127. In practice, this
|
||||
* should be much smaller (only a few times), and even the worst case would be
|
||||
* acceptable for a single event.
|
||||
*/
|
||||
static void
|
||||
prune_tree(isc_task_t *task, isc_event_t *event) {
|
||||
dns_rbtdb_t *rbtdb = event->ev_sender;
|
||||
dns_rbtnode_t *node = event->ev_arg;
|
||||
dns_rbtnode_t *parent = NULL;
|
||||
unsigned int locknum = node->locknum;
|
||||
dns_rbtnode_t *parent;
|
||||
unsigned int locknum;
|
||||
|
||||
UNUSED(task);
|
||||
|
||||
isc_event_free(&event);
|
||||
|
||||
RWLOCK(&rbtdb->tree_lock, isc_rwlocktype_write);
|
||||
locknum = node->locknum;
|
||||
NODE_LOCK(&rbtdb->node_locks[locknum].lock, isc_rwlocktype_write);
|
||||
do {
|
||||
parent = node->parent;
|
||||
decrement_reference(rbtdb, node, 0, isc_rwlocktype_write,
|
||||
isc_rwlocktype_write, true);
|
||||
|
||||
/*
|
||||
* Check whether the parent is an interior node. Note that it
|
||||
* might have been one before the decrement_reference() call on
|
||||
* the previous line, but decrementing the reference count for
|
||||
* 'node' could have caused 'node->parent->down' to become
|
||||
* NULL.
|
||||
*/
|
||||
if (parent != NULL && parent->down == NULL) {
|
||||
/*
|
||||
* Keep the node lock if possible; otherwise, release
|
||||
* the old lock and acquire one for the parent.
|
||||
* node was the only down child of the parent and has
|
||||
* just been removed. We'll then need to examine the
|
||||
* parent. Keep the lock if possible; otherwise,
|
||||
* release the old lock and acquire one for the parent.
|
||||
*/
|
||||
if (parent->locknum != locknum) {
|
||||
NODE_UNLOCK(&rbtdb->node_locks[locknum].lock,
|
||||
@@ -2209,9 +2170,13 @@ prune_tree(isc_task_t *task, isc_event_t *event) {
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to gain a reference to the parent node
|
||||
* before decrementing it in the next iteration.
|
||||
* We need to gain a reference to the node before
|
||||
* decrementing it in the next iteration.
|
||||
*/
|
||||
if (ISC_LINK_LINKED(parent, deadlink)) {
|
||||
ISC_LIST_UNLINK(rbtdb->deadnodes[locknum],
|
||||
parent, deadlink);
|
||||
}
|
||||
new_reference(rbtdb, parent, isc_rwlocktype_write);
|
||||
} else {
|
||||
parent = NULL;
|
||||
@@ -6862,10 +6827,6 @@ rdataset_size(rdatasetheader_t *header) {
|
||||
return (sizeof(*header));
|
||||
}
|
||||
|
||||
static void
|
||||
expire_ttl_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, bool tree_locked,
|
||||
isc_stdtime_t now);
|
||||
|
||||
static isc_result_t
|
||||
addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
|
||||
@@ -6875,6 +6836,7 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
rbtdb_version_t *rbtversion = version;
|
||||
isc_region_t region;
|
||||
rdatasetheader_t *newheader;
|
||||
rdatasetheader_t *header;
|
||||
isc_result_t result;
|
||||
bool delegating;
|
||||
bool newnsec;
|
||||
@@ -7047,7 +7009,20 @@ addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
|
||||
cleanup_dead_nodes(rbtdb, rbtnode->locknum);
|
||||
}
|
||||
|
||||
expire_ttl_headers(rbtdb, rbtnode->locknum, tree_locked, now);
|
||||
header = isc_heap_element(rbtdb->heaps[rbtnode->locknum], 1);
|
||||
if (header != NULL) {
|
||||
dns_ttl_t rdh_ttl = header->rdh_ttl;
|
||||
|
||||
/* Only account for stale TTL if cache is not overmem */
|
||||
if (!cache_is_overmem) {
|
||||
rdh_ttl += STALE_TTL(header, rbtdb);
|
||||
}
|
||||
|
||||
if (rdh_ttl < now - RBTDB_VIRTUAL) {
|
||||
expire_header(rbtdb, header, tree_locked,
|
||||
expire_ttl);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we've been holding a write lock on the tree just for
|
||||
@@ -7767,7 +7742,7 @@ hashsize(dns_db_t *db) {
|
||||
}
|
||||
|
||||
static void
|
||||
settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
settask(dns_db_t *db, isc_task_t *task) {
|
||||
dns_rbtdb_t *rbtdb;
|
||||
|
||||
rbtdb = (dns_rbtdb_t *)db;
|
||||
@@ -7781,12 +7756,6 @@ settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
if (task != NULL) {
|
||||
isc_task_attach(task, &rbtdb->task);
|
||||
}
|
||||
if (rbtdb->prunetask != NULL) {
|
||||
isc_task_detach(&rbtdb->prunetask);
|
||||
}
|
||||
if (prunetask != NULL) {
|
||||
isc_task_attach(prunetask, &rbtdb->prunetask);
|
||||
}
|
||||
RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);
|
||||
}
|
||||
|
||||
@@ -8464,7 +8433,6 @@ dns_rbtdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
|
||||
isc_refcount_init(&rbtdb->references, 1);
|
||||
rbtdb->attributes = 0;
|
||||
rbtdb->task = NULL;
|
||||
rbtdb->prunetask = NULL;
|
||||
rbtdb->serve_stale_ttl = 0;
|
||||
|
||||
/*
|
||||
@@ -10196,21 +10164,22 @@ update_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, isc_stdtime_t now) {
|
||||
static size_t
|
||||
expire_lru_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, size_t purgesize,
|
||||
bool tree_locked) {
|
||||
rdatasetheader_t *header;
|
||||
rdatasetheader_t *header, *header_prev;
|
||||
size_t purged = 0;
|
||||
|
||||
for (header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]);
|
||||
header != NULL &&
|
||||
header->last_used <= atomic_load(&rbtdb->last_used) &&
|
||||
purged <= purgesize;
|
||||
header = ISC_LIST_TAIL(rbtdb->rdatasets[locknum]))
|
||||
header = header_prev)
|
||||
{
|
||||
header_prev = ISC_LIST_PREV(header, link);
|
||||
/*
|
||||
* Unlink the entry at this point to avoid checking it
|
||||
* again even if it's currently used someone else and
|
||||
* cannot be purged at this moment. This entry won't be
|
||||
* referenced any more (so unlinking is safe) since the
|
||||
* TTL will be reset to 0.
|
||||
* TTL was reset to 0.
|
||||
*/
|
||||
ISC_LIST_UNLINK(rbtdb->rdatasets[locknum], header, link);
|
||||
size_t header_size = rdataset_size(header);
|
||||
@@ -10322,40 +10291,3 @@ expire_header(dns_rbtdb_t *rbtdb, rdatasetheader_t *header, bool tree_locked,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Caller must be holding the node write lock.
|
||||
*/
|
||||
static void
|
||||
expire_ttl_headers(dns_rbtdb_t *rbtdb, unsigned int locknum, bool tree_locked,
|
||||
isc_stdtime_t now) {
|
||||
isc_heap_t *heap = rbtdb->heaps[locknum];
|
||||
|
||||
for (size_t i = 0; i < DNS_RBTDB_EXPIRE_TTL_COUNT; i++) {
|
||||
rdatasetheader_t *header = isc_heap_element(heap, 1);
|
||||
|
||||
if (header == NULL) {
|
||||
/* No headers left on this TTL heap; exit cleaning */
|
||||
return;
|
||||
}
|
||||
|
||||
dns_ttl_t ttl = header->rdh_ttl;
|
||||
|
||||
if (!isc_mem_isovermem(rbtdb->common.mctx)) {
|
||||
/* Only account for stale TTL if cache is not overmem */
|
||||
ttl += STALE_TTL(header, rbtdb);
|
||||
}
|
||||
|
||||
if (ttl >= now - RBTDB_VIRTUAL) {
|
||||
/*
|
||||
* The header at the top of this TTL heap is not yet
|
||||
* eligible for expiry, so none of the other headers on
|
||||
* the same heap can be eligible for expiry, either;
|
||||
* exit cleaning.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
expire_header(rbtdb, header, tree_locked, expire_ttl);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -10408,8 +10408,8 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
|
||||
* Since we have a pool of tasks we bind them to task
|
||||
* queues to spread the load evenly
|
||||
*/
|
||||
result = isc_task_create_bound(
|
||||
taskmgr, 0, &res->buckets[i].task, ISC_NM_TASK_SLOW(i));
|
||||
result = isc_task_create_bound(taskmgr, 0,
|
||||
&res->buckets[i].task, i);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
ntasks = i;
|
||||
isc_mutex_destroy(&res->buckets[i].lock);
|
||||
|
||||
+1
-2
@@ -1263,10 +1263,9 @@ overmem(dns_db_t *db, bool over) {
|
||||
}
|
||||
|
||||
static void
|
||||
settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
settask(dns_db_t *db, isc_task_t *task) {
|
||||
UNUSED(db);
|
||||
UNUSED(task);
|
||||
UNUSED(prunetask);
|
||||
}
|
||||
|
||||
static dns_dbmethods_t sdb_methods = {
|
||||
|
||||
+1
-2
@@ -1213,10 +1213,9 @@ overmem(dns_db_t *db, bool over) {
|
||||
}
|
||||
|
||||
static void
|
||||
settask(dns_db_t *db, isc_task_t *task, isc_task_t *prunetask) {
|
||||
settask(dns_db_t *db, isc_task_t *task) {
|
||||
UNUSED(db);
|
||||
UNUSED(task);
|
||||
UNUSED(prunetask);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+8
-14
@@ -1757,9 +1757,8 @@ isc_result_t
|
||||
dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
|
||||
const dns_name_t *algorithm, dns_tsig_keyring_t *ring) {
|
||||
dns_tsigkey_t *key;
|
||||
isc_result_t result;
|
||||
isc_rwlocktype_t locktype = isc_rwlocktype_read;
|
||||
isc_stdtime_t now;
|
||||
isc_result_t result;
|
||||
|
||||
REQUIRE(tsigkey != NULL);
|
||||
REQUIRE(*tsigkey == NULL);
|
||||
@@ -1771,30 +1770,25 @@ dns_tsigkey_find(dns_tsigkey_t **tsigkey, const dns_name_t *name,
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||
|
||||
isc_stdtime_get(&now);
|
||||
|
||||
again:
|
||||
RWLOCK(&ring->lock, locktype);
|
||||
RWLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
key = NULL;
|
||||
result = dns_rbt_findname(ring->keys, name, 0, NULL, (void *)&key);
|
||||
if (result == DNS_R_PARTIALMATCH || result == ISC_R_NOTFOUND) {
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
if (algorithm != NULL && !dns_name_equal(key->algorithm, algorithm)) {
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
if (key->inception != key->expire && isc_serial_lt(key->expire, now)) {
|
||||
/*
|
||||
* The key has expired.
|
||||
*/
|
||||
if (locktype == isc_rwlocktype_read) {
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
locktype = isc_rwlocktype_write;
|
||||
goto again;
|
||||
}
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
RWLOCK(&ring->lock, isc_rwlocktype_write);
|
||||
remove_fromring(key);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_write);
|
||||
return (ISC_R_NOTFOUND);
|
||||
}
|
||||
#if 0
|
||||
@@ -1809,7 +1803,7 @@ again:
|
||||
}
|
||||
#endif /* if 0 */
|
||||
isc_refcount_increment(&key->refs);
|
||||
RWUNLOCK(&ring->lock, locktype);
|
||||
RWUNLOCK(&ring->lock, isc_rwlocktype_read);
|
||||
adjust_lru(key);
|
||||
*tsigkey = key;
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
+38
-31
@@ -1104,8 +1104,8 @@ create_validator(dns_validator_t *val, dns_name_t *name, dns_rdatatype_t type,
|
||||
* 'rdataset'. If found, build a dst_key_t for it and point val->key at
|
||||
* it.
|
||||
*
|
||||
* If val->key is already non-NULL, start searching from the next position in
|
||||
* 'rdataset' to find the *next* key that could have signed 'siginfo', then
|
||||
* If val->key is already non-NULL, locate it in the rdataset and then
|
||||
* search past it for the *next* key that could have signed 'siginfo', then
|
||||
* set val->key to that.
|
||||
*
|
||||
* Returns ISC_R_SUCCESS if a possible matching key has been found,
|
||||
@@ -1118,59 +1118,59 @@ select_signing_key(dns_validator_t *val, dns_rdataset_t *rdataset) {
|
||||
isc_buffer_t b;
|
||||
dns_rdata_t rdata = DNS_RDATA_INIT;
|
||||
dst_key_t *oldkey = val->key;
|
||||
bool no_rdata = false;
|
||||
bool foundold;
|
||||
|
||||
if (oldkey == NULL) {
|
||||
result = dns_rdataset_first(rdataset);
|
||||
foundold = true;
|
||||
} else {
|
||||
dst_key_free(&oldkey);
|
||||
foundold = false;
|
||||
val->key = NULL;
|
||||
result = dns_rdataset_next(rdataset);
|
||||
}
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = dns_rdataset_first(rdataset);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
goto failure;
|
||||
}
|
||||
do {
|
||||
dns_rdataset_current(rdataset, &rdata);
|
||||
|
||||
isc_buffer_init(&b, rdata.data, rdata.length);
|
||||
isc_buffer_add(&b, rdata.length);
|
||||
INSIST(val->key == NULL);
|
||||
result = dst_key_fromdns_ex(&siginfo->signer, rdata.rdclass, &b,
|
||||
val->view->mctx, no_rdata,
|
||||
&val->key);
|
||||
result = dst_key_fromdns(&siginfo->signer, rdata.rdclass, &b,
|
||||
val->view->mctx, &val->key);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
if (siginfo->algorithm ==
|
||||
(dns_secalg_t)dst_key_alg(val->key) &&
|
||||
siginfo->keyid ==
|
||||
(dns_keytag_t)dst_key_id(val->key) &&
|
||||
(dst_key_flags(val->key) & DNS_KEYFLAG_REVOKE) ==
|
||||
0 &&
|
||||
dst_key_iszonekey(val->key))
|
||||
{
|
||||
if (no_rdata) {
|
||||
/* Retry with full key */
|
||||
dns_rdata_reset(&rdata);
|
||||
dst_key_free(&val->key);
|
||||
no_rdata = false;
|
||||
continue;
|
||||
if (foundold) {
|
||||
/*
|
||||
* This is the key we're looking for.
|
||||
*/
|
||||
return (ISC_R_SUCCESS);
|
||||
} else if (dst_key_compare(oldkey, val->key)) {
|
||||
foundold = true;
|
||||
dst_key_free(&oldkey);
|
||||
}
|
||||
/* This is the key we're looking for. */
|
||||
goto done;
|
||||
}
|
||||
dst_key_free(&val->key);
|
||||
}
|
||||
dns_rdata_reset(&rdata);
|
||||
result = dns_rdataset_next(rdataset);
|
||||
no_rdata = true;
|
||||
} while (result == ISC_R_SUCCESS);
|
||||
|
||||
done:
|
||||
if (result == ISC_R_NOMORE) {
|
||||
result = ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
failure:
|
||||
if (oldkey != NULL) {
|
||||
dst_key_free(&oldkey);
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
@@ -1589,9 +1589,20 @@ validate_answer(dns_validator_t *val, bool resume) {
|
||||
continue;
|
||||
}
|
||||
|
||||
vresult = verify(val, val->key, &rdata, val->siginfo->keyid);
|
||||
do {
|
||||
isc_result_t tresult;
|
||||
vresult = verify(val, val->key, &rdata,
|
||||
val->siginfo->keyid);
|
||||
if (vresult == ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
tresult = select_signing_key(val, val->keyset);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
if (vresult != ISC_R_SUCCESS) {
|
||||
val->failed = true;
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"failed to verify rdataset");
|
||||
} else {
|
||||
@@ -1628,13 +1639,9 @@ validate_answer(dns_validator_t *val, bool resume) {
|
||||
} else {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
"verify failure: %s",
|
||||
isc_result_totext(vresult));
|
||||
isc_result_totext(result));
|
||||
resume = false;
|
||||
}
|
||||
if (val->failed) {
|
||||
result = ISC_R_NOMORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (result != ISC_R_NOMORE) {
|
||||
validator_log(val, ISC_LOG_DEBUG(3),
|
||||
|
||||
+4
-4
@@ -2339,7 +2339,7 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
|
||||
isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
dns_db_settask(db, zone->task, zone->task);
|
||||
dns_db_settask(db, zone->task);
|
||||
|
||||
if (zone->type == dns_zone_primary ||
|
||||
zone->type == dns_zone_secondary || zone->type == dns_zone_mirror)
|
||||
@@ -14791,7 +14791,7 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
||||
isc_result_totext(result));
|
||||
goto cleanup;
|
||||
}
|
||||
dns_db_settask(stub->db, zone->task, zone->task);
|
||||
dns_db_settask(stub->db, zone->task);
|
||||
}
|
||||
|
||||
result = dns_db_newversion(stub->db, &stub->version);
|
||||
@@ -16235,7 +16235,7 @@ dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
|
||||
isc_task_attach(task, &zone->task);
|
||||
ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
if (zone->db != NULL) {
|
||||
dns_db_settask(zone->db, zone->task, zone->task);
|
||||
dns_db_settask(zone->db, zone->task);
|
||||
}
|
||||
ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
|
||||
UNLOCK_ZONE(zone);
|
||||
@@ -17508,7 +17508,7 @@ zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
|
||||
zone_detachdb(zone);
|
||||
}
|
||||
zone_attachdb(zone, db);
|
||||
dns_db_settask(zone->db, zone->task, zone->task);
|
||||
dns_db_settask(zone->db, zone->task);
|
||||
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
|
||||
return (ISC_R_SUCCESS);
|
||||
|
||||
|
||||
+4
-51
@@ -93,54 +93,11 @@ maybe_rehash(isc_ht_t *ht, size_t newcount);
|
||||
static isc_result_t
|
||||
isc__ht_iter_next(isc_ht_iter_t *it);
|
||||
|
||||
static uint8_t maptolower[] = {
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
|
||||
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
|
||||
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
|
||||
0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
|
||||
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
|
||||
0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
||||
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
|
||||
0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
|
||||
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
|
||||
0xfc, 0xfd, 0xfe, 0xff
|
||||
};
|
||||
|
||||
static int
|
||||
memcasecmp(const void *vs1, const void *vs2, size_t len) {
|
||||
uint8_t const *s1 = vs1;
|
||||
uint8_t const *s2 = vs2;
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
uint8_t u1 = s1[i];
|
||||
uint8_t u2 = s2[i];
|
||||
int U1 = maptolower[u1];
|
||||
int U2 = maptolower[u2];
|
||||
int diff = U1 - U2;
|
||||
if (diff) {
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
isc__ht_node_match(isc_ht_node_t *node, const uint32_t hashval,
|
||||
const uint8_t *key, uint32_t keysize, bool case_sensitive) {
|
||||
const uint8_t *key, uint32_t keysize) {
|
||||
return (node->hashval == hashval && node->keysize == keysize &&
|
||||
(case_sensitive ? (memcmp(node->key, key, keysize) == 0)
|
||||
: (memcasecmp(node->key, key, keysize) == 0)));
|
||||
memcmp(node->key, key, keysize) == 0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
@@ -384,9 +341,7 @@ nexttable:
|
||||
for (isc_ht_node_t *node = ht->table[findex][hash]; node != NULL;
|
||||
node = node->next)
|
||||
{
|
||||
if (isc__ht_node_match(node, hashval, key, keysize,
|
||||
ht->case_sensitive))
|
||||
{
|
||||
if (isc__ht_node_match(node, hashval, key, keysize)) {
|
||||
return (node);
|
||||
}
|
||||
}
|
||||
@@ -435,9 +390,7 @@ isc__ht_delete(isc_ht_t *ht, const unsigned char *key, const uint32_t keysize,
|
||||
for (isc_ht_node_t *node = ht->table[idx][hash]; node != NULL;
|
||||
prev = node, node = node->next)
|
||||
{
|
||||
if (isc__ht_node_match(node, hashval, key, keysize,
|
||||
ht->case_sensitive))
|
||||
{
|
||||
if (isc__ht_node_match(node, hashval, key, keysize)) {
|
||||
if (prev == NULL) {
|
||||
ht->table[idx][hash] = node->next;
|
||||
} else {
|
||||
|
||||
@@ -750,9 +750,6 @@ isc_nm_verify_tls_peer_result_string(const isc_nmhandle_t *handle);
|
||||
* \li 'handle' is a valid netmgr handle object.
|
||||
*/
|
||||
|
||||
#define ISC_NM_TASK_SLOW_OFFSET -2
|
||||
#define ISC_NM_TASK_SLOW(i) (ISC_NM_TASK_SLOW_OFFSET - 1 - i)
|
||||
|
||||
void
|
||||
isc_nm_task_enqueue(isc_nm_t *mgr, isc_task_t *task, int threadid);
|
||||
/*%<
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/result.h>
|
||||
|
||||
/*! \file isc/types.h
|
||||
@@ -75,11 +74,10 @@ typedef struct isc_rwlock isc_rwlock_t; /*%< Read Write Lock */
|
||||
typedef struct isc_sockaddr isc_sockaddr_t; /*%< Socket Address */
|
||||
typedef ISC_LIST(isc_sockaddr_t) isc_sockaddrlist_t; /*%< Socket Address List
|
||||
* */
|
||||
typedef struct isc_stats isc_stats_t; /*%< Statistics */
|
||||
typedef int_fast64_t isc_statscounter_t;
|
||||
typedef atomic_int_fast64_t isc_atomic_statscounter_t;
|
||||
typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */
|
||||
typedef struct isc_task isc_task_t; /*%< Task */
|
||||
typedef struct isc_stats isc_stats_t; /*%< Statistics */
|
||||
typedef int_fast64_t isc_statscounter_t;
|
||||
typedef struct isc_symtab isc_symtab_t; /*%< Symbol Table */
|
||||
typedef struct isc_task isc_task_t; /*%< Task */
|
||||
typedef ISC_LIST(isc_task_t) isc_tasklist_t; /*%< Task List */
|
||||
typedef struct isc_taskmgr isc_taskmgr_t; /*%< Task Manager */
|
||||
typedef struct isc_textregion isc_textregion_t; /*%< Text Region */
|
||||
|
||||
@@ -2969,7 +2969,7 @@ isc__nm_http_set_max_streams(isc_nmsocket_t *listener,
|
||||
void
|
||||
isc_nm_http_set_endpoints(isc_nmsocket_t *listener,
|
||||
isc_nm_http_endpoints_t *eps) {
|
||||
size_t nlisteners;
|
||||
size_t nworkers;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(listener->type == isc_nm_httplistener);
|
||||
@@ -2977,8 +2977,8 @@ isc_nm_http_set_endpoints(isc_nmsocket_t *listener,
|
||||
|
||||
atomic_store(&eps->in_use, true);
|
||||
|
||||
nlisteners = (size_t)listener->mgr->nlisteners;
|
||||
for (size_t i = 0; i < nlisteners; i++) {
|
||||
nworkers = (size_t)listener->mgr->nworkers;
|
||||
for (size_t i = 0; i < nworkers; i++) {
|
||||
isc__netievent__http_eps_t *ievent =
|
||||
isc__nm_get_netievent_httpendpoints(listener->mgr,
|
||||
listener, eps);
|
||||
@@ -3003,20 +3003,20 @@ isc__nm_async_httpendpoints(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
static void
|
||||
http_init_listener_endpoints(isc_nmsocket_t *listener,
|
||||
isc_nm_http_endpoints_t *epset) {
|
||||
size_t nlisteners;
|
||||
size_t nworkers;
|
||||
|
||||
REQUIRE(VALID_NMSOCK(listener));
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
REQUIRE(VALID_HTTP_ENDPOINTS(epset));
|
||||
|
||||
nlisteners = (size_t)listener->mgr->nlisteners;
|
||||
INSIST(nlisteners > 0);
|
||||
nworkers = (size_t)listener->mgr->nworkers;
|
||||
INSIST(nworkers > 0);
|
||||
|
||||
listener->h2.listener_endpoints =
|
||||
isc_mem_get(listener->mgr->mctx,
|
||||
sizeof(isc_nm_http_endpoints_t *) * nlisteners);
|
||||
listener->h2.n_listener_endpoints = nlisteners;
|
||||
for (size_t i = 0; i < nlisteners; i++) {
|
||||
sizeof(isc_nm_http_endpoints_t *) * nworkers);
|
||||
listener->h2.n_listener_endpoints = nworkers;
|
||||
for (size_t i = 0; i < nworkers; i++) {
|
||||
listener->h2.listener_endpoints[i] = NULL;
|
||||
isc_nm_http_endpoints_attach(
|
||||
epset, &listener->h2.listener_endpoints[i]);
|
||||
|
||||
@@ -776,7 +776,6 @@ struct isc_nm {
|
||||
isc_refcount_t references;
|
||||
isc_mem_t *mctx;
|
||||
int nworkers;
|
||||
int nlisteners;
|
||||
isc_mutex_t lock;
|
||||
isc_condition_t wkstatecond;
|
||||
isc_condition_t wkpausecond;
|
||||
|
||||
+14
-24
@@ -189,12 +189,12 @@ isc__nm_force_tid(int tid) {
|
||||
}
|
||||
|
||||
static void
|
||||
isc__nm_threadpool_initialize(uint32_t nworkers) {
|
||||
isc__nm_threadpool_initialize(uint32_t workers) {
|
||||
char buf[11];
|
||||
int r = uv_os_getenv("UV_THREADPOOL_SIZE", buf,
|
||||
&(size_t){ sizeof(buf) });
|
||||
if (r == UV_ENOENT) {
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32, nworkers);
|
||||
snprintf(buf, sizeof(buf), "%" PRIu32, workers);
|
||||
uv_os_setenv("UV_THREADPOOL_SIZE", buf);
|
||||
}
|
||||
}
|
||||
@@ -212,11 +212,11 @@ isc__nm_threadpool_initialize(uint32_t nworkers) {
|
||||
#endif
|
||||
|
||||
void
|
||||
isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
|
||||
isc__netmgr_create(isc_mem_t *mctx, uint32_t workers, isc_nm_t **netmgrp) {
|
||||
isc_nm_t *mgr = NULL;
|
||||
char name[32];
|
||||
|
||||
REQUIRE(nworkers > 0);
|
||||
REQUIRE(workers > 0);
|
||||
|
||||
#ifdef MAXIMAL_UV_VERSION
|
||||
if (uv_version() > MAXIMAL_UV_VERSION) {
|
||||
@@ -234,13 +234,10 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
|
||||
uv_version_string(), UV_VERSION_STRING);
|
||||
}
|
||||
|
||||
isc__nm_threadpool_initialize(nworkers);
|
||||
isc__nm_threadpool_initialize(workers);
|
||||
|
||||
mgr = isc_mem_get(mctx, sizeof(*mgr));
|
||||
*mgr = (isc_nm_t){
|
||||
.nworkers = nworkers * 2,
|
||||
.nlisteners = nworkers,
|
||||
};
|
||||
*mgr = (isc_nm_t){ .nworkers = workers };
|
||||
|
||||
isc_mem_attach(mctx, &mgr->mctx);
|
||||
isc_mutex_init(&mgr->lock);
|
||||
@@ -275,12 +272,11 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
|
||||
atomic_init(&mgr->keepalive, 30000);
|
||||
atomic_init(&mgr->advertised, 30000);
|
||||
|
||||
isc_barrier_init(&mgr->pausing, mgr->nworkers);
|
||||
isc_barrier_init(&mgr->resuming, mgr->nworkers);
|
||||
isc_barrier_init(&mgr->pausing, workers);
|
||||
isc_barrier_init(&mgr->resuming, workers);
|
||||
|
||||
mgr->workers = isc_mem_get(mctx,
|
||||
mgr->nworkers * sizeof(isc__networker_t));
|
||||
for (int i = 0; i < mgr->nworkers; i++) {
|
||||
mgr->workers = isc_mem_get(mctx, workers * sizeof(isc__networker_t));
|
||||
for (size_t i = 0; i < workers; i++) {
|
||||
isc__networker_t *worker = &mgr->workers[i];
|
||||
int r;
|
||||
|
||||
@@ -314,7 +310,7 @@ isc__netmgr_create(isc_mem_t *mctx, uint32_t nworkers, isc_nm_t **netmgrp) {
|
||||
mgr->workers_running++;
|
||||
isc_thread_create(nm_thread, &mgr->workers[i], &worker->thread);
|
||||
|
||||
snprintf(name, sizeof(name), "isc-net-%04d", i);
|
||||
snprintf(name, sizeof(name), "isc-net-%04zu", i);
|
||||
isc_thread_setname(worker->thread, name);
|
||||
}
|
||||
|
||||
@@ -821,15 +817,9 @@ isc_nm_task_enqueue(isc_nm_t *nm, isc_task_t *task, int threadid) {
|
||||
isc__networker_t *worker = NULL;
|
||||
|
||||
if (threadid == -1) {
|
||||
tid = (int)isc_random_uniform(nm->nlisteners);
|
||||
} else if (threadid == ISC_NM_TASK_SLOW_OFFSET) {
|
||||
tid = nm->nlisteners +
|
||||
(int)isc_random_uniform(nm->nworkers - nm->nlisteners);
|
||||
} else if (threadid < ISC_NM_TASK_SLOW_OFFSET) {
|
||||
tid = nm->nlisteners + (ISC_NM_TASK_SLOW(threadid) %
|
||||
(nm->nworkers - nm->nlisteners));
|
||||
tid = (int)isc_random_uniform(nm->nworkers);
|
||||
} else {
|
||||
tid = threadid % nm->nlisteners;
|
||||
tid = threadid % nm->nworkers;
|
||||
}
|
||||
|
||||
worker = &nm->workers[tid];
|
||||
@@ -3788,7 +3778,7 @@ isc__nm_async_settlsctx(isc__networker_t *worker, isc__netievent_t *ev0) {
|
||||
static void
|
||||
set_tlsctx_workers(isc_nmsocket_t *listener, isc_tlsctx_t *tlsctx) {
|
||||
/* Update the TLS context reference for every worker thread. */
|
||||
for (size_t i = 0; i < (size_t)listener->mgr->nlisteners; i++) {
|
||||
for (size_t i = 0; i < (size_t)listener->mgr->nworkers; i++) {
|
||||
isc__netievent__tlsctx_t *ievent =
|
||||
isc__nm_get_netievent_settlsctx(listener->mgr, listener,
|
||||
tlsctx);
|
||||
|
||||
@@ -341,7 +341,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc__nm_connectcb(sock, req, result, false);
|
||||
} else {
|
||||
isc__nmsocket_clearcb(sock);
|
||||
sock->tid = isc_random_uniform(mgr->nlisteners);
|
||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_connectcb(sock, req, result, true);
|
||||
}
|
||||
atomic_store(&sock->closed, true);
|
||||
@@ -362,7 +362,7 @@ isc_nm_tcpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc__nm_put_netievent_tcpconnect(mgr, ievent);
|
||||
} else {
|
||||
atomic_init(&sock->active, false);
|
||||
sock->tid = isc_random_uniform(mgr->nlisteners);
|
||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
@@ -457,7 +457,7 @@ isc_nm_listentcp(isc_nm_t *mgr, isc_sockaddr_t *iface,
|
||||
isc__nmsocket_init(sock, mgr, isc_nm_tcplistener, iface);
|
||||
|
||||
atomic_init(&sock->rchildren, 0);
|
||||
sock->nchildren = mgr->nlisteners;
|
||||
sock->nchildren = mgr->nworkers;
|
||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||
memset(sock->children, 0, children_size);
|
||||
|
||||
@@ -324,7 +324,7 @@ isc_nm_tcpdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc__nm_put_netievent_tcpdnsconnect(mgr, ievent);
|
||||
} else {
|
||||
atomic_init(&sock->active, false);
|
||||
sock->tid = isc_random_uniform(mgr->nlisteners);
|
||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
@@ -422,7 +422,7 @@ isc_nm_listentcpdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
|
||||
isc__nmsocket_init(sock, mgr, isc_nm_tcpdnslistener, iface);
|
||||
|
||||
atomic_init(&sock->rchildren, 0);
|
||||
sock->nchildren = mgr->nlisteners;
|
||||
sock->nchildren = mgr->nworkers;
|
||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||
memset(sock->children, 0, children_size);
|
||||
@@ -808,13 +808,6 @@ isc__nm_tcpdns_processbuffer(isc_nmsocket_t *sock) {
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
if (sock->client && !sock->recv_read) {
|
||||
/*
|
||||
* We are not reading data - stop here.
|
||||
*/
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
req = isc__nm_get_read_req(sock, NULL);
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
|
||||
@@ -419,7 +419,7 @@ isc_nm_tlsdnsconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc__nm_put_netievent_tlsdnsconnect(mgr, ievent);
|
||||
} else {
|
||||
atomic_init(&sock->active, false);
|
||||
sock->tid = isc_random_uniform(mgr->nlisteners);
|
||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)ievent);
|
||||
}
|
||||
@@ -532,7 +532,7 @@ isc_nm_listentlsdns(isc_nm_t *mgr, isc_sockaddr_t *iface,
|
||||
isc__nmsocket_init(sock, mgr, isc_nm_tlsdnslistener, iface);
|
||||
|
||||
atomic_init(&sock->rchildren, 0);
|
||||
sock->nchildren = mgr->nlisteners;
|
||||
sock->nchildren = mgr->nworkers;
|
||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||
memset(sock->children, 0, children_size);
|
||||
@@ -1016,13 +1016,6 @@ isc__nm_tlsdns_processbuffer(isc_nmsocket_t *sock) {
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
if (sock->client && !sock->recv_read) {
|
||||
/*
|
||||
* We are not reading data - stop here.
|
||||
*/
|
||||
return (ISC_R_CANCELED);
|
||||
}
|
||||
|
||||
req = isc__nm_get_read_req(sock, NULL);
|
||||
REQUIRE(VALID_UVREQ(req));
|
||||
|
||||
|
||||
@@ -1264,18 +1264,18 @@ isc__nm_tls_verify_tls_peer_result_string(const isc_nmhandle_t *handle) {
|
||||
|
||||
static void
|
||||
tls_init_listener_tlsctx(isc_nmsocket_t *listener, isc_tlsctx_t *ctx) {
|
||||
size_t nlisteners;
|
||||
size_t nworkers;
|
||||
|
||||
REQUIRE(VALID_NM(listener->mgr));
|
||||
REQUIRE(ctx != NULL);
|
||||
|
||||
nlisteners = (size_t)listener->mgr->nlisteners;
|
||||
INSIST(nlisteners > 0);
|
||||
nworkers = (size_t)listener->mgr->nworkers;
|
||||
INSIST(nworkers > 0);
|
||||
|
||||
listener->tlsstream.listener_tls_ctx = isc_mem_get(
|
||||
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nlisteners);
|
||||
listener->tlsstream.n_listener_tls_ctx = nlisteners;
|
||||
for (size_t i = 0; i < nlisteners; i++) {
|
||||
listener->mgr->mctx, sizeof(isc_tlsctx_t *) * nworkers);
|
||||
listener->tlsstream.n_listener_tls_ctx = nworkers;
|
||||
for (size_t i = 0; i < nworkers; i++) {
|
||||
listener->tlsstream.listener_tls_ctx[i] = NULL;
|
||||
isc_tlsctx_attach(ctx,
|
||||
&listener->tlsstream.listener_tls_ctx[i]);
|
||||
|
||||
@@ -157,14 +157,14 @@ isc_nm_listenudp(isc_nm_t *mgr, isc_sockaddr_t *iface, isc_nm_recv_cb_t cb,
|
||||
REQUIRE(VALID_NM(mgr));
|
||||
|
||||
/*
|
||||
* We are creating mgr->nlisteners duplicated sockets, one
|
||||
* We are creating mgr->nworkers duplicated sockets, one
|
||||
* socket for each worker thread.
|
||||
*/
|
||||
sock = isc_mem_get(mgr->mctx, sizeof(isc_nmsocket_t));
|
||||
isc__nmsocket_init(sock, mgr, isc_nm_udplistener, iface);
|
||||
|
||||
atomic_init(&sock->rchildren, 0);
|
||||
sock->nchildren = mgr->nlisteners;
|
||||
sock->nchildren = mgr->nworkers;
|
||||
children_size = sock->nchildren * sizeof(sock->children[0]);
|
||||
sock->children = isc_mem_get(mgr->mctx, children_size);
|
||||
memset(sock->children, 0, children_size);
|
||||
@@ -1037,7 +1037,7 @@ isc_nm_udpconnect(isc_nm_t *mgr, isc_sockaddr_t *local, isc_sockaddr_t *peer,
|
||||
isc__nm_put_netievent_udpconnect(mgr, event);
|
||||
} else {
|
||||
atomic_init(&sock->active, false);
|
||||
sock->tid = isc_random_uniform(mgr->nlisteners);
|
||||
sock->tid = isc_random_uniform(mgr->nworkers);
|
||||
isc__nm_enqueue_ievent(&mgr->workers[sock->tid],
|
||||
(isc__netievent_t *)event);
|
||||
}
|
||||
|
||||
+8
-17
@@ -28,22 +28,14 @@
|
||||
#define ISC_STATS_MAGIC ISC_MAGIC('S', 't', 'a', 't')
|
||||
#define ISC_STATS_VALID(x) ISC_MAGIC_VALID(x, ISC_STATS_MAGIC)
|
||||
|
||||
/*
|
||||
* Statistics are counted with an atomic int_fast64_t but exported to functions
|
||||
* taking uint64_t (isc_stats_dumper_t). A 128-bit native and fast architecture
|
||||
* doesn't exist in reality so these two are the same thing in practise.
|
||||
* However, a silent truncation happening silently in the future is still not
|
||||
* acceptable.
|
||||
*/
|
||||
STATIC_ASSERT(sizeof(isc_statscounter_t) <= sizeof(uint64_t),
|
||||
"Exported statistics must fit into the statistic counter size");
|
||||
typedef atomic_int_fast64_t isc__atomic_statcounter_t;
|
||||
|
||||
struct isc_stats {
|
||||
unsigned int magic;
|
||||
isc_mem_t *mctx;
|
||||
isc_refcount_t references;
|
||||
int ncounters;
|
||||
isc_atomic_statscounter_t *counters;
|
||||
isc__atomic_statcounter_t *counters;
|
||||
};
|
||||
|
||||
static isc_result_t
|
||||
@@ -54,7 +46,7 @@ create_stats(isc_mem_t *mctx, int ncounters, isc_stats_t **statsp) {
|
||||
REQUIRE(statsp != NULL && *statsp == NULL);
|
||||
|
||||
stats = isc_mem_get(mctx, sizeof(*stats));
|
||||
counters_alloc_size = sizeof(isc_atomic_statscounter_t) * ncounters;
|
||||
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters;
|
||||
stats->counters = isc_mem_get(mctx, counters_alloc_size);
|
||||
isc_refcount_init(&stats->references, 1);
|
||||
for (int i = 0; i < ncounters; i++) {
|
||||
@@ -90,7 +82,7 @@ isc_stats_detach(isc_stats_t **statsp) {
|
||||
if (isc_refcount_decrement(&stats->references) == 1) {
|
||||
isc_refcount_destroy(&stats->references);
|
||||
isc_mem_put(stats->mctx, stats->counters,
|
||||
sizeof(isc_atomic_statscounter_t) *
|
||||
sizeof(isc__atomic_statcounter_t) *
|
||||
stats->ncounters);
|
||||
isc_mem_putanddetach(&stats->mctx, stats, sizeof(*stats));
|
||||
}
|
||||
@@ -133,8 +125,7 @@ isc_stats_dump(isc_stats_t *stats, isc_stats_dumper_t dump_fn, void *arg,
|
||||
REQUIRE(ISC_STATS_VALID(stats));
|
||||
|
||||
for (i = 0; i < stats->ncounters; i++) {
|
||||
isc_statscounter_t counter =
|
||||
atomic_load_acquire(&stats->counters[i]);
|
||||
uint32_t counter = atomic_load_acquire(&stats->counters[i]);
|
||||
if ((options & ISC_STATSDUMP_VERBOSE) == 0 && counter == 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -178,7 +169,7 @@ void
|
||||
isc_stats_resize(isc_stats_t **statsp, int ncounters) {
|
||||
isc_stats_t *stats;
|
||||
size_t counters_alloc_size;
|
||||
isc_atomic_statscounter_t *newcounters;
|
||||
isc__atomic_statcounter_t *newcounters;
|
||||
|
||||
REQUIRE(statsp != NULL && *statsp != NULL);
|
||||
REQUIRE(ISC_STATS_VALID(*statsp));
|
||||
@@ -191,7 +182,7 @@ isc_stats_resize(isc_stats_t **statsp, int ncounters) {
|
||||
}
|
||||
|
||||
/* Grow number of counters. */
|
||||
counters_alloc_size = sizeof(isc_atomic_statscounter_t) * ncounters;
|
||||
counters_alloc_size = sizeof(isc__atomic_statcounter_t) * ncounters;
|
||||
newcounters = isc_mem_get(stats->mctx, counters_alloc_size);
|
||||
for (int i = 0; i < ncounters; i++) {
|
||||
atomic_init(&newcounters[i], 0);
|
||||
@@ -201,7 +192,7 @@ isc_stats_resize(isc_stats_t **statsp, int ncounters) {
|
||||
atomic_store_release(&newcounters[i], counter);
|
||||
}
|
||||
isc_mem_put(stats->mctx, stats->counters,
|
||||
sizeof(isc_atomic_statscounter_t) * stats->ncounters);
|
||||
sizeof(isc__atomic_statcounter_t) * stats->ncounters);
|
||||
stats->counters = newcounters;
|
||||
stats->ncounters = ncounters;
|
||||
}
|
||||
|
||||
+12
-17
@@ -465,10 +465,10 @@ static void
|
||||
query_addnxrrsetnsec(query_ctx_t *qctx);
|
||||
|
||||
static isc_result_t
|
||||
query_nxdomain(query_ctx_t *qctx, isc_result_t result);
|
||||
query_nxdomain(query_ctx_t *qctx, isc_result_t res);
|
||||
|
||||
static isc_result_t
|
||||
query_redirect(query_ctx_t *qctx, isc_result_t result);
|
||||
query_redirect(query_ctx_t *qctx);
|
||||
|
||||
static isc_result_t
|
||||
query_ncache(query_ctx_t *qctx, isc_result_t result);
|
||||
@@ -6228,13 +6228,6 @@ query_lookup_stale(ns_client_t *client) {
|
||||
query_ctx_t qctx;
|
||||
|
||||
qctx_init(client, NULL, client->query.qtype, &qctx);
|
||||
if (DNS64(client)) {
|
||||
qctx.qtype = qctx.type = dns_rdatatype_a;
|
||||
qctx.dns64 = true;
|
||||
}
|
||||
if (DNS64EXCLUDE(client)) {
|
||||
qctx.dns64_exclude = true;
|
||||
}
|
||||
dns_db_attach(client->view->cachedb, &qctx.db);
|
||||
client->query.attributes &= ~NS_QUERYATTR_RECURSIONOK;
|
||||
client->query.dboptions |= DNS_DBFIND_STALETIMEOUT;
|
||||
@@ -7725,7 +7718,8 @@ query_usestale(query_ctx_t *qctx, isc_result_t result) {
|
||||
* result from the search.
|
||||
*/
|
||||
static isc_result_t
|
||||
query_gotanswer(query_ctx_t *qctx, isc_result_t result) {
|
||||
query_gotanswer(query_ctx_t *qctx, isc_result_t res) {
|
||||
isc_result_t result = res;
|
||||
char errmsg[256];
|
||||
|
||||
CCTRACE(ISC_LOG_DEBUG(3), "query_gotanswer");
|
||||
@@ -7801,7 +7795,7 @@ root_key_sentinel:
|
||||
return (query_coveringnsec(qctx));
|
||||
|
||||
case DNS_R_NCACHENXDOMAIN:
|
||||
result = query_redirect(qctx, result);
|
||||
result = query_redirect(qctx);
|
||||
if (result != ISC_R_COMPLETE) {
|
||||
return (result);
|
||||
}
|
||||
@@ -9618,10 +9612,11 @@ query_addnxrrsetnsec(query_ctx_t *qctx) {
|
||||
* Handle NXDOMAIN and empty wildcard responses.
|
||||
*/
|
||||
static isc_result_t
|
||||
query_nxdomain(query_ctx_t *qctx, isc_result_t result) {
|
||||
query_nxdomain(query_ctx_t *qctx, isc_result_t res) {
|
||||
dns_section_t section;
|
||||
uint32_t ttl;
|
||||
bool empty_wild = (result == DNS_R_EMPTYWILD);
|
||||
isc_result_t result = res;
|
||||
bool empty_wild = (res == DNS_R_EMPTYWILD);
|
||||
|
||||
CCTRACE(ISC_LOG_DEBUG(3), "query_nxdomain");
|
||||
|
||||
@@ -9630,7 +9625,7 @@ query_nxdomain(query_ctx_t *qctx, isc_result_t result) {
|
||||
INSIST(qctx->is_zone || REDIRECT(qctx->client));
|
||||
|
||||
if (!empty_wild) {
|
||||
result = query_redirect(qctx, result);
|
||||
result = query_redirect(qctx);
|
||||
if (result != ISC_R_COMPLETE) {
|
||||
return (result);
|
||||
}
|
||||
@@ -9718,7 +9713,7 @@ cleanup:
|
||||
* redirecting, so query processing should continue past it.
|
||||
*/
|
||||
static isc_result_t
|
||||
query_redirect(query_ctx_t *qctx, isc_result_t saved_result) {
|
||||
query_redirect(query_ctx_t *qctx) {
|
||||
isc_result_t result;
|
||||
|
||||
CCTRACE(ISC_LOG_DEBUG(3), "query_redirect");
|
||||
@@ -9759,7 +9754,7 @@ query_redirect(query_ctx_t *qctx, isc_result_t saved_result) {
|
||||
SAVE(qctx->client->query.redirect.rdataset, qctx->rdataset);
|
||||
SAVE(qctx->client->query.redirect.sigrdataset,
|
||||
qctx->sigrdataset);
|
||||
qctx->client->query.redirect.result = saved_result;
|
||||
qctx->client->query.redirect.result = DNS_R_NCACHENXDOMAIN;
|
||||
dns_name_copy(qctx->fname, qctx->client->query.redirect.fname);
|
||||
qctx->client->query.redirect.authoritative =
|
||||
qctx->authoritative;
|
||||
@@ -10420,7 +10415,7 @@ query_coveringnsec(query_ctx_t *qctx) {
|
||||
* We now have the proof that we have an NXDOMAIN. Apply
|
||||
* NXDOMAIN redirection if configured.
|
||||
*/
|
||||
result = query_redirect(qctx, DNS_R_COVERINGNSEC);
|
||||
result = query_redirect(qctx);
|
||||
if (result != ISC_R_COMPLETE) {
|
||||
redirected = true;
|
||||
goto cleanup;
|
||||
|
||||
@@ -312,57 +312,7 @@ ISC_RUN_TEST_IMPL(isc_ht_iterator) {
|
||||
test_ht_iterator();
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(isc_ht_case) {
|
||||
isc_ht_t *ht = NULL;
|
||||
void *f = NULL;
|
||||
isc_result_t result = ISC_R_UNSET;
|
||||
|
||||
unsigned char lower[16] = { "test case" };
|
||||
unsigned char same[16] = { "test case" };
|
||||
unsigned char upper[16] = { "TEST CASE" };
|
||||
unsigned char mixed[16] = { "tEsT CaSe" };
|
||||
|
||||
isc_ht_init(&ht, mctx, 8, ISC_HT_CASE_SENSITIVE);
|
||||
assert_non_null(ht);
|
||||
|
||||
result = isc_ht_add(ht, lower, 16, (void *)lower);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_ht_add(ht, same, 16, (void *)same);
|
||||
assert_int_equal(result, ISC_R_EXISTS);
|
||||
|
||||
result = isc_ht_add(ht, upper, 16, (void *)upper);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_ht_find(ht, mixed, 16, &f);
|
||||
assert_int_equal(result, ISC_R_NOTFOUND);
|
||||
assert_null(f);
|
||||
|
||||
isc_ht_destroy(&ht);
|
||||
assert_null(ht);
|
||||
|
||||
isc_ht_init(&ht, mctx, 8, ISC_HT_CASE_INSENSITIVE);
|
||||
assert_non_null(ht);
|
||||
|
||||
result = isc_ht_add(ht, lower, 16, (void *)lower);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
result = isc_ht_add(ht, same, 16, (void *)same);
|
||||
assert_int_equal(result, ISC_R_EXISTS);
|
||||
|
||||
result = isc_ht_add(ht, upper, 16, (void *)upper);
|
||||
assert_int_equal(result, ISC_R_EXISTS);
|
||||
|
||||
result = isc_ht_find(ht, mixed, 16, &f);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
assert_ptr_equal(f, &lower);
|
||||
|
||||
isc_ht_destroy(&ht);
|
||||
assert_null(ht);
|
||||
}
|
||||
|
||||
ISC_TEST_LIST_START
|
||||
ISC_TEST_ENTRY(isc_ht_case)
|
||||
ISC_TEST_ENTRY(isc_ht_20)
|
||||
ISC_TEST_ENTRY(isc_ht_8)
|
||||
ISC_TEST_ENTRY(isc_ht_1)
|
||||
|
||||
@@ -2401,176 +2401,6 @@ ISC_RUN_TEST_IMPL(tlsdns_recv_one) {
|
||||
atomic_assert_int_eq(ssends, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
tlsdns_many_listen_read_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *cbarg) {
|
||||
uint64_t magic = 0;
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
isc_buffer_t *send_data = (isc_buffer_t *)cbarg;
|
||||
isc_region_t send_messages = { 0 };
|
||||
|
||||
assert_non_null(handle);
|
||||
assert_non_null(send_data);
|
||||
|
||||
F();
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
goto unref;
|
||||
}
|
||||
|
||||
atomic_fetch_add(&sreads, 1);
|
||||
|
||||
assert_true(region->length >= sizeof(magic));
|
||||
|
||||
memmove(&magic, region->base + sizeof(uint16_t), sizeof(magic));
|
||||
assert_true(magic == stop_magic || magic == send_magic);
|
||||
|
||||
isc_nmhandle_attach(handle, &sendhandle);
|
||||
isc_refcount_increment0(&active_ssends);
|
||||
isc_nmhandle_setwritetimeout(sendhandle, T_IDLE);
|
||||
/* send multiple DNS messages at once */
|
||||
isc_buffer_usedregion(send_data, &send_messages);
|
||||
isc_nm_send(sendhandle, &send_messages, listen_send_cb, cbarg);
|
||||
unref:
|
||||
isc_refcount_decrement(&active_sreads);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
tlsdns_many_listen_accept_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
void *cbarg) {
|
||||
isc_nmhandle_t *readhandle = NULL;
|
||||
|
||||
UNUSED(cbarg);
|
||||
|
||||
F();
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
return (eresult);
|
||||
}
|
||||
|
||||
atomic_fetch_add(&saccepts, 1);
|
||||
|
||||
isc_refcount_increment0(&active_sreads);
|
||||
isc_nmhandle_attach(handle, &readhandle);
|
||||
isc_nm_read(handle, tlsdns_many_listen_read_cb, cbarg);
|
||||
|
||||
return (ISC_R_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
tlsdns_many_connect_read_cb(isc_nmhandle_t *handle, isc_result_t eresult,
|
||||
isc_region_t *region, void *cbarg) {
|
||||
isc_nmhandle_t *sendhandle = NULL;
|
||||
uint64_t magic = 0;
|
||||
|
||||
UNUSED(cbarg);
|
||||
|
||||
assert_non_null(handle);
|
||||
|
||||
F();
|
||||
|
||||
if (eresult != ISC_R_SUCCESS) {
|
||||
goto unref;
|
||||
}
|
||||
|
||||
assert_true(region->length >= sizeof(magic));
|
||||
|
||||
atomic_fetch_add(&creads, 1);
|
||||
|
||||
memmove(&magic, region->base, sizeof(magic));
|
||||
|
||||
assert_true(magic == stop_magic || magic == send_magic);
|
||||
|
||||
isc_refcount_increment0(&active_csends);
|
||||
isc_nmhandle_attach(handle, &sendhandle);
|
||||
isc_nmhandle_setwritetimeout(handle, T_IDLE);
|
||||
/*
|
||||
* At this point the read is completed, so we should stop that -
|
||||
* but the sending code will make a cycling through input
|
||||
* attempt. When not properly handled, this situation will cause
|
||||
* excessive reads.
|
||||
*/
|
||||
isc_nm_send(sendhandle, &send_msg, connect_send_cb, NULL);
|
||||
|
||||
unref:
|
||||
isc_refcount_decrement(&active_creads);
|
||||
isc_nmhandle_detach(&handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* A unit test *VERY* specific to #4487 - it would crash the unit test
|
||||
* suite without the related fix due to excessive/unexpected reads.
|
||||
*
|
||||
* The intention behind the test is to (needlessly ;-)) prove that the
|
||||
* author of the fix is not fantasising and excessive reads are
|
||||
* possible in principle. Also, it proves that there is more than one
|
||||
* way to do that.
|
||||
*
|
||||
* It is *not* reproducing the situation from the bug report 1:1, as
|
||||
* it is impossible to understand what exactly was going on with this
|
||||
* custom/proprietary server without having access to it (and even in
|
||||
* that case the bug was hard to reproduce to the point, where the
|
||||
* reporters considered it to be fixed for a while). There are far too
|
||||
* many things a play.
|
||||
*/
|
||||
ISC_RUN_TEST_IMPL(tlsdns_server_send_many_recv_one) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
uint8_t buf[512];
|
||||
isc_buffer_t server_send_buf = { 0 };
|
||||
|
||||
isc_buffer_init(&server_send_buf, buf, sizeof(buf));
|
||||
|
||||
/*
|
||||
* Prepare a buffer with three "DNS" messages which we will send
|
||||
* at once (our code does not normally do that do that).
|
||||
*/
|
||||
isc_buffer_putuint16(&server_send_buf, (uint16_t)send_msg.length);
|
||||
isc_buffer_putmem(&server_send_buf, send_msg.base, send_msg.length);
|
||||
isc_buffer_putuint16(&server_send_buf, (uint16_t)send_msg.length);
|
||||
isc_buffer_putmem(&server_send_buf, send_msg.base, send_msg.length);
|
||||
isc_buffer_putuint16(&server_send_buf, (uint16_t)send_msg.length);
|
||||
isc_buffer_putmem(&server_send_buf, send_msg.base, send_msg.length);
|
||||
|
||||
atomic_store(&nsends, 1);
|
||||
|
||||
result = isc_nm_listentls(
|
||||
listen_nm, &tcp_listen_addr, tlsdns_many_listen_accept_cb,
|
||||
&server_send_buf, 0, 0, NULL, tcp_listen_tlsctx, &listen_sock);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
connect_readcb = tlsdns_many_connect_read_cb;
|
||||
isc_refcount_increment0(&active_cconnects);
|
||||
isc_nm_tlsdnsconnect(connect_nm, &tcp_connect_addr, &tcp_listen_addr,
|
||||
connect_connect_cb, NULL, T_CONNECT, 0,
|
||||
tcp_connect_tlsctx, tcp_tlsctx_client_sess_cache);
|
||||
|
||||
WAIT_FOR_EQ(cconnects, 1);
|
||||
WAIT_FOR_LE(nsends, 0);
|
||||
WAIT_FOR_EQ(csends, 2);
|
||||
WAIT_FOR_EQ(sreads, 1);
|
||||
WAIT_FOR_EQ(ssends, 1);
|
||||
WAIT_FOR_EQ(creads, 1);
|
||||
|
||||
isc_nm_stoplistening(listen_sock);
|
||||
isc_nmsocket_close(&listen_sock);
|
||||
assert_null(listen_sock);
|
||||
isc__netmgr_shutdown(connect_nm);
|
||||
|
||||
X(cconnects);
|
||||
X(csends);
|
||||
X(creads);
|
||||
X(sreads);
|
||||
X(ssends);
|
||||
|
||||
atomic_assert_int_eq(cconnects, 1);
|
||||
atomic_assert_int_eq(csends, 2);
|
||||
atomic_assert_int_eq(creads, 1);
|
||||
atomic_assert_int_eq(sreads, 1);
|
||||
atomic_assert_int_eq(ssends, 1);
|
||||
}
|
||||
|
||||
ISC_RUN_TEST_IMPL(tlsdns_recv_two) {
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_nmsocket_t *listen_sock = NULL;
|
||||
@@ -3049,8 +2879,6 @@ ISC_TEST_ENTRY_CUSTOM(tls_half_recv_half_send_quota_sendback, setup_test,
|
||||
|
||||
/* TLSDNS */
|
||||
ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_one, setup_test, teardown_test)
|
||||
ISC_TEST_ENTRY_CUSTOM(tlsdns_server_send_many_recv_one, setup_test,
|
||||
teardown_test)
|
||||
ISC_TEST_ENTRY_CUSTOM(tlsdns_recv_two, setup_test, teardown_test)
|
||||
ISC_TEST_ENTRY_CUSTOM(tlsdns_noop, setup_test, teardown_test)
|
||||
ISC_TEST_ENTRY_CUSTOM(tlsdns_noresponse, setup_test, teardown_test)
|
||||
|
||||
Reference in New Issue
Block a user