new: usr: Add support for Generalized DNS Notifications

A new configuration option, ``notify-cfg CDS``, is added to enable Generalized DNS Notifications for CDS and/or CDNSKEY RRset changes, as specified in RFC 9859.

Closes #5611

Merge branch '5611-generalized-dns-notifications-rfc-9859' into 'main'

See merge request isc-projects/bind9!11315
This commit is contained in:
Matthijs Mekking 2025-12-19 14:46:23 +00:00
commit 9696da5f24
60 changed files with 1500 additions and 278 deletions

View file

@ -215,6 +215,7 @@ options {\n\
min-transfer-rate-in 10240 5;\n\
multi-master no;\n\
notify yes;\n\
notify-cds no;\n\
notify-defer 0;\n\
notify-delay 5;\n\
notify-to-soa no;\n\

View file

@ -1845,7 +1845,8 @@ dns64_reverse(dns_view_t *view, isc_mem_t *mctx, isc_netaddr_t *na,
dns_zone_setqueryonacl(zone, view->queryonacl);
}
dns_zone_setcheckdstype(zone, dns_checkdstype_no);
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_soa, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_cds, dns_notifytype_no);
dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
setquerystats(zone, mctx, dns_zonestat_none);
CHECK(dns_view_addzone(view, zone));
@ -3220,7 +3221,8 @@ create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
dns_zone_setoption(zone, DNS_ZONEOPT_ZONEVERSION, false);
dns_zone_setcheckdstype(zone, dns_checkdstype_no);
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_soa, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_cds, dns_notifytype_no);
dns_zone_setautomatic(zone, true);
if (view->queryacl != NULL) {
dns_zone_setqueryacl(zone, view->queryacl);
@ -3319,7 +3321,10 @@ create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view,
dns_zone_setstats(zone, named_g_server->zonestats);
dns_zone_setdbtype(zone, dbtypec, dbtype);
dns_zone_setcheckdstype(zone, dns_checkdstype_no);
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_soa,
dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_cds,
dns_notifytype_no);
dns_zone_setautomatic(zone, true);
dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
} else {
@ -6394,7 +6399,8 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
dns_acl_detach(&none);
dns_zone_setcheckdstype(zone, dns_checkdstype_no);
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_soa, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_cds, dns_notifytype_no);
dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
dns_zone_setjournalsize(zone, 0);

View file

@ -1209,9 +1209,20 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
notifytype = process_notifytype(notifytype, ztype, zname,
nodefault);
if (raw != NULL) {
dns_zone_setnotifytype(raw, dns_notifytype_no);
dns_zone_setnotifytype(raw, dns_rdatatype_soa,
dns_notifytype_no);
}
dns_zone_setnotifytype(zone, notifytype);
dns_zone_setnotifytype(zone, dns_rdatatype_soa, notifytype);
obj = NULL;
result = named_config_get(maps, "notify-cds", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
if (raw != NULL) {
dns_zone_setnotifytype(raw, dns_rdatatype_cds,
dns_notifytype_no);
}
dns_zone_setnotifytype(zone, dns_rdatatype_cds,
cfg_obj_asboolean(obj));
obj = NULL;
result = named_config_get(maps, "also-notify", &obj);
@ -1473,7 +1484,10 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
}
}
} else if (ztype == dns_zone_redirect) {
dns_zone_setnotifytype(zone, dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_soa,
dns_notifytype_no);
dns_zone_setnotifytype(zone, dns_rdatatype_cds,
dns_notifytype_no);
obj = NULL;
result = named_config_get(maps, "max-journal-size", &obj);

View file

@ -0,0 +1,22 @@
/*
* 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.
*/
/*
* Bad notify-cds type
*/
zone dummy {
type primary;
file "xxxx";
notify-cds explicit;
};

View file

@ -194,6 +194,7 @@ view "fourth" {
1.2.3.5;
};
dnssec-policy "test";
notify-cds no;
parental-source 10.10.10.10;
};
zone "dnssec-default" {
@ -203,6 +204,7 @@ view "fourth" {
"parents";
};
dnssec-policy "default";
notify-cds yes;
};
zone "dnssec-inherit" {
type primary;

View file

@ -0,0 +1,33 @@
/*
* 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.
*/
// NS1
options {
query-source address 10.53.0.1;
notify-source 10.53.0.1;
transfer-source 10.53.0.1;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.1; };
listen-on-v6 { none; };
recursion no;
notify yes;
};
zone "." {
type primary;
file "root.db.signed";
};
include "trusted.conf";

View file

@ -0,0 +1,30 @@
; 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
. IN SOA gson.nominum.com. a.root.servers.nil. (
2000042100 ; serial
600 ; refresh
600 ; retry
1200 ; expire
600 ; minimum
)
. NS a.root-servers.nil.
a.root-servers.nil. A 10.53.0.1
multisigner. NS ns2.multisigner.
ns2.multisigner. A 10.53.0.2
bad-dsync. NS ns2.bad-dsync.
ns2.bad-dsync. A 10.53.0.2
secondary. NS ns2.secondary.
ns2.secondary. A 10.53.0.2

View file

@ -0,0 +1,41 @@
#!/bin/sh -e
# 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.
# shellcheck source=conf.sh
. ../../conf.sh
set -e
zone=.
infile=root.db.in
zonefile=root.db
echo_i "ns1/setup.sh"
for tld in multisigner bad-dsync secondary; do
cp "../ns2/dsset-${tld}." .
done
KSK=$($KEYGEN -q -fk -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -b $DEFAULT_BITS $zone)
cat $infile $KSK.key $ZSK.key >$zonefile
$SIGNER -g -o $zone $zonefile >/dev/null 2>&1
# Configure the resolving server with a static key.
keyfile_to_static_ds "$KSK" >trusted.conf
cp trusted.conf ../ns2/trusted.conf
cp trusted.conf ../ns3/trusted.conf
cp trusted.conf ../ns4/trusted.conf
cp trusted.conf ../ns5/trusted.conf

View file

@ -0,0 +1,35 @@
; 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
$ORIGIN bad-dsync.
bad-dsync. IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
scanner A 10.53.0.2
model2 NS ns3
NS ns4
ns3.model2 A 10.53.0.3
ns4.model2 A 10.53.0.4
*._dsync DSYNC CDS NOTIFY @PORT@ scanner1
*._dsync DSYNC CDS NOTIFY @PORT@ scanner2

View file

@ -0,0 +1,34 @@
; 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
$ORIGIN multisigner.
multisigner. IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
scanner A 10.53.0.2
model2 NS ns3
NS ns4
ns3.model2 A 10.53.0.3
ns4.model2 A 10.53.0.4
*._dsync DSYNC CDS NOTIFY @PORT@ scanner

View file

@ -0,0 +1,58 @@
/*
* 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.
*/
// NS2
options {
query-source address 10.53.0.2;
notify-source 10.53.0.2;
transfer-source 10.53.0.2;
port @PORT@;
pid-file "named.pid";
listen-on { 10.53.0.2; };
listen-on-v6 { none; };
allow-transfer { any; };
allow-notify { 10.53.0.3; 10.53.0.4; };
dnssec-validation no;
};
key rndc_key {
secret "1234abcd8765";
algorithm @DEFAULT_HMAC@;
};
controls {
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
};
zone "multisigner" {
type primary;
file "multisigner.db.signed";
};
zone "bad-dsync" {
type primary;
file "bad-dsync.db.signed";
};
zone "secondary" {
type primary;
file "secondary.db.signed";
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -0,0 +1,36 @@
; 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
$ORIGIN secondary.
secondary. IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns2
ns2 A 10.53.0.2
scanner A 10.53.0.2
model2 NS ns3
NS ns4
ns3.model2 A 10.53.0.3
ns4.model2 A 10.53.0.4
model2._dsync DSYNC CSYNC NOTIFY @PORT@ scanner ; ignored, unknown rrtype
model2._dsync DSYNC DSYNC NOTIFY @PORT@ scanner ; ignored, bad rrtype
model2._dsync DSYNC CDS NOTIFY @PORT@ scanner

View file

@ -0,0 +1,39 @@
#!/bin/sh -e
# 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.
# shellcheck source=conf.sh
. ../../conf.sh
echo_i "ns2/setup.sh"
setup() {
zone="$1"
echo_i "setting up zone: $zone"
infile="${zone}.db.in"
zonefile="${zone}.db"
cp ../ns3/dsset-ns3-model2.$zone. .
cp ../ns4/dsset-ns4-model2.$zone. .
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 -f KSK $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zone)
$DSFROMKEY $KSK.key >dsset-ns2-${zone}.
cat $infile $KSK.key $ZSK.key >$zonefile
$SIGNER -g -o $zone $zonefile
# >/dev/null 2>&1
}
setup "multisigner"
setup "bad-dsync"
setup "secondary"

View file

@ -0,0 +1,26 @@
; 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
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns3
ns3 A 10.53.0.3
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View file

@ -24,9 +24,9 @@ options {
listen-on { 10.53.0.3; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
dnssec-validation yes;
notify-cds yes;
};
key rndc_key {
@ -46,10 +46,26 @@ zone "model2.multisigner." {
inline-signing no;
};
zone "model2.bad-dsync." {
type primary;
allow-update { any; };
file "model2.bad-dsync.db";
dnssec-policy model2;
inline-signing no;
};
zone "model2.secondary." {
type secondary;
primaries { 10.53.0.5; };
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
notify no;
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -23,20 +23,29 @@ zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns3-${zone}.
zone="model2.bad-dsync"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns3-${zone}.
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns3-${zone}.
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"

View file

@ -0,0 +1,26 @@
; 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
@ IN SOA mname1. . (
1 ; serial
20 ; refresh (20 seconds)
20 ; retry (20 seconds)
1814400 ; expire (3 weeks)
3600 ; minimum (1 hour)
)
NS ns4
ns4 A 10.53.0.4
a A 10.0.0.1
b A 10.0.0.2
c A 10.0.0.3

View file

@ -24,9 +24,9 @@ options {
listen-on { 10.53.0.4; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
dnssec-validation yes;
notify-cds yes;
};
key rndc_key {
@ -46,10 +46,26 @@ zone "model2.multisigner." {
inline-signing yes;
};
zone "model2.bad-dsync." {
type primary;
allow-update { any; };
file "model2.bad-dsync.db";
dnssec-policy model2;
inline-signing yes;
};
zone "model2.secondary." {
type secondary;
primaries { 10.53.0.5; };
file "model2.secondary.db";
dnssec-policy model2;
inline-signing yes;
notify no;
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -23,20 +23,29 @@ zsktimes="-P now -A now"
zone="model2.multisigner"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns4-${zone}.
zone="model2.bad-dsync"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns4-${zone}.
zone="model2.secondary"
echo_i "setting up zone: $zone"
zonefile="${zone}.db"
cp "../ns5/${zonefile}.in" "$zonefile"
KSK=$($KEYGEN -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone 2>keygen.out.$zone.1)
ZSK=$($KEYGEN -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone 2>keygen.out.$zone.2)
KSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -f KSK -L 3600 $ksktimes $zone)
ZSK=$($KEYGEN -q -a $DEFAULT_ALGORITHM -L 3600 $zsktimes $zone)
$SETTIME -s -g $O -k $O now -r $O now -d $O now "$KSK" >settime.out.$zone.1 2>&1
$SETTIME -s -g $O -k $O now -z $O now "$ZSK" >settime.out.$zone.2 2>&1
$DSFROMKEY $KSK.key >dsset-ns4-${zone}.
# ZSK will be added to the other provider with nsupdate.
cat "${ZSK}.key" | grep -v ";.*" >"${zone}.zsk"

View file

@ -24,7 +24,6 @@ options {
listen-on { 10.53.0.5; };
listen-on-v6 { none; };
allow-transfer { any; };
recursion no;
key-directory ".";
dnssec-validation no;
notify-delay 0;
@ -44,3 +43,10 @@ zone "model2.secondary." {
allow-update { any; };
file "model2.secondary.db";
};
zone "." {
type hint;
file "../../_common/root.hint";
};
include "trusted.conf";

View file

@ -16,6 +16,7 @@
set -e
# multi-signers
(
cd ns3
$SHELL setup.sh
@ -28,3 +29,13 @@ set -e
cd ns5
$SHELL setup.sh
)
# tld
(
cd ns2
$SHELL setup.sh
)
# root
(
cd ns1
$SHELL setup.sh
)

View file

@ -33,16 +33,20 @@ pytestmark = pytest.mark.extra_artifacts(
"secondary.cds.ns*",
"unused.*",
"verify.out.*",
"ns*/K*",
"ns*/db-*",
"ns*/keygen.out.*",
"ns*/*.db",
"ns*/*.db.in",
"ns*/*.jbk",
"ns*/*.jnl",
"ns*/*.zsk",
"ns*/*.signed",
"ns*/*.journal.out.*",
"ns*/*.signed",
"ns*/*.zsk",
"ns*/db-*",
"ns*/dsset-*",
"ns*/K*",
"ns*/keygen.out.*",
"ns*/managed-keys.bind*",
"ns*/settime.out.*",
"ns*/model2.secondary.db",
"ns*/trusted.conf",
]
)
@ -503,7 +507,7 @@ def check_remove_cds(
check_dnssec(server, zone, keys, expected)
def test_multisigner(ns3, ns4):
def test_multisigner(ns2, ns3, ns4):
zone = "model2.multisigner"
keyprops = [
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
@ -515,6 +519,23 @@ def test_multisigner(ns3, ns4):
isctest.kasp.wait_keymgr_done(ns3, zone)
isctest.kasp.wait_keymgr_done(ns4, zone)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN: dsyncfetch: send NOTIFY(CDS) query to scanner.multisigner"
)
with ns4.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.multisigner"
)
with ns2.watch_log_from_start() as watcher:
# Receiving NOTIFY(CDS) has not been implemented yet. Until
# then, notifies for child zones towards the parent result in
# not authoritative (unless child and parent are served by the
# same name server).
watcher.wait_for_line(f"received notify for zone '{zone}': NOTAUTH")
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
ksks3 = [k for k in keys3 if k.is_ksk()]
zsks3 = [k for k in keys3 if not k.is_ksk()]
@ -574,7 +595,26 @@ def test_multisigner(ns3, ns4):
check_no_dnssec_in_journal(ns4, zone)
def test_multisigner_secondary(ns3, ns4, ns5):
def test_multisigner_bad_dsync(ns3, ns4):
zone = "model2.bad-dsync"
# First make sure the zone is properly signed.
isctest.log.info(f"basic DNSSEC tests for {zone}")
isctest.kasp.wait_keymgr_done(ns3, zone)
isctest.kasp.wait_keymgr_done(ns4, zone)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN: dsyncfetch: multiple DSYNC records matching NOTIFY scheme and CDS RRtype, dropping response"
)
with ns4.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: multiple DSYNC records matching NOTIFY scheme and CDS RRtype, dropping response"
)
def test_multisigner_secondary(ns2, ns3, ns4, ns5):
zone = "model2.secondary"
keyprops = [
f"ksk 0 {ALGORITHM} {SIZE} goal:omnipresent dnskey:omnipresent krrsig:omnipresent ds:omnipresent",
@ -586,6 +626,24 @@ def test_multisigner_secondary(ns3, ns4, ns5):
isctest.kasp.wait_keymgr_done(ns3, zone)
isctest.kasp.wait_keymgr_done(ns4, zone)
for server in [ns3, ns4]:
with server.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.secondary"
)
msg = f"zone {zone}/IN (signed): dsyncfetch: DSYNC RRtype CSYNC not supported, ignoring"
assert msg in server.log
msg = f"zone {zone}/IN (signed): dsyncfetch: DSYNC RRtype DSYNC not supported, ignoring"
assert msg in server.log
with ns2.watch_log_from_start() as watcher:
# Receiving NOTIFY(CDS) has not been implemented yet. Until
# then, notifies for child zones towards the parent result in
# not authoritative (unless child and parent are served by the
# same name server).
watcher.wait_for_line(f"received notify for zone '{zone}': NOTAUTH")
keys3 = isctest.kasp.keydir_to_keylist(zone, ns3.identifier)
ksks3 = [k for k in keys3 if k.is_ksk()]
zsks3 = [k for k in keys3 if not k.is_ksk()]

View file

@ -45,7 +45,7 @@ for i in 1 2 3 4 5 6 7 8 9 10; do
$DIG +tcp -p "${PORT}" example @10.53.0.3 soa >dig.out.ns3.test$n || ret=1
grep "status: NOERROR" dig.out.ns3.test$n >/dev/null || ret=1
grep "flags:.* aa[ ;]" dig.out.ns3.test$n >/dev/null || ret=1
nr=$(grep -c 'x[0-9].*sending notify to' ns2/named.run)
nr=$(grep -c 'x[0-9].*sending notify(SOA) to' ns2/named.run)
[ "$nr" -ge 22 ] || ret=1
[ $ret = 0 ] && break
sleep 1
@ -64,7 +64,7 @@ digcomp dig.out.ns2.test$n dig.out.ns3.test$n || ret=1
test_end
test_start "checking startup notify rate limit"
awk '/x[0-9].*sending notify to/ {
awk '/x[0-9].*sending notify\(SOA\) to/ {
split($1, ts, "T");
split(ts[2], a, ":");
this = a[1] * 3600 + a[2] * 60 + a[3];
@ -101,7 +101,7 @@ test_end
# See [GL#4689]
test_start "checking server behaviour with invalid notify-source-v6 address"
grep "zone ./IN: sending notify to fd92:7065:b8e:fffe::a35:4#" ns1/named.run >/dev/null || ret=1
grep "zone ./IN: sending notify(SOA) to fd92:7065:b8e:fffe::a35:4#" ns1/named.run >/dev/null || ret=1
grep "dns_request_create: failed address not available" ns1/named.run >/dev/null || ret=1
test_end
@ -121,15 +121,15 @@ test_end
if $FEATURETEST --have-fips-dh; then
test_start "checking notify over TLS successful"
grep "zone tls-x1/IN: notify to 10.53.0.2#${TLSPORT} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x2/IN: notify to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x3/IN: notify to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x5/IN: notify to 10.53.0.2#${EXTRAPORT3} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x1/IN: notify(SOA) to 10.53.0.2#${TLSPORT} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x2/IN: notify(SOA) to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x3/IN: notify(SOA) to 10.53.0.2#${EXTRAPORT1} successful" ns3/named.run >/dev/null || ret=1
grep "zone tls-x5/IN: notify(SOA) to 10.53.0.2#${EXTRAPORT3} successful" ns3/named.run >/dev/null || ret=1
test_end
test_start "checking notify over TLS failed"
grep "zone tls-x4/IN: notify to 10.53.0.2#${EXTRAPORT1} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1
grep "zone tls-x6/IN: notify to 10.53.0.2#${EXTRAPORT4} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1
grep "zone tls-x4/IN: notify(SOA) to 10.53.0.2#${EXTRAPORT1} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1
grep "zone tls-x6/IN: notify(SOA) to 10.53.0.2#${EXTRAPORT4} failed: TLS peer certificate verification failed" ns3/named.run >/dev/null || ret=1
test_end
fi
@ -218,8 +218,8 @@ for i in 1 2 3 4 5 6 7 8 9; do
done
grep "test string" "$fnb" >/dev/null || ret=1
grep "test string" "$fnc" >/dev/null || ret=1
grep "sending notify to 10.53.0.5#[0-9]* : TSIG (b)" ns5/named.run >/dev/null || ret=1
grep "sending notify to 10.53.0.5#[0-9]* : TSIG (c)" ns5/named.run >/dev/null || ret=1
grep "sending notify(SOA) to 10.53.0.5#[0-9]* : TSIG (b)" ns5/named.run >/dev/null || ret=1
grep "sending notify(SOA) to 10.53.0.5#[0-9]* : TSIG (c)" ns5/named.run >/dev/null || ret=1
test_end
# notify messages were sent to unresponsive 10.53.0.6 during the tests

View file

@ -123,7 +123,7 @@ def test_nsec3_retransfer(servers, templates):
with ns3.watch_log_from_here() as watcher:
ns3.rndc(f"retransfer {zone}")
# When sending notifies, the zone should be up to date.
watcher.wait_for_line(f"zone {zone}/IN (signed): sending notify to 10.53.0.4")
watcher.wait_for_line(f"zone_needdump: zone {zone}/IN (signed): enter")
salt = perform_nsec3_tests(ns3, params)
assert prevsalt == salt

View file

@ -80,3 +80,5 @@ def test_algoroll_csk_initial(tld, ns3):
"nextev": TIMEDELTA["PT1H"],
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -138,6 +138,8 @@ def test_algoroll_csk_reconfig_step1(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -175,6 +177,8 @@ def test_algoroll_csk_reconfig_step2(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -244,6 +248,11 @@ def test_algoroll_csk_reconfig_step3(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -299,6 +308,8 @@ def test_algoroll_csk_reconfig_step4(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -333,6 +344,8 @@ def test_algoroll_csk_reconfig_step5(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -365,3 +378,5 @@ def test_algoroll_csk_reconfig_step6(tld, ns3, alg, size):
"verbose": True,
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -77,3 +77,5 @@ def test_algoroll_ksk_zsk_initial(tld, ns3):
"nextev": TIMEDELTA["PT1H"],
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -141,6 +141,8 @@ def test_algoroll_ksk_zsk_reconfig_step1(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -180,6 +182,8 @@ def test_algoroll_ksk_zsk_reconfig_step2(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -253,6 +257,11 @@ def test_algoroll_ksk_zsk_reconfig_step3(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -315,6 +324,8 @@ def test_algoroll_ksk_zsk_reconfig_step4(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -353,6 +364,8 @@ def test_algoroll_ksk_zsk_reconfig_step5(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -387,3 +400,5 @@ def test_algoroll_ksk_zsk_reconfig_step6(tld, ns3, alg, size):
"verbose": True,
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -123,6 +123,8 @@ def test_csk_roll1_step1(tld, ns3, alg, size):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -181,6 +183,8 @@ def test_csk_roll1_step2(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -268,6 +272,11 @@ def test_csk_roll1_step3(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -333,6 +342,8 @@ def test_csk_roll1_step4(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -366,6 +377,8 @@ def test_csk_roll1_step5(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -402,6 +415,8 @@ def test_csk_roll1_step6(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -461,3 +476,5 @@ def test_csk_roll1_step8(tld, alg, size, ns3):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -126,6 +126,8 @@ def test_csk_roll2_step1(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -184,6 +186,8 @@ def test_csk_roll2_step2(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -271,6 +275,11 @@ def test_csk_roll2_step3(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -310,6 +319,8 @@ def test_csk_roll2_step4(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -374,6 +385,8 @@ def test_csk_roll2_step5(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -409,6 +422,8 @@ def test_csk_roll2_step6(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -439,3 +454,5 @@ def test_csk_roll2_step7(tld, alg, size, ns3):
"verbose": True,
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -122,6 +122,8 @@ def test_rollover_enable_dnssec_step1(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -154,6 +156,8 @@ def test_rollover_enable_dnssec_step2(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -208,6 +212,11 @@ def test_rollover_enable_dnssec_step3(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -237,3 +246,5 @@ def test_rollover_enable_dnssec_step4(tld, alg, size, ns3):
"nextev": TIMEDELTA["PT1H"],
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -70,3 +70,5 @@ def test_going_insecure_initial(zone, ns3, alg, size):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -63,14 +63,14 @@ def after_servers_start(ns3, templates):
def test_going_insecure_reconfig_step1(zone, alg, size, ns3):
config = DEFAULT_CONFIG
policy = "insecure"
zone = f"step1.{zone}"
szone = f"step1.{zone}"
isctest.kasp.wait_keymgr_done(ns3, zone, reconfig=True)
isctest.kasp.wait_keymgr_done(ns3, szone, reconfig=True)
# Key goal states should be HIDDEN.
# The DS may be removed if we are going insecure.
step = {
"zone": zone,
"zone": szone,
"cdss": CDSS,
"keyprops": [
f"ksk 0 {alg} {size} goal:hidden dnskey:omnipresent krrsig:omnipresent ds:unretentive offset:{-DURATION['P10D']}",
@ -85,6 +85,16 @@ def test_going_insecure_reconfig_step1(zone, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
with ns3.watch_log_from_start() as watcher:
if "dynamic" in zone:
watcher.wait_for_line(
f"zone {szone}/IN: dsyncfetch: send NOTIFY(CDS) query to scanner.kasp"
)
else:
watcher.wait_for_line(
f"zone {szone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.kasp"
)
@pytest.mark.parametrize(
"zone",
@ -119,3 +129,5 @@ def test_going_insecure_reconfig_step2(zone, alg, size, ns3):
"check-keytimes": False,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -115,3 +115,8 @@ def test_rollover_ksk_three_is_a_crowd(alg, size, ns3):
expected[1].timing["Removed"] = now + KSK_IPUB + KSK_IRET
isctest.kasp.check_keytimes(keys, expected)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.kasp"
)

View file

@ -107,6 +107,8 @@ def test_ksk_doubleksk_step1(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -166,6 +168,8 @@ def test_ksk_doubleksk_step2(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -246,6 +250,11 @@ def test_ksk_doubleksk_step3(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
with ns3.watch_log_from_start() as watcher:
watcher.wait_for_line(
f"zone {zone}/IN (signed): dsyncfetch: send NOTIFY(CDS) query to scanner.{tld}"
)
@pytest.mark.parametrize(
"tld",
@ -312,6 +321,8 @@ def test_ksk_doubleksk_step4(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -349,6 +360,8 @@ def test_ksk_doubleksk_step5(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -376,3 +389,5 @@ def test_ksk_doubleksk_step6(tld, alg, size, ns3):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, KSK_CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -48,3 +48,5 @@ def test_lifetime_initial(zone, policy, lifetime, alg, size, ns3):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -63,3 +63,5 @@ def test_lifetime_reconfig(zone, policy, lifetime, alg, size, ns3):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -68,3 +68,5 @@ def test_straight2none_initial(zone, ns3, alg, size):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -77,3 +77,5 @@ def test_straight2none_reconfig(zone, ns3, alg, size):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, config, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -116,6 +116,8 @@ def test_zsk_prepub_step1(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -173,6 +175,8 @@ def test_zsk_prepub_step2(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -251,6 +255,8 @@ def test_zsk_prepub_step3(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
# Force full resign and check all signatures have been replaced.
with ns3.watch_log_from_here() as watcher:
ns3.rndc(f"sign {zone}")
@ -321,6 +327,8 @@ def test_zsk_prepub_step4(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -356,6 +364,8 @@ def test_zsk_prepub_step5(tld, alg, size, ns3):
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log
@pytest.mark.parametrize(
"tld",
@ -382,3 +392,5 @@ def test_zsk_prepub_step6(tld, alg, size, ns3):
"nextev": None,
}
isctest.kasp.check_rollover_step(ns3, CONFIG, policy, step)
assert f"zone {zone}/IN (signed): dsyncfetch" not in ns3.log

View file

@ -30,6 +30,7 @@ options {
allow-transfer { any; };
recursion yes;
dnssec-validation @dnssec_validation@;
notify-cds yes;
};
key rndc_key {

View file

@ -33,7 +33,7 @@ def wait_for_initial_xfrin(ns):
def wait_for_sending_notify(ns1, ns, key_name):
pattern = Re(
f"zone test/IN: sending notify to {ns.ip}#[0-9]+ : TSIG \\({key_name}\\)"
f"zone test/IN: sending notify\\(SOA\\) to {ns.ip}#[0-9]+ : TSIG \\({key_name}\\)"
)
with ns1.watch_log_from_start() as watcher:
watcher.wait_for_line(pattern)

View file

@ -2097,9 +2097,9 @@ Boolean Options
.. namedconf:statement:: notify
:tags: transfer
:short: Controls whether ``NOTIFY`` messages are sent on zone changes.
:short: Controls whether ``NOTIFY(SOA)`` messages are sent on zone changes.
If set to ``yes`` (the default), DNS NOTIFY messages are sent when a
If set to ``yes`` (the default), DNS NOTIFY(SOA) messages are sent when a
zone the server is authoritative for changes; see :ref:`using notify<notify>`.
The messages are sent to the servers listed in the zone's NS records
(except the primary server identified in the SOA MNAME field), and to
@ -2115,6 +2115,22 @@ Boolean Options
statement. It would only be necessary to turn off this option if it
caused secondary zones to crash.
.. namedconf:statement:: notify-cds
:tags: dnssec
:short: Controls whether ``NOTIFY(CDS)`` messages are sent on zone changes.
If set to ``yes``, DNS NOTIFY(CDS) messages are sent when the CDS or CDNSKEY
RRset changes. The messages are sent to the servers listed in the parent
zone's matching DSYNC records. A DSYNC record matches if the owner name under
`_dsync` subdomain of the parent zone corresponds to the given zone. For
example, the zone `child.example` should have a DSYNC record at
`child._dsync.example`. In addition, the RRtype field of the record must be
`CDS` and the Scheme field must be 1 (NOTIFY).
The default is ``no``. The :namedconf:ref:`notify-cds` option may also be
specified in the :any:`zone` statement, in which case it overrides the
``options notify-cds`` statement.
.. namedconf:statement:: notify-to-soa
:tags: transfer
:short: Controls whether the name servers in the NS RRset are checked against the SOA MNAME.

View file

@ -29,6 +29,7 @@ zone <string> [ <class> ] {
min-transfer-rate-in <integer> <integer>;
multi-master <boolean>;
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );

View file

@ -210,6 +210,7 @@ options {
no-case-compress { <address_match_element>; ... };
nocookie-udp-size <integer>;
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-rate <integer>;
@ -415,6 +416,7 @@ template <string> {
min-transfer-rate-in <integer> <integer>;
multi-master <boolean>;
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
@ -586,6 +588,7 @@ view <string> [ <class> ] {
no-case-compress { <address_match_element>; ... };
nocookie-udp-size <integer>;
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );

View file

@ -44,6 +44,7 @@ zone <string> [ <class> ] {
max-types-per-name <integer>;
max-zone-ttl ( unlimited | <duration> ); // deprecated
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );

View file

@ -41,6 +41,7 @@ zone <string> [ <class> ] {
min-transfer-rate-in <integer> <integer>;
multi-master <boolean>;
notify ( explicit | master-only | primary-only | <boolean> );
notify-cds <boolean>;
notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );

View file

@ -1825,8 +1825,9 @@ add_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
"CDS (%s) for key %s is now published", algbuf,
keystr);
addrdata(&cdsrdata, diff, origin, ttl, mctx);
return ISC_R_SUCCESS;
}
return ISC_R_SUCCESS;
return DNS_R_UNCHANGED;
}
static isc_result_t
@ -1850,8 +1851,9 @@ delete_cds(dns_dnsseckey_t *key, dns_rdata_t *keyrdata, const char *keystr,
"CDS (%s) for key %s is now deleted", algbuf,
keystr);
delrdata(&cdsrdata, diff, origin, cds->ttl, mctx);
return ISC_R_SUCCESS;
}
return ISC_R_SUCCESS;
return DNS_R_UNCHANGED;
}
isc_result_t
@ -1861,9 +1863,10 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
bool gencdnskey, dns_ttl_t ttl, dns_diff_t *diff,
isc_mem_t *mctx) {
unsigned char keybuf[DST_KEY_MAXSIZE];
isc_result_t result;
isc_result_t result = DNS_R_UNCHANGED;
dns_ttl_t cdsttl = ttl;
dns_ttl_t cdnskeyttl = ttl;
bool changed = false;
REQUIRE(digests != NULL);
REQUIRE(keys != NULL);
@ -1890,9 +1893,15 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
dst_key_format(key->key, keystr, sizeof(keystr));
ISC_LIST_FOREACH(*digests, alg, link) {
CHECK(add_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
alg->digest, cdsttl, diff, mctx));
result = add_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
alg->digest, cdsttl, diff,
mctx);
if (result == ISC_R_SUCCESS) {
changed = true;
} else if (result != DNS_R_UNCHANGED) {
goto cleanup;
}
}
if (gencdnskey &&
@ -1906,6 +1915,7 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
keystr);
addrdata(&cdnskeyrdata, diff, origin,
cdnskeyttl, mctx);
changed = true;
}
}
@ -1915,15 +1925,32 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
if (dns_rdataset_isassociated(cds)) {
/* Delete all possible CDS records */
delete_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
DNS_DSDIGEST_SHA1, diff, mctx);
delete_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
DNS_DSDIGEST_SHA256, diff, mctx);
delete_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
DNS_DSDIGEST_SHA384, diff, mctx);
for (dns_dsdigest_t digest = DNS_DSDIGEST_SHA1;
digest < DNS_DSDIGEST_TOTAL; digest++)
{
result = delete_cds(
key, &cdnskeyrdata,
(const char *)keystr, cds,
digest, diff, mctx);
switch (result) {
case ISC_R_SUCCESS:
changed = true;
break;
case DNS_R_UNCHANGED:
case ISC_R_NOTIMPLEMENTED:
/*
* Either the digest is not
* supported and we cannot
* construct the CDS for it, or
* the CDS with this digest is
* not present in the CDS RRset.
*/
break;
default:
goto cleanup;
}
}
}
if (dns_rdataset_isassociated(cdnskey)) {
@ -1936,6 +1963,7 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
keystr);
delrdata(&cdnskeyrdata, diff, origin,
cdnskey->ttl, mctx);
changed = true;
}
}
}
@ -1944,7 +1972,10 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
if (!dns_rdataset_isassociated(cds) &&
!dns_rdataset_isassociated(cdnskey))
{
return ISC_R_SUCCESS;
if (changed) {
return ISC_R_SUCCESS;
}
return DNS_R_UNCHANGED;
}
/*
@ -1961,12 +1992,30 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
&cdnskeyrdata));
if (dns_rdataset_isassociated(cds)) {
delete_cds(key, &cdnskeyrdata, (const char *)keystr,
cds, DNS_DSDIGEST_SHA1, diff, mctx);
delete_cds(key, &cdnskeyrdata, (const char *)keystr,
cds, DNS_DSDIGEST_SHA256, diff, mctx);
delete_cds(key, &cdnskeyrdata, (const char *)keystr,
cds, DNS_DSDIGEST_SHA384, diff, mctx);
for (dns_dsdigest_t digest = DNS_DSDIGEST_SHA1;
digest < DNS_DSDIGEST_TOTAL; digest++)
{
result = delete_cds(key, &cdnskeyrdata,
(const char *)keystr, cds,
digest, diff, mctx);
switch (result) {
case ISC_R_SUCCESS:
changed = true;
break;
case DNS_R_UNCHANGED:
case ISC_R_NOTIMPLEMENTED:
/*
* Either the digest is not
* supported and we cannot
* construct the CDS for it, or
* the CDS with this digest is
* not present in the CDS RRset.
*/
break;
default:
goto cleanup;
}
}
}
if (dns_rdataset_isassociated(cdnskey)) {
@ -1978,11 +2027,15 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
keystr);
delrdata(&cdnskeyrdata, diff, origin,
cdnskey->ttl, mctx);
changed = true;
}
}
}
result = ISC_R_SUCCESS;
if (changed) {
return ISC_R_SUCCESS;
}
return DNS_R_UNCHANGED;
cleanup:
return result;
@ -1999,6 +2052,7 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
dns_rdata_t cds_delete = DNS_RDATA_INIT;
dns_rdata_t cdnskey_delete = DNS_RDATA_INIT;
isc_region_t r;
bool changed = false;
r.base = keybuf;
r.length = sizeof(keybuf);
@ -2021,6 +2075,7 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
"published",
namebuf);
addrdata(&cds_delete, diff, origin, ttl, mctx);
changed = true;
}
} else {
if (dns_rdataset_isassociated(cds) && exists(cds, &cds_delete))
@ -2031,6 +2086,7 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
"deleted",
namebuf);
delrdata(&cds_delete, diff, origin, cds->ttl, mctx);
changed = true;
}
}
@ -2044,6 +2100,7 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
"published",
namebuf);
addrdata(&cdnskey_delete, diff, origin, ttl, mctx);
changed = true;
}
} else {
if (dns_rdataset_isassociated(cdnskey) &&
@ -2056,10 +2113,14 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
namebuf);
delrdata(&cdnskey_delete, diff, origin, cdnskey->ttl,
mctx);
changed = true;
}
}
return ISC_R_SUCCESS;
if (changed) {
return ISC_R_SUCCESS;
}
return DNS_R_UNCHANGED;
}
/*

View file

@ -403,6 +403,7 @@ dns_dnssec_syncupdate(dns_dnsseckeylist_t *keys, dns_dnsseckeylist_t *rmkeys,
*
* Returns:
*\li ISC_R_SUCCESS
*\li DNS_R_UNCHANGED - if the CDS and CDNSKEY sets have not changed
*\li Other values indicate error
*/
@ -421,6 +422,7 @@ dns_dnssec_syncdelete(dns_rdataset_t *cds, dns_rdataset_t *cdnskey,
*
* Returns:
*\li ISC_R_SUCCESS
*\li DNS_R_UNCHANGED - if the CDS and CDNSKEY sets have not changed
*\li Other values indicate error
*/

View file

@ -31,6 +31,9 @@
#define DNS_DSDIGEST_SHA256PRIVATE (7)
#define DNS_DSDIGEST_SHA384PRIVATE (8)
#define DNS_DSDIGEST_SM3PRIVATE (9)
#define DNS_DSDIGEST_TOTAL (10)
#else
#define DNS_DSDIGEST_TOTAL (7)
#endif
#define DNS_DSDIGEST_MAX (255)

View file

@ -29,6 +29,8 @@
struct dns_notifyctx {
dns_acl_t *notify_acl;
dns_rdatatype_t type;
isc_sockaddr_t notifyfrom;
dns_notifylist_t notifies;
@ -49,6 +51,8 @@ struct dns_notify {
dns_adbfind_t *find;
dns_request_t *request;
dns_name_t ns;
dns_rdatatype_t type;
in_port_t port;
isc_sockaddr_t src;
isc_sockaddr_t dst;
dns_tsigkey_t *key;
@ -64,7 +68,18 @@ typedef enum dns_notify_flags {
} dns_notify_flags_t;
void
dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp);
dns_notifyctx_init(dns_notifyctx_t *nctx, dns_rdatatype_t type);
/*%
* Initializes a notify context for the RRtype 'type'.
*
* Requires:
* 'nctx' is not NULL.
*
*/
void
dns_notify_create(isc_mem_t *mctx, dns_rdatatype_t type, in_port_t port,
unsigned int flags, dns_notify_t **notifyp);
/*%<
* Create a notify structure to maintain state.
*
@ -84,14 +99,15 @@ dns_notify_destroy(dns_notify_t *notify, bool zone_locked);
*/
bool
dns_notify_isqueued(dns_notifyctx_t *nctx, unsigned int flags, dns_name_t *name,
isc_sockaddr_t *addr, dns_tsigkey_t *key,
dns_transport_t *transport);
dns_notify_isqueued(dns_notifyctx_t *nctx, dns_rdatatype_t type, in_port_t port,
unsigned int flags, dns_name_t *name, isc_sockaddr_t *addr,
dns_tsigkey_t *key, dns_transport_t *transport);
/*%<
* Check if we already have a notify queued matching name, destination
* address, TSIG key, and transport. Will requeue on the normal notify
* ratelimiter if the notify was enqueued on the startup ratelimiter and
* this is not a startup notify.
* Check if we already have a notify queued matching name, type,
* destination address and port, TSIG key, and transport. Will
* requeue on the normal notify ratelimiter if the notify was
* enqueued on the startup ratelimiter and this is not a startup
* notify.
*
* Requires:
* 'nctx' is not NULL

View file

@ -682,6 +682,20 @@ dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
*\li 'count' to be the number of notifiees.
*/
void
dns_zone_setcdsendpoints(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count);
/*%<
* Set the list of servers to be notified when the zone changes
* its CDS/CDNSKEY RRset. To clear the list use 'count = 0'.
*
* Require:
*\li 'zone' to be a valid zone.
*\li 'addresses' to be non-NULL if count != 0.
*\li 'count' to be the number of notifiees.
*/
void
dns_zone_unload(dns_zone_t *zone);
/*%<
@ -1541,9 +1555,10 @@ dns_zone_getrequesttransporttype(dns_zone_t *zone);
*/
void
dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype);
dns_zone_setnotifytype(dns_zone_t *zone, dns_rdatatype_t type,
dns_notifytype_t notifytype);
/*%<
* Sets zone notify method to "notifytype"
* Sets zone notify(type) method to "notifytype"
*/
void

View file

@ -31,20 +31,22 @@
* the last position of the enum.
*/
typedef enum {
ZONEFETCHTYPE_DSYNC,
ZONEFETCHTYPE_KEY,
ZONEFETCHTYPE_NS,
ZONEFETCHTYPE_COUNT,
} dns_zonefetch_type_t;
typedef struct dns_keyfetch dns_keyfetch_t;
typedef struct dns_nsfetch dns_nsfetch_t;
typedef struct dns_zonefetch dns_zonefetch_t;
typedef struct dns_dsyncfetch dns_dsyncfetch_t;
typedef struct dns_keyfetch dns_keyfetch_t;
typedef struct dns_nsfetch dns_nsfetch_t;
typedef struct dns_zonefetch dns_zonefetch_t;
/*
* Fetch methods.
*/
typedef struct dns_zonefetch_methods {
void (*start_fetch)(dns_zonefetch_t *fetch);
isc_result_t (*start_fetch)(dns_zonefetch_t *fetch);
void (*continue_fetch)(dns_zonefetch_t *fetch);
void (*cancel_fetch)(dns_zonefetch_t *fetch);
void (*cleanup_fetch)(dns_zonefetch_t *fetch);
@ -55,6 +57,12 @@ typedef struct dns_zonefetch_methods {
/*
* Fetch contexts.
*/
struct dns_dsyncfetch {
dns_fixedname_t fname;
dns_name_t pname;
dns_name_t dsyncname;
};
struct dns_keyfetch {
dns_rdataset_t keydataset;
dns_db_t *db;
@ -65,8 +73,9 @@ struct dns_nsfetch {
};
typedef union dns_fetchdata {
dns_keyfetch_t keyfetch;
dns_nsfetch_t nsfetch;
dns_dsyncfetch_t dsyncfetch;
dns_keyfetch_t keyfetch;
dns_nsfetch_t nsfetch;
} dns_zonefetch_data_t;
struct dns_zonefetch {

View file

@ -40,7 +40,21 @@ notify_log(dns_notify_t *notify, int level, const char *fmt, ...) {
}
void
dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
dns_notifyctx_init(dns_notifyctx_t *nctx, dns_rdatatype_t type) {
dns_notifyctx_t ctx = {
.type = type,
.notifytype = dns_notifytype_yes,
.notifies = ISC_LIST_INITIALIZER,
};
isc_sockaddr_any(&ctx.notifysrc4);
isc_sockaddr_any6(&ctx.notifysrc6);
*nctx = ctx;
}
void
dns_notify_create(isc_mem_t *mctx, dns_rdatatype_t type, in_port_t port,
unsigned int flags, dns_notify_t **notifyp) {
dns_notify_t *notify;
REQUIRE(notifyp != NULL && *notifyp == NULL);
@ -48,6 +62,8 @@ dns_notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
notify = isc_mem_get(mctx, sizeof(*notify));
*notify = (dns_notify_t){
.flags = flags,
.port = port,
.type = type,
};
isc_mem_attach(mctx, &notify->mctx);
@ -71,7 +87,7 @@ dns_notify_destroy(dns_notify_t *notify, bool locked) {
dns__zone_lock(notify->zone);
}
REQUIRE(dns__zone_locked(notify->zone));
nctx = dns__zone_getnotifyctx(notify->zone);
nctx = dns__zone_getnotifyctx(notify->zone, notify->type);
if (ISC_LINK_LINKED(notify, link)) {
ISC_LIST_UNLINK(nctx->notifies, notify, link);
}
@ -113,11 +129,15 @@ notify_done(void *arg) {
isc_buffer_t buf;
char rcode[128];
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
REQUIRE(DNS_NOTIFY_VALID(notify));
isc_buffer_init(&buf, rcode, sizeof(rcode));
isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
dns_rdatatype_format(notify->type, typebuf, sizeof(typebuf));
/* WMM: This is changing the mctx from zone to notify. */
dns_message_create(notify->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE,
&message);
@ -136,32 +156,33 @@ notify_done(void *arg) {
result = dns_rcode_totext(message->rcode, &buf);
if (result == ISC_R_SUCCESS) {
notify_log(notify, ISC_LOG_DEBUG(3),
"notify response from %s: %.*s", addrbuf,
(int)buf.used, rcode);
"notify(%s) response from %s: %.*s", typebuf,
addrbuf, (int)buf.used, rcode);
}
fail:
dns_message_detach(&message);
if (result == ISC_R_SUCCESS) {
notify_log(notify, ISC_LOG_DEBUG(1), "notify to %s successful",
addrbuf);
notify_log(notify, ISC_LOG_DEBUG(1),
"notify(%s) to %s successful", typebuf, addrbuf);
} else if (result == ISC_R_SHUTTINGDOWN || result == ISC_R_CANCELED) {
/* just destroy the notify */
} else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
notify_log(notify, ISC_LOG_NOTICE,
"notify to %s failed: %s: retrying over TCP",
addrbuf, isc_result_totext(result));
"notify(%s) to %s failed: %s: retrying over TCP",
typebuf, addrbuf, isc_result_totext(result));
notify->flags |= DNS_NOTIFY_TCP;
dns_request_destroy(&notify->request);
dns_notify_queue(notify, notify->flags & DNS_NOTIFY_STARTUP);
return;
} else if (result == ISC_R_TIMEDOUT) {
notify_log(notify, ISC_LOG_WARNING,
"notify to %s failed: %s: retries exceeded", addrbuf,
isc_result_totext(result));
"notify(%s) to %s failed: %s: retries exceeded",
typebuf, addrbuf, isc_result_totext(result));
} else {
notify_log(notify, ISC_LOG_WARNING, "notify to %s failed: %s",
addrbuf, isc_result_totext(result));
notify_log(notify, ISC_LOG_WARNING,
"notify(%s) to %s failed: %s", typebuf, addrbuf,
isc_result_totext(result));
}
dns_notify_destroy(notify, false);
}
@ -308,6 +329,7 @@ notify_send_toaddr(void *arg) {
isc_netaddr_t dstip;
dns_tsigkey_t *key = NULL;
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
char typebuf[DNS_RDATATYPE_FORMATSIZE];
isc_sockaddr_t src;
unsigned int options;
bool have_notifysource = false;
@ -317,13 +339,16 @@ notify_send_toaddr(void *arg) {
dns__zone_lock(notify->zone);
notifyctx = dns__zone_getnotifyctx(notify->zone);
notifyctx = dns__zone_getnotifyctx(notify->zone, notify->type);
zmgr = dns_zone_getmgr(notify->zone);
view = dns_zone_getview(notify->zone);
loop = dns_zone_getloop(notify->zone);
result = dns_zone_getdb(notify->zone, &zonedb);
isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
dns_rdatatype_format(notify->type, typebuf, sizeof(typebuf));
if (!dns__zone_loaded(notify->zone) || notify->rlevent->canceled ||
dns__zone_exiting(notify->zone) || zmgr == NULL || view == NULL ||
view->requestmgr == NULL || loop == NULL || zonedb == NULL ||
@ -341,8 +366,8 @@ notify_send_toaddr(void *arg) {
IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr))
{
notify_log(notify, ISC_LOG_DEBUG(3),
"notify: ignoring IPv6 mapped IPV4 address: %s",
addrbuf);
"notify(%s): ignoring IPv6 mapped IPV4 address: %s",
typebuf, addrbuf);
result = ISC_R_CANCELED;
goto cleanup;
}
@ -358,9 +383,9 @@ notify_send_toaddr(void *arg) {
result = dns_view_getpeertsig(view, &dstip, &key);
if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
notify_log(notify, ISC_LOG_ERROR,
"NOTIFY to %s not sent. "
"NOTIFY(%s) to %s not sent. "
"Peer TSIG key lookup failure.",
addrbuf);
typebuf, addrbuf);
goto cleanup_message;
}
}
@ -370,11 +395,11 @@ notify_send_toaddr(void *arg) {
dns_name_format(key->name, namebuf, sizeof(namebuf));
notify_log(notify, ISC_LOG_INFO,
"sending notify to %s : TSIG (%s)", addrbuf,
namebuf);
"sending notify(%s) to %s : TSIG (%s)", typebuf,
addrbuf, namebuf);
} else {
notify_log(notify, ISC_LOG_INFO, "sending notify to %s",
addrbuf);
notify_log(notify, ISC_LOG_INFO, "sending notify(%s) to %s",
typebuf, addrbuf);
}
options = 0;
if (view->peers != NULL) {
@ -450,8 +475,8 @@ again:
goto cleanup_key;
} else if ((notify->flags & DNS_NOTIFY_TCP) == 0) {
notify_log(notify, ISC_LOG_NOTICE,
"notify to %s failed: %s: retrying over TCP",
addrbuf, isc_result_totext(result));
"notify(%s) to %s failed: %s: retrying over TCP",
typebuf, addrbuf, isc_result_totext(result));
notify->flags |= DNS_NOTIFY_TCP;
goto again;
}
@ -475,8 +500,9 @@ cleanup:
if (result != ISC_R_SUCCESS) {
isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
notify_log(notify, ISC_LOG_WARNING, "notify to %s failed: %s",
addrbuf, isc_result_totext(result));
notify_log(notify, ISC_LOG_WARNING,
"notify(%s) to %s failed: %s", typebuf, addrbuf,
isc_result_totext(result));
dns_notify_destroy(notify, false);
}
}
@ -512,9 +538,9 @@ dns_notify_queue(dns_notify_t *notify, bool startup) {
}
bool
dns_notify_isqueued(dns_notifyctx_t *nctx, unsigned int flags, dns_name_t *name,
isc_sockaddr_t *addr, dns_tsigkey_t *key,
dns_transport_t *transport) {
dns_notify_isqueued(dns_notifyctx_t *nctx, dns_rdatatype_t type, in_port_t port,
unsigned int flags, dns_name_t *name, isc_sockaddr_t *addr,
dns_tsigkey_t *key, dns_transport_t *transport) {
dns_notify_t *notify = NULL;
isc_result_t result;
@ -524,10 +550,14 @@ dns_notify_isqueued(dns_notifyctx_t *nctx, unsigned int flags, dns_name_t *name,
if (n->request != NULL) {
continue;
}
if (n->type != type) {
continue;
}
if ((name != NULL && dns_name_dynamic(&n->ns) &&
dns_name_equal(name, &n->ns)) ||
(addr != NULL && isc_sockaddr_equal(addr, &n->dst) &&
n->key == key && n->transport == transport))
n->port == port && n->key == key &&
n->transport == transport))
{
notify = n;
goto requeue;
@ -571,7 +601,7 @@ notify_isself(dns_notify_t *notify, isc_sockaddr_t *dst) {
dns_isselffunc_t isselffunc;
void *isselfarg = NULL;
notifyctx = dns__zone_getnotifyctx(notify->zone);
notifyctx = dns__zone_getnotifyctx(notify->zone, notify->type);
view = dns_zone_getview(notify->zone);
dns__zone_getisself(notify->zone, &isselffunc, &isselfarg);
if (view == NULL || isselffunc == NULL) {
@ -629,12 +659,12 @@ notify_send(dns_notify_t *notify) {
if (dns__zone_exiting(notify->zone)) {
return;
}
notifyctx = dns__zone_getnotifyctx(notify->zone);
notifyctx = dns__zone_getnotifyctx(notify->zone, notify->type);
ISC_LIST_FOREACH(notify->find->list, ai, publink) {
dst = ai->sockaddr;
if (dns_notify_isqueued(notifyctx, notify->flags, NULL, &dst,
NULL, NULL))
if (dns_notify_isqueued(notifyctx, notify->type, notify->port,
notify->flags, NULL, &dst, NULL, NULL))
{
continue;
}
@ -643,7 +673,8 @@ notify_send(dns_notify_t *notify) {
}
newnotify = NULL;
flags = notify->flags & DNS_NOTIFY_NOSOA;
dns_notify_create(notify->mctx, flags, &newnotify);
dns_notify_create(notify->mctx, notify->type, notify->port,
flags, &newnotify);
dns__zone_iattach_locked(notify->zone, &newnotify->zone);
ISC_LIST_APPEND(notifyctx->notifies, newnotify, link);
newnotify->dst = dst;
@ -718,7 +749,7 @@ dns_notify_find_address(dns_notify_t *notify) {
}
result = dns_adb_createfind(adb, loop, process_notify_adb_event, notify,
&notify->ns, options, 0, view->dstport, 0,
&notify->ns, options, 0, notify->port, 0,
NULL, NULL, NULL, &notify->find);
dns_adb_detach(&adb);

View file

@ -53,6 +53,7 @@
#include <dns/dbiterator.h>
#include <dns/dlz.h>
#include <dns/dnssec.h>
#include <dns/dsync.h>
#include <dns/journal.h>
#include <dns/kasp.h>
#include <dns/keydata.h>
@ -340,7 +341,10 @@ struct dns_zone {
uint32_t fetchcount[ZONEFETCHTYPE_COUNT];
dns_remote_t alsonotify;
dns_notifyctx_t notifyctx;
dns_notifyctx_t notifysoa;
dns_remote_t cds_endpoints;
dns_notifyctx_t notifycds;
isc_sockaddr_t parentalsrc4;
isc_sockaddr_t parentalsrc6;
@ -906,6 +910,8 @@ zone_maintenance(dns_zone_t *zone);
static void
zone_notify(dns_zone_t *zone, isc_time_t *now);
static void
zone_notifycds(dns_zone_t *zone);
static void
dump_done(void *arg, isc_result_t result);
static isc_result_t
zone_signwithkey(dns_zone_t *zone, dst_algorithm_t algorithm, uint16_t keyid,
@ -1085,13 +1091,6 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, isc_tid_t tid) {
dns_remote_t r = {
.magic = DNS_REMOTE_MAGIC,
};
dns_notifyctx_t nc = {
.notifytype = dns_notifytype_yes,
.notifies = ISC_LIST_INITIALIZER,
};
isc_sockaddr_any(&nc.notifysrc4);
isc_sockaddr_any6(&nc.notifysrc6);
zone->notifyctx = nc;
isc_mem_attach(mctx, &zone->mctx);
isc_mutex_init(&zone->lock);
@ -1108,9 +1107,13 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx, isc_tid_t tid) {
zone->primaries = r;
zone->parentals = r;
zone->alsonotify = r;
zone->cds_endpoints = r;
zone->defaultkasp = NULL;
ISC_LIST_INIT(zone->keyring);
dns_notifyctx_init(&zone->notifysoa, dns_rdatatype_soa);
dns_notifyctx_init(&zone->notifycds, dns_rdatatype_cds);
isc_stats_create(mctx, &zone->gluecachestats,
dns_gluecachestatscounter_max);
@ -1243,6 +1246,7 @@ dns__zone_free(dns_zone_t *zone) {
dns_zone_setparentals(zone, NULL, NULL, NULL, NULL, 0);
dns_zone_setprimaries(zone, NULL, NULL, NULL, NULL, 0);
dns_zone_setalsonotify(zone, NULL, NULL, NULL, NULL, 0);
dns_zone_setcdsendpoints(zone, NULL, NULL, NULL, NULL, 0);
zone->check_names = dns_severity_ignore;
if (zone->update_acl != NULL) {
@ -1251,8 +1255,11 @@ dns__zone_free(dns_zone_t *zone) {
if (zone->forward_acl != NULL) {
dns_acl_detach(&zone->forward_acl);
}
if (zone->notifyctx.notify_acl != NULL) {
dns_acl_detach(&zone->notifyctx.notify_acl);
if (zone->notifysoa.notify_acl != NULL) {
dns_acl_detach(&zone->notifysoa.notify_acl);
}
if (zone->notifycds.notify_acl != NULL) {
dns_acl_detach(&zone->notifycds.notify_acl);
}
if (zone->query_acl != NULL) {
dns_acl_detach(&zone->query_acl);
@ -1366,11 +1373,23 @@ dns_zone_getclass(dns_zone_t *zone) {
}
void
dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
dns_zone_setnotifytype(dns_zone_t *zone, dns_rdatatype_t type,
dns_notifytype_t notifytype) {
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
zone->notifyctx.notifytype = notifytype;
switch (type) {
case dns_rdatatype_soa:
zone->notifysoa.notifytype = notifytype;
break;
case dns_rdatatype_cds:
INSIST(notifytype == dns_notifytype_no ||
notifytype == dns_notifytype_yes);
zone->notifycds.notifytype = notifytype;
break;
default:
UNREACHABLE();
}
UNLOCK_ZONE(zone);
}
@ -6339,7 +6358,8 @@ dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone);
zone->notifyctx.notifysrc4 = *notifysrc;
zone->notifysoa.notifysrc4 = *notifysrc;
zone->notifycds.notifysrc4 = *notifysrc;
UNLOCK_ZONE(zone);
}
@ -6349,7 +6369,8 @@ dns_zone_getnotifysrc4(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone);
*notifysrc = zone->notifyctx.notifysrc4;
*notifysrc = zone->notifysoa.notifysrc4;
*notifysrc = zone->notifycds.notifysrc4;
UNLOCK_ZONE(zone);
}
@ -6359,7 +6380,8 @@ dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone);
zone->notifyctx.notifysrc6 = *notifysrc;
zone->notifysoa.notifysrc6 = *notifysrc;
zone->notifycds.notifysrc6 = *notifysrc;
UNLOCK_ZONE(zone);
}
@ -6369,47 +6391,8 @@ dns_zone_getnotifysrc6(dns_zone_t *zone, isc_sockaddr_t *notifysrc) {
REQUIRE(notifysrc != NULL);
LOCK_ZONE(zone);
*notifysrc = zone->notifyctx.notifysrc6;
UNLOCK_ZONE(zone);
}
void
dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
dns_remote_t remote;
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
remote.sources = sources;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
remote.addrcnt = count;
if (dns_remote_equal(&zone->alsonotify, &remote)) {
goto unlock;
}
dns_remote_clear(&zone->alsonotify);
/*
* If count == 0, don't allocate any space for servers to notify.
*/
if (count == 0) {
goto unlock;
}
/*
* Now set up the notify address and key lists.
*/
dns_remote_init(&zone->alsonotify, count, addresses, sources, keynames,
tlsnames, true, zone->mctx);
unlock:
*notifysrc = zone->notifysoa.notifysrc6;
*notifysrc = zone->notifycds.notifysrc6;
UNLOCK_ZONE(zone);
}
@ -6439,57 +6422,81 @@ report_no_active_addresses(dns_zone_t *zone, isc_sockaddr_t *addresses,
}
}
void
dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
dns_remote_t remote;
static void
setremote(dns_zone_t *zone, dns_remote_t *remote, const char *remotestr,
isc_sockaddr_t *addresses, isc_sockaddr_t *sources,
dns_name_t **keynames, dns_name_t **tlsnames, bool refresh,
bool report, uint32_t count) {
dns_remote_t newremote;
REQUIRE(DNS_ZONE_VALID(zone));
REQUIRE(DNS_REMOTE_VALID(remote));
LOCK_ZONE(zone);
newremote.magic = DNS_REMOTE_MAGIC;
newremote.addresses = addresses;
newremote.sources = sources;
newremote.keynames = keynames;
newremote.tlsnames = tlsnames;
newremote.addrcnt = count;
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
remote.sources = sources;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
remote.addrcnt = count;
if (dns_remote_equal(remote, &newremote)) {
return;
}
/*
* The refresh code assumes that 'primaries' wouldn't change under it.
* The refresh code assumes that 'servers' wouldn't change under it.
* If it will change then kill off any current refresh in progress
* and update the primaries info. If it won't change then we can just
* unlock and exit.
*/
if (!dns_remote_equal(&zone->primaries, &remote)) {
if (zone->request != NULL) {
dns_request_cancel(zone->request);
}
} else {
goto unlock;
if (zone->request != NULL && refresh) {
dns_request_cancel(zone->request);
}
dns_remote_clear(&zone->primaries);
dns_remote_clear(remote);
/*
* If count == 0, don't allocate any space for primaries.
* If count == 0, don't allocate any space for servers.
*/
if (count == 0) {
goto unlock;
return;
}
report_no_active_addresses(zone, addresses, count, "primaries");
/*
* Now set up the primaries and primary key lists.
* Now set up the address and key lists.
*/
dns_remote_init(&zone->primaries, count, addresses, sources, keynames,
tlsnames, true, zone->mctx);
if (report) {
report_no_active_addresses(zone, addresses, count, remotestr);
}
dns_remote_init(remote, count, addresses, sources, keynames, tlsnames,
true, zone->mctx);
}
void
dns_zone_setalsonotify(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
bool refresh = false;
bool report = false;
LOCK_ZONE(zone);
setremote(zone, &zone->alsonotify, "also-notify", addresses, sources,
keynames, tlsnames, refresh, report, count);
UNLOCK_ZONE(zone);
}
void
dns_zone_setprimaries(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
bool refresh = true;
bool report = true;
LOCK_ZONE(zone);
setremote(zone, &zone->primaries, "primaries", addresses, sources,
keynames, tlsnames, refresh, report, count);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOPRIMARIES);
unlock:
UNLOCK_ZONE(zone);
}
@ -6497,43 +6504,25 @@ void
dns_zone_setparentals(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
dns_remote_t remote;
REQUIRE(DNS_ZONE_VALID(zone));
bool refresh = false;
bool report = true;
LOCK_ZONE(zone);
setremote(zone, &zone->parentals, "parental-agents", addresses, sources,
keynames, tlsnames, refresh, report, count);
UNLOCK_ZONE(zone);
}
remote.magic = DNS_REMOTE_MAGIC;
remote.addresses = addresses;
remote.sources = sources;
remote.keynames = keynames;
remote.tlsnames = tlsnames;
remote.addrcnt = count;
void
dns_zone_setcdsendpoints(dns_zone_t *zone, isc_sockaddr_t *addresses,
isc_sockaddr_t *sources, dns_name_t **keynames,
dns_name_t **tlsnames, uint32_t count) {
bool refresh = false;
bool report = false;
if (dns_remote_equal(&zone->parentals, &remote)) {
goto unlock;
}
dns_remote_clear(&zone->parentals);
/*
* If count == 0, don't allocate any space for parentals.
*/
if (count == 0) {
goto unlock;
}
report_no_active_addresses(zone, addresses, count, "parental-agents");
/*
* Now set up the parentals and parental key lists.
*/
dns_remote_init(&zone->parentals, count, addresses, sources, keynames,
tlsnames, true, zone->mctx);
dns_zone_log(zone, ISC_LOG_NOTICE, "checkds: set %u parentals", count);
unlock:
LOCK_ZONE(zone);
setremote(zone, &zone->cds_endpoints, "cds-endpoints", addresses,
sources, keynames, tlsnames, refresh, report, count);
UNLOCK_ZONE(zone);
}
@ -10498,12 +10487,14 @@ revocable(dns_zonefetch_t *fetch, dns_rdata_keydata_t *keydata) {
/*
* Fetch DNSKEY records at the trust anchor name.
*/
static void
static isc_result_t
keyfetch_start(dns_zonefetch_t *fetch) {
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_KEY);
fetch->qname = dns_fixedname_name(&fetch->name);
fetch->qtype = dns_rdatatype_dnskey;
return ISC_R_SUCCESS;
}
static void
@ -10519,12 +10510,12 @@ keyfetch_cancel(dns_zonefetch_t *fetch) {
dns_zone_t *zone;
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_KEY);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
kfetch = &fetch->fetchdata.keyfetch;
zone = fetch->zone;
INSIST(LOCKED_ZONE(zone));
/*
* Error during a key fetch; cancel and retry in an hour.
*/
@ -10597,6 +10588,8 @@ keyfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) {
REQUIRE(fetch != NULL);
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_KEY);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
kfetch = &fetch->fetchdata.keyfetch;
zone = fetch->zone;
@ -12463,7 +12456,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
DNS_ZONEFLG_NEEDSTARTUPNOTIFY |
DNS_ZONEFLG_NOTIFYNODEFER |
DNS_ZONEFLG_NOTIFYDEFERRED);
notifytype = zone->notifyctx.notifytype;
notifytype = zone->notifysoa.notifytype;
DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
UNLOCK_ZONE(zone);
@ -12582,7 +12575,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
goto next;
}
if (dns_notify_isqueued(&zone->notifyctx, flags, NULL, &dst,
if (dns_notify_isqueued(&zone->notifysoa, dns_rdatatype_soa,
zone->view->dstport, flags, NULL, &dst,
key, transport))
{
if (key != NULL) {
@ -12594,7 +12588,8 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
goto next;
}
dns_notify_create(zone->mctx, flags, &notify);
dns_notify_create(zone->mctx, dns_rdatatype_soa,
zone->view->dstport, flags, &notify);
zone_iattach(zone, &notify->zone);
notify->src = src;
notify->dst = dst;
@ -12612,7 +12607,7 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
transport = NULL;
}
ISC_LIST_APPEND(zone->notifyctx.notifies, notify, link);
ISC_LIST_APPEND(zone->notifysoa.notifies, notify, link);
result = dns_notify_queue(notify, startup);
if (result != ISC_R_SUCCESS) {
dns_notify_destroy(notify, true);
@ -12671,17 +12666,19 @@ zone_notify(dns_zone_t *zone, isc_time_t *now) {
}
LOCK_ZONE(zone);
isqueued = dns_notify_isqueued(&zone->notifyctx, flags,
&ns.name, NULL, NULL, NULL);
isqueued = dns_notify_isqueued(
&zone->notifysoa, dns_rdatatype_soa,
zone->view->dstport, flags, &ns.name, NULL, NULL, NULL);
UNLOCK_ZONE(zone);
if (isqueued) {
continue;
}
dns_notify_create(zone->mctx, flags, &notify);
dns_notify_create(zone->mctx, dns_rdatatype_soa,
zone->view->dstport, flags, &notify);
dns_zone_iattach(zone, &notify->zone);
dns_name_dup(&ns.name, zone->mctx, &notify->ns);
LOCK_ZONE(zone);
ISC_LIST_APPEND(zone->notifyctx.notifies, notify, link);
ISC_LIST_APPEND(zone->notifysoa.notifies, notify, link);
UNLOCK_ZONE(zone);
dns_notify_find_address(notify);
}
@ -14609,7 +14606,8 @@ zone_shutdown(void *arg) {
checkds_cancel(zone);
dns_notify_cancel(&zone->notifyctx);
dns_notify_cancel(&zone->notifysoa);
dns_notify_cancel(&zone->notifycds);
forward_cancel(zone);
@ -15000,13 +14998,13 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
/*
* Accept notify requests from non primaries if they are on
* 'zone->notifyctx.notify_acl'.
* 'zone->notifysoa.notify_acl'.
*/
tsigkey = dns_message_gettsigkey(msg);
tsig = dns_tsigkey_identity(tsigkey);
if (i >= dns_remote_count(&zone->primaries) &&
zone->notifyctx.notify_acl != NULL &&
(dns_acl_match(&netaddr, tsig, zone->notifyctx.notify_acl,
zone->notifysoa.notify_acl != NULL &&
(dns_acl_match(&netaddr, tsig, zone->notifysoa.notify_acl,
zone->view->aclenv, &match,
NULL) == ISC_R_SUCCESS) &&
match > 0)
@ -15070,7 +15068,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
*/
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
zone->notifyctx.notifyfrom = *from;
zone->notifysoa.notifyfrom = *from;
UNLOCK_ZONE(zone);
if (have_serial) {
dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
@ -15096,7 +15094,7 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
"notify from %s: no serial", fromtext);
}
zone->notifyctx.notifyfrom = *from;
zone->notifysoa.notifyfrom = *from;
UNLOCK_ZONE(zone);
if (to != NULL) {
@ -15110,11 +15108,11 @@ void
dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
REQUIRE(DNS_ZONE_VALID(zone));
dns_zone_clearnotifyacl(zone);
LOCK_ZONE(zone);
if (zone->notifyctx.notify_acl != NULL) {
dns_acl_detach(&zone->notifyctx.notify_acl);
}
dns_acl_attach(acl, &zone->notifyctx.notify_acl);
dns_acl_attach(acl, &zone->notifysoa.notify_acl);
dns_acl_attach(acl, &zone->notifycds.notify_acl);
UNLOCK_ZONE(zone);
}
@ -15240,8 +15238,11 @@ dns_zone_clearnotifyacl(dns_zone_t *zone) {
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
if (zone->notifyctx.notify_acl != NULL) {
dns_acl_detach(&zone->notifyctx.notify_acl);
if (zone->notifysoa.notify_acl != NULL) {
dns_acl_detach(&zone->notifysoa.notify_acl);
}
if (zone->notifycds.notify_acl != NULL) {
dns_acl_detach(&zone->notifycds.notify_acl);
}
UNLOCK_ZONE(zone);
}
@ -15663,10 +15664,18 @@ dns_zone_getrdclass(dns_zone_t *zone) {
}
dns_notifyctx_t *
dns__zone_getnotifyctx(dns_zone_t *zone) {
dns__zone_getnotifyctx(dns_zone_t *zone, dns_rdatatype_t type) {
REQUIRE(DNS_ZONE_VALID(zone));
return &zone->notifyctx;
switch (type) {
case dns_rdatatype_soa:
return &zone->notifysoa;
case dns_rdatatype_cds:
return &zone->notifycds;
default:
UNREACHABLE();
}
return NULL;
}
void
@ -20856,7 +20865,7 @@ checkds_send(dns_zone_t *zone) {
/*
* Fetch NS records from parent zone.
*/
static void
static isc_result_t
nsfetch_start(dns_zonefetch_t *fetch) {
dns_nsfetch_t *nsfetch;
unsigned int nlabels = 1;
@ -20872,6 +20881,8 @@ nsfetch_start(dns_zonefetch_t *fetch) {
fetch->qtype = dns_rdatatype_ns;
fetch->qname = &nsfetch->pname;
return ISC_R_SUCCESS;
}
/*
@ -20910,11 +20921,11 @@ nsfetch_cancel(dns_zonefetch_t *fetch) {
dns_zone_t *zone;
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_NS);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
zone = fetch->zone;
INSIST(LOCKED_ZONE(zone));
zone->fetchcount[ZONEFETCHTYPE_NS]--;
}
@ -20929,7 +20940,7 @@ nsfetch_cleanup(dns_zonefetch_t *fetch) {
* agents.
*/
static isc_result_t
nsfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) {
nsfetch_checkds(dns_zonefetch_t *fetch, isc_result_t eresult) {
dns_nsfetch_t *nsfetch;
isc_result_t result = ISC_R_NOMORE;
dns_zone_t *zone = NULL;
@ -20939,6 +20950,8 @@ nsfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) {
REQUIRE(fetch != NULL);
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_NS);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
nsfetch = &fetch->fetchdata.nsfetch;
zone = fetch->zone;
@ -20949,7 +20962,7 @@ nsfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) {
dns_name_format(pname, pnamebuf, sizeof(pnamebuf));
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Returned from '%s' NS fetch in nsfetch_done(): %s",
"Returned from '%s' NS fetch in nsfetch_checkds(): %s",
pnamebuf, isc_result_totext(eresult));
if (eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NXRRSET) {
@ -21090,7 +21103,7 @@ zone_checkds(dns_zone_t *zone) {
.continue_fetch = nsfetch_continue,
.cancel_fetch = nsfetch_cancel,
.cleanup_fetch = nsfetch_cleanup,
.done_fetch = nsfetch_done,
.done_fetch = nsfetch_checkds,
},
};
isc_mem_attach(zone->mctx, &fetch->mctx);
@ -21115,6 +21128,374 @@ zone_checkds(dns_zone_t *zone) {
#endif /* ifdef ENABLE_AFL */
}
static isc_result_t
dsyncfetch_start(dns_zonefetch_t *fetch) {
dns_dsyncfetch_t *dsyncfetch;
dns_zone_t *zone;
dns_fixedname_t fndl, fnp;
dns_name_t *name, *dsyncname, *dsynclabel, *prefix;
unsigned int nlabels;
isc_result_t result;
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_DSYNC);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
dsyncfetch = &fetch->fetchdata.dsyncfetch;
zone = fetch->zone;
/*
* The dsync owner name is build up of <prefix>._dsync.<parent-name>.
* The prefix is the relative domain name of the child consisting of
* the labels under the zonecut.
*/
dsyncname = dns_fixedname_initname(&dsyncfetch->fname);
dsynclabel = dns_fixedname_initname(&fndl);
dns_name_fromstring(dsynclabel, "_dsync", NULL, 0, fetch->mctx);
result = dns_name_concatenate(dsynclabel, &dsyncfetch->pname,
dsyncname);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"dsyncfetch: failed to create parent DSYNC fetch "
"(parent part): %s",
isc_result_totext(result));
return result;
}
name = dns_fixedname_name(&fetch->name);
nlabels = dns_name_countlabels(&dsyncfetch->pname);
prefix = dns_fixedname_initname(&fnp);
dns_name_split(name, nlabels, prefix, NULL);
result = dns_name_concatenate(prefix, dsyncname, dsyncname);
if (result != ISC_R_SUCCESS) {
dnssec_log(zone, ISC_LOG_ERROR,
"dsyncfetch: failed to create parent DSYNC fetch "
"(child part): %s",
isc_result_totext(result));
return result;
}
dns_name_init(&dsyncfetch->dsyncname);
dns_name_clone(dsyncname, &dsyncfetch->dsyncname);
fetch->qtype = dns_rdatatype_dsync;
fetch->qname = &dsyncfetch->dsyncname;
return ISC_R_SUCCESS;
}
/*
* Retry an DSYNC RRset lookup.
*/
static void
dsyncfetch_continue(dns_zonefetch_t *fetch) {
dns_zone_t *zone;
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_DSYNC);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
zone = fetch->zone;
#ifdef ENABLE_AFL
if (!dns_fuzzing_resolver) {
#endif /* ifdef ENABLE_AFL */
LOCK_ZONE(zone);
zone->fetchcount[ZONEFETCHTYPE_DSYNC]++;
dns_zonefetch_reschedule(fetch);
if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Creating parent DSYNC fetch in "
"dsyncfetch_continue()");
}
UNLOCK_ZONE(zone);
#ifdef ENABLE_AFL
}
#endif /* ifdef ENABLE_AFL */
}
static void
dsyncfetch_cancel(dns_zonefetch_t *fetch) {
dns_zone_t *zone;
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_DSYNC);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
zone = fetch->zone;
zone->fetchcount[ZONEFETCHTYPE_DSYNC]--;
}
static void
dsyncfetch_cleanup(dns_zonefetch_t *fetch) {
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_DSYNC);
}
/*
* A DSYNC RRset has been fetched; scan the RRset and start sending
* NOTIFY(CDS) queries to them.
*/
static isc_result_t
dsyncfetch_done(dns_zonefetch_t *fetch, isc_result_t eresult) {
dns_dsyncfetch_t *dsyncfetch;
isc_result_t result = ISC_R_NOMORE;
dns_notify_t *notify = NULL;
dns_zone_t *zone = NULL;
dns_name_t *dsyncname = NULL;
char dsyncnamebuf[DNS_NAME_FORMATSIZE];
dns_rdataset_t *rrset = NULL;
REQUIRE(fetch != NULL);
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_DSYNC);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
dsyncfetch = &fetch->fetchdata.dsyncfetch;
zone = fetch->zone;
rrset = &fetch->rrset;
dsyncname = &dsyncfetch->dsyncname;
zone->fetchcount[ZONEFETCHTYPE_DSYNC]--;
dns_name_format(dsyncname, dsyncnamebuf, sizeof(dsyncnamebuf));
dns_zone_log(zone, ISC_LOG_DEBUG(3),
"dsyncfetch: Returned from '%s' DSYNC fetch in "
"dsyncfetch_done(): %s",
dsyncnamebuf, isc_result_totext(eresult));
result = dns_zonefetch_verify(fetch, eresult, dns_trust_secure);
if (result != ISC_R_SUCCESS) {
goto done;
}
UNLOCK_ZONE(zone);
/* Notify targets. */
dns_rdata_dsync_t dsync;
unsigned int count = 0;
for (result = dns_rdataset_first(rrset); result == ISC_R_SUCCESS;
result = dns_rdataset_next(rrset))
{
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(rrset, &rdata);
result = dns_rdata_tostruct(&rdata, &dsync, NULL);
RUNTIME_CHECK(result == ISC_R_SUCCESS);
dns_rdata_reset(&rdata);
if (dsync.scheme != DNS_DSYNCSCHEME_NOTIFY) {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"dsyncfetch: unsupported DSYNC scheme %u, "
"ignoring",
dsync.scheme);
continue;
}
if (dsync.type != dns_rdatatype_cds) {
char typebuf[DNS_RDATATYPE_FORMATSIZE];
dns_rdatatype_format(dsync.type, typebuf,
sizeof(typebuf));
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"dsyncfetch: DSYNC RRtype %s not "
"supported, ignoring",
result == ISC_R_SUCCESS ? typebuf
: "UNKNOWN");
continue;
}
count++;
if (count > 1) {
dns_zone_log(zone, ISC_LOG_WARNING,
"dsyncfetch: multiple DSYNC records "
"matching NOTIFY scheme and CDS RRtype, "
"dropping response");
result = DNS_R_INVALIDDSYNC;
break;
}
}
LOCK_ZONE(zone);
if (result == ISC_R_NOMORE) {
result = ISC_R_SUCCESS;
} else {
goto done;
}
bool isqueued = dns_notify_isqueued(&zone->notifycds, dns_rdatatype_cds,
dsync.port, 0, &dsync.target, NULL,
NULL, NULL);
UNLOCK_ZONE(zone);
if (!isqueued) {
dns_notify_create(zone->mctx, dns_rdatatype_cds, dsync.port,
DNS_NOTIFY_NOSOA, &notify);
if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
char tbuf[DNS_NAME_FORMATSIZE];
dns_name_format(&dsync.target, tbuf, sizeof(tbuf));
dns_zone_log(zone, ISC_LOG_DEBUG(3),
"dsyncfetch: send NOTIFY(CDS) query to %s",
tbuf);
}
dns_zone_iattach(zone, &notify->zone);
dns_name_dup(&dsync.target, zone->mctx, &notify->ns);
LOCK_ZONE(zone);
ISC_LIST_APPEND(zone->notifycds.notifies, notify, link);
UNLOCK_ZONE(zone);
dns_notify_find_address(notify);
}
LOCK_ZONE(zone);
done:
if (result != ISC_R_SUCCESS) {
dns_zone_log(zone, ISC_LOG_DEBUG(3),
"dsyncfetch: error processing DSYNC RRset: %s",
isc_result_totext(result));
}
return result;
}
/*
* An NS RRset has been fetched from the parent of a zone whose DSYNC RRset
* needs to be queried; scan the RRset and start resolving those queries.
*/
static isc_result_t
nsfetch_dsync(dns_zonefetch_t *fetch, isc_result_t eresult) {
dns_nsfetch_t *nsfetch;
isc_result_t result = ISC_R_NOMORE;
dns_zone_t *zone = NULL;
dns_name_t *pname = NULL;
char pnamebuf[DNS_NAME_FORMATSIZE];
REQUIRE(fetch != NULL);
REQUIRE(fetch->fetchtype == ZONEFETCHTYPE_NS);
REQUIRE(DNS_ZONE_VALID(fetch->zone));
REQUIRE(LOCKED_ZONE(fetch->zone));
nsfetch = &fetch->fetchdata.nsfetch;
zone = fetch->zone;
pname = &nsfetch->pname;
zone->fetchcount[ZONEFETCHTYPE_NS]--;
dns_name_format(pname, pnamebuf, sizeof(pnamebuf));
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Returned from '%s' NS fetch in nsfetch_dsync(): %s",
pnamebuf, isc_result_totext(eresult));
if (eresult == DNS_R_NCACHENXRRSET || eresult == DNS_R_NXRRSET) {
dnssec_log(zone, ISC_LOG_DEBUG(3),
"NODATA response for NS '%s', level up", pnamebuf);
return DNS_R_CONTINUE;
}
result = dns_zonefetch_verify(fetch, eresult, dns_trust_secure);
if (result != ISC_R_SUCCESS) {
goto done;
}
#ifdef ENABLE_AFL
if (!dns_fuzzing_resolver) {
#endif /* ifdef ENABLE_AFL */
dns_zonefetch_t *zfetch = NULL;
dns_dsyncfetch_t *dsyncfetch;
zfetch = isc_mem_get(zone->mctx, sizeof(dns_zonefetch_t));
*zfetch = (dns_zonefetch_t){
.zone = zone,
.options = DNS_FETCHOPT_UNSHARED |
DNS_FETCHOPT_NOCACHED,
.fetchtype = ZONEFETCHTYPE_DSYNC,
.fetchmethods =
(dns_zonefetch_methods_t){
.start_fetch = dsyncfetch_start,
.continue_fetch = dsyncfetch_continue,
.cancel_fetch = dsyncfetch_cancel,
.cleanup_fetch = dsyncfetch_cleanup,
.done_fetch = dsyncfetch_done,
},
};
isc_mem_attach(zone->mctx, &zfetch->mctx);
zone->fetchcount[ZONEFETCHTYPE_DSYNC]++;
dsyncfetch = &zfetch->fetchdata.dsyncfetch;
dns_name_init(&dsyncfetch->pname);
dns_name_clone(pname, &dsyncfetch->pname);
dns_zonefetch_schedule(zfetch, &zone->origin);
if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
dnssec_log(zone, ISC_LOG_DEBUG(3),
"Creating parent DSYNC fetch in "
"nsfetch_dsync()");
}
#ifdef ENABLE_AFL
}
#endif /* ifdef ENABLE_AFL */
done:
return result;
}
static void
zone_notifycds(dns_zone_t *zone) {
dns_notifytype_t notifytype = zone->notifycds.notifytype;
if (notifytype == dns_notifytype_no) {
return;
}
INSIST(notifytype == dns_notifytype_yes);
#ifdef ENABLE_AFL
if (!dns_fuzzing_resolver) {
#endif /* ifdef ENABLE_AFL */
dns_zonefetch_t *fetch = NULL;
dns_nsfetch_t *nsfetch;
fetch = isc_mem_get(zone->mctx, sizeof(dns_zonefetch_t));
*fetch = (dns_zonefetch_t){
.zone = zone,
.options = DNS_FETCHOPT_UNSHARED |
DNS_FETCHOPT_NOCACHED,
.fetchtype = ZONEFETCHTYPE_NS,
.fetchmethods =
(dns_zonefetch_methods_t){
.start_fetch = nsfetch_start,
.continue_fetch = nsfetch_continue,
.cancel_fetch = nsfetch_cancel,
.cleanup_fetch = nsfetch_cleanup,
.done_fetch = nsfetch_dsync,
},
};
isc_mem_attach(zone->mctx, &fetch->mctx);
LOCK_ZONE(zone);
zone->fetchcount[ZONEFETCHTYPE_NS]++;
nsfetch = &fetch->fetchdata.nsfetch;
dns_name_init(&nsfetch->pname);
dns_name_clone(&zone->origin, &nsfetch->pname);
dns_zonefetch_schedule(fetch, &zone->origin);
if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
dnssec_log(
zone, ISC_LOG_DEBUG(3),
"Creating parent NS fetch in zone_notifyds()");
}
UNLOCK_ZONE(zone);
#ifdef ENABLE_AFL
}
#endif /* ifdef ENABLE_AFL */
}
static void
update_ttl(dns_rdataset_t *rdataset, dns_name_t *name, dns_ttl_t ttl,
dns_diff_t *diff) {
@ -21260,6 +21641,7 @@ zone_rekey(dns_zone_t *zone) {
bool commit = false, newactive = false;
bool newalg = false;
bool fullsign;
bool notifycds = false;
bool offlineksk = false;
bool kasp_change = false;
uint8_t options = 0;
@ -21624,7 +22006,9 @@ zone_rekey(dns_zone_t *zone) {
result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
&cdnskeyset, now, &digests,
cdnskeypub, ttl, &diff, mctx);
if (result != ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) {
notifycds = true;
} else if (result != DNS_R_UNCHANGED) {
dnssec_log(zone, ISC_LOG_ERROR,
"zone_rekey:couldn't update CDS/CDNSKEY: %s",
isc_result_totext(result));
@ -21660,7 +22044,9 @@ zone_rekey(dns_zone_t *zone) {
result = dns_dnssec_syncdelete(
&cdsset, &cdnskeyset, &zone->origin, zone->rdclass, ttl,
&diff, mctx, cdsdel, cdnskeydel);
if (result != ISC_R_SUCCESS) {
if (result == ISC_R_SUCCESS) {
notifycds = true;
} else if (result != DNS_R_UNCHANGED) {
dnssec_log(zone, ISC_LOG_ERROR,
"zone_rekey:couldn't update CDS/CDNSKEY "
"DELETE records: %s",
@ -21975,6 +22361,13 @@ zone_rekey(dns_zone_t *zone) {
ISC_LIST_APPEND(zone->keyring, key, link);
}
/*
* If the CDS/CDNSKEY RRset has changed, send NOTIFY(CDS) to endpoints.
*/
if (notifycds) {
zone_notifycds(zone);
}
result = ISC_R_SUCCESS;
cleanup:

View file

@ -108,7 +108,7 @@ dns__zone_stats_increment(dns_zone_t *zone, isc_statscounter_t counter);
*/
dns_notifyctx_t *
dns__zone_getnotifyctx(dns_zone_t *zone);
dns__zone_getnotifyctx(dns_zone_t *zone, dns_rdatatype_t type);
/*%<
* Returns the notify context.
*

View file

@ -43,7 +43,10 @@ dns_zonefetch_run(void *arg) {
INSIST(view != NULL);
INSIST(loop != NULL);
fetch->fetchmethods.start_fetch(fetch);
result = fetch->fetchmethods.start_fetch(fetch);
if (result != ISC_R_SUCCESS) {
goto cancel;
}
result = dns_view_getresolver(view, &resolver);
if (result != ISC_R_SUCCESS) {

View file

@ -209,6 +209,7 @@ typedef enum isc_result {
DNS_R_NOSKRFILE,
DNS_R_NOSKRBUNDLE,
DNS_R_LOOPDETECTED,
DNS_R_INVALIDDSYNC,
DST_R_UNSUPPORTEDALG,
DST_R_CRYPTOFAILURE,

View file

@ -212,6 +212,7 @@ static const char *description[ISC_R_NRESULTS] = {
[DNS_R_NOSKRFILE] = "no SKR file",
[DNS_R_NOSKRBUNDLE] = "no available SKR bundle",
[DNS_R_LOOPDETECTED] = "fetch loop detected",
[DNS_R_INVALIDDSYNC] = "invalid DSYNC response",
[DST_R_UNSUPPORTEDALG] = "algorithm is unsupported",
[DST_R_CRYPTOFAILURE] = "crypto failure",
@ -445,6 +446,7 @@ static const char *identifier[ISC_R_NRESULTS] = {
[DNS_R_NOSKRFILE] = "DNS_R_NOSKRFILE",
[DNS_R_NOSKRBUNDLE] = "DNS_R_NOSKRBUNDLE",
[DNS_R_LOOPDETECTED] = "DNS_R_LOOPDETECTED",
[DNS_R_INVALIDDSYNC] = "DNS_R_INVALIDDSYNC",
[DST_R_UNSUPPORTEDALG] = "DST_R_UNSUPPORTEDALG",
[DST_R_CRYPTOFAILURE] = "DST_R_CRYPTOFAILURE",

View file

@ -2685,6 +2685,8 @@ static cfg_clausedef_t zone_clauses[] = {
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB, NULL },
{ "notify", &cfg_type_notifytype,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
{ "notify-cds", &cfg_type_boolean,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
{ "notify-defer", &cfg_type_uint32,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR, NULL },
{ "notify-delay", &cfg_type_uint32,