min-transfer-rate-in 10240 5;\n\
multi-master no;\n\
notify yes;\n\
+ notify-defer 0;\n\
notify-delay 5;\n\
notify-to-soa no;\n\
provide-zoneversion yes;\n\
return ISC_R_UNEXPECTEDEND;
}
- dns_zone_notify(zone);
+ dns_zone_notify(zone, true);
dns_zone_detach(&zone);
(void)putstr(text, msg);
(void)putnull(text);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
+ obj = NULL;
+ result = named_config_get(maps, "notify-defer", &obj);
+ INSIST(result == ISC_R_SUCCESS && obj != NULL);
+ dns_zone_setnotifydefer(zone, cfg_obj_asuint32(obj));
+
obj = NULL;
result = named_config_get(maps, "check-sibling", &obj);
INSIST(result == ISC_R_SUCCESS && obj != NULL);
/* catalog5 is missing on purpose */
+ zone "catalog6.example" {
+ type primary;
+ file "catalog6.example.db";
+ allow-transfer { any; };
+ allow-update { any; };
+ also-notify { 10.53.0.2; };
+ notify explicit;
+ notify-defer 5;
+ };
+
# No "version" property
zone "catalog-bad1.example" {
type primary;
#T2 zone "catalog5.example"
#T2 min-update-interval 1s
#T2 default-primaries { 10.53.0.1; };
+ zone "catalog6.example"
+ min-update-interval 1s
+ default-primaries { 10.53.0.1; };
zone "catalog-bad1.example"
default-masters { 10.53.0.1; }
min-update-interval 1s
primaries { 10.53.0.1; };
};
+ zone "catalog6.example" {
+ type secondary;
+ file "catalog6.example.db";
+ primaries { 10.53.0.1; };
+ };
+
# When the following zone configuration is enabled, "dom3.example" should
# already exist as a member of "catalog1.example", and named should be able
# to deal with that situation (see GL #3911). Make sure that this duplicate
primaries { 10.53.0.1; };
};
+ zone "catalog6.example" {
+ type secondary;
+ file "catalog6.example.db";
+ primaries { 10.53.0.1; };
+ };
+
# No "version" property
zone "catalog-bad1.example" {
type secondary;
cp -f ns3/catalog.example.db.in ns3/catalog2.example.db
cp -f ns1/catalog.example.db.in ns1/catalog3.example.db
cp -f ns1/catalog.example.db.in ns1/catalog4.example.db
+# catalog5 is missing on purpose
+cp -f ns1/catalog.example.db.in ns1/catalog6.example.db
cp -f ns1/catalog.example.db.in ns1/catalog-tls.example.db
cp -f ns4/catalog.example.db.in ns4/catalog-self.example.db
if [ $ret -ne 0 ]; then echo_i "failed"; fi
status=$((status + ret))
+##########################################################################
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n + 1))
+echo_i "Adding a domain dom20.example. to primary via RNDC ($n)"
+ret=0
+# enough initial content for IXFR response when TXT record is added below
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom20.example.db
+echo "@ 3600 IN NS invalid." >>ns1/dom20.example.db
+echo "foo 3600 IN TXT some content here" >>ns1/dom20.example.db
+echo "bar 3600 IN TXT some content here" >>ns1/dom20.example.db
+echo "xxx 3600 IN TXT some content here" >>ns1/dom20.example.db
+echo "yyy 3600 IN TXT some content here" >>ns1/dom20.example.db
+rndccmd 10.53.0.1 addzone dom20.example. in default '{ type primary; file "dom20.example.db"; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that dom20.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom20.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Adding domain dom20.example. to catalog6 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >>nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom20.zones.catalog6.example. 3600 IN PTR dom20.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+start=$(date +%s)
+wait_for_message ns2/named.run "catz: adding zone 'dom20.example' from catalog 'catalog6.example'" \
+ && wait_for_message ns2/named.run "transfer of 'dom20.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+end=$(date +%s)
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that 'notify-defer 5;' worked ($n)"
+ret=0
+elapsed=$(($end - $start))
+[ $elapsed -ge 5 ] || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that dom20.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom20.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+nextpart ns2/named.run >/dev/null
+
+n=$((n + 1))
+echo_i "Adding a domain dom21.example. to primary via RNDC ($n)"
+ret=0
+# enough initial content for IXFR response when TXT record is added below
+echo "@ 3600 IN SOA . . 1 3600 3600 3600 3600" >ns1/dom21.example.db
+echo "@ 3600 IN NS invalid." >>ns1/dom21.example.db
+echo "foo 3600 IN TXT some content here" >>ns1/dom21.example.db
+echo "bar 3600 IN TXT some content here" >>ns1/dom21.example.db
+echo "xxx 3600 IN TXT some content here" >>ns1/dom21.example.db
+echo "yyy 3600 IN TXT some content here" >>ns1/dom21.example.db
+rndccmd 10.53.0.1 addzone dom21.example. in default '{ type primary; file "dom21.example.db"; allow-update { any; }; notify explicit; also-notify { 10.53.0.2; }; };' || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that dom21.example. is now served by primary ($n)"
+ret=0
+wait_for_soa @10.53.0.1 dom21.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Adding domain dom21.example. to catalog6 zone ($n)"
+ret=0
+$NSUPDATE -d <<END >>nsupdate.out.test$n 2>&1 || ret=1
+ server 10.53.0.1 ${PORT}
+ update add dom21.zones.catalog6.example. 3600 IN PTR dom21.example.
+ send
+END
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "Sending 'rndc notify catalog6.example.' to primary via RNDC ($n)"
+ret=0
+rndccmd 10.53.0.1 notify catalog6.example. || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "waiting for secondary to sync up ($n)"
+ret=0
+start=$(date +%s)
+wait_for_message ns2/named.run "catz: adding zone 'dom21.example' from catalog 'catalog6.example'" \
+ && wait_for_message ns2/named.run "transfer of 'dom21.example/IN/default' from 10.53.0.1#${PORT}: Transfer status: success" || ret=1
+end=$(date +%s)
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that 'notify-defer 5;' was ignored because of implicit notify command ($n)"
+ret=0
+elapsed=$(($end - $start))
+[ $elapsed -lt 5 ] || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
+n=$((n + 1))
+echo_i "checking that dom21.example. is served by secondary ($n)"
+ret=0
+wait_for_soa @10.53.0.2 dom21.example. dig.out.test$n || ret=1
+if [ $ret -ne 0 ]; then echo_i "failed"; fi
+status=$((status + ret))
+
##########################################################################
echo_i "exit status: $status"
[ $status -eq 0 ] || exit 1
dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", serial);
if (zone_dynamic) {
- dns_zone_notify(zone);
+ dns_zone_notify(zone, false);
}
cleanup:
when resolving a client query, before terminating the query to avoid a
CNAME loop. Valid values are 1 to 255. The default is 11.
+.. namedconf:statement:: notify-defer
+ :tags: transfer, zone
+ :short: Sets the defer time (in seconds) before sending NOTIFY messages for a zone.
+
+ This sets the delay, in seconds, to wait before sending a set of NOTIFY
+ messages for a zone. Whenever a NOTIFY message is ready to be sent, sending
+ will be deferred for this duration. This can be useful, for example, when
+ for some operation needs a catalog zone is updated with new member zones
+ before these member zones are actually ready to be tranferred. The delay can
+ be tuned for the catalog zone to an amount of time after which the member
+ zones are usually known to become ready. The default is 0 seconds.
+
+ .. warning::
+ This option is not to be confused with the :any:`notify-delay` option.
+
+ .. note::
+ An implicit :option:`rndc notify` command for a zone overrides the
+ effects of this option.
+
.. namedconf:statement:: notify-delay
:tags: transfer, zone
:short: Sets the delay (in seconds) between sending sets of NOTIFY messages for a zone.
The overall rate at which NOTIFY messages are sent for all zones is
controlled by :any:`notify-rate`.
+ .. warning::
+ This option is not to be confused with the :any:`notify-defer` option.
+
.. namedconf:statement:: max-rsa-exponent-size
:tags: dnssec, query
:short: Sets the maximum RSA exponent size (in bits) when validating.
min-transfer-rate-in <integer> <integer>;
multi-master <boolean>;
notify ( explicit | master-only | primary-only | <boolean> );
+ notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
notify-source-v6 ( <ipv6_address> | * );
no-case-compress { <address_match_element>; ... };
nocookie-udp-size <integer>;
notify ( explicit | master-only | primary-only | <boolean> );
+ notify-defer <integer>;
notify-delay <integer>;
notify-rate <integer>;
notify-source ( <ipv4_address> | * );
no-case-compress { <address_match_element>; ... };
nocookie-udp-size <integer>;
notify ( explicit | master-only | primary-only | <boolean> );
+ notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
notify-source-v6 ( <ipv6_address> | * );
max-types-per-name <integer>;
max-zone-ttl ( unlimited | <duration> ); // deprecated
notify ( explicit | master-only | primary-only | <boolean> );
+ notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
notify-source-v6 ( <ipv6_address> | * );
min-transfer-rate-in <integer> <integer>;
multi-master <boolean>;
notify ( explicit | master-only | primary-only | <boolean> );
+ notify-defer <integer>;
notify-delay <integer>;
notify-source ( <ipv4_address> | * );
notify-source-v6 ( <ipv6_address> | * );
*/
void
-dns_zone_notify(dns_zone_t *zone);
+dns_zone_notify(dns_zone_t *zone, bool nodefer);
/*%<
- * Generate notify events for this zone.
+ * Generate notify events for this zone. If 'nodefer' is true, the
+ * 'notify-defer' configuration option is ingored.
*
* Requires:
*\li 'zone' to be a valid zone.
* 'zone' to be a valid zone.
*/
+void
+dns_zone_setnotifydefer(dns_zone_t *zone, uint32_t defer);
+/*%<
+ * Set the wait/defer time (in seconds) before notify messages are sent when
+ * they are ready.
+ *
+ * Requires:
+ * 'zone' to be valid.
+ */
+
void
dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay);
/*%<
dns_stats_t *rcvquerystats;
dns_stats_t *dnssecsignstats;
uint32_t notifydelay;
+ uint32_t notifydefer;
dns_isselffunc_t isself;
void *isselfarg;
* notify due to the zone
* just being loaded for
* the first time. */
- DNS_ZONEFLG_FIRSTREFRESH = 0x100000000U, /*%< First refresh pending */
+ DNS_ZONEFLG_NOTIFYNODEFER = 0x100000000U, /*%< ignore the
+ * notify-defer option. */
+ DNS_ZONEFLG_NOTIFYDEFERRED = 0x200000000U, /*%< notify was deferred
+ * according to the
+ * notify-defer option. */
+ DNS_ZONEFLG_FIRSTREFRESH = 0x400000000U, /*%< First refresh pending */
DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
} dns_zoneflg_t;
} \
} while (0)
+#define DNS_ZONE_TIME_SUBTRACT(a, b, c) \
+ do { \
+ isc_interval_t _i; \
+ isc_interval_set(&_i, (b), 0); \
+ if (isc_time_subtract((a), &_i, (c)) != ISC_R_SUCCESS) { \
+ dns_zone_log(zone, ISC_LOG_WARNING, \
+ "epoch approaching: upgrade required: " \
+ "isc_time_subtract() failed"); \
+ isc_interval_set(&_i, (b) / 2, 0); \
+ (void)isc_time_subtract((a), &_i, (c)); \
+ } \
+ } while (0)
+
typedef struct nsec3param nsec3param_t;
struct nsec3param {
dns_rdata_nsec3param_t rdata;
* primaries after.
*/
LOCK_ZONE(zone);
+ if (zone->notifydefer != 0 &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER) &&
+ !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED))
+ {
+ if (isc_time_compare(&now, &zone->notifytime) > 0) {
+ zone->notifytime = now;
+ }
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
+ DNS_ZONE_TIME_ADD(&zone->notifytime, zone->notifydefer,
+ &zone->notifytime);
+ }
notify = (zone->type == dns_zone_secondary ||
zone->type == dns_zone_mirror) &&
(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
}
void
-dns_zone_notify(dns_zone_t *zone) {
+dns_zone_notify(dns_zone_t *zone, bool nodefer) {
isc_time_t now;
REQUIRE(DNS_ZONE_VALID(zone));
LOCK_ZONE(zone);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
-
+ if (nodefer) {
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED)) {
+ /*
+ * We have previously deferred the notify, but we have a
+ * new request not to defer it. Reverse the deferring
+ * operation.
+ */
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOTIFYDEFERRED);
+ DNS_ZONE_TIME_SUBTRACT(&zone->notifytime,
+ zone->notifydefer,
+ &zone->notifytime);
+ }
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYNODEFER);
+ }
now = isc_time_now();
zone_settimer(zone, &now);
UNLOCK_ZONE(zone);
LOCK_ZONE(zone);
startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
- DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
- DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY |
+ DNS_ZONEFLG_NEEDSTARTUPNOTIFY |
+ DNS_ZONEFLG_NOTIFYNODEFER |
+ DNS_ZONEFLG_NOTIFYDEFERRED);
notifytype = zone->notifytype;
DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
UNLOCK_ZONE(zone);
UNLOCK_ZONE(zone);
}
+void
+dns_zone_setnotifydefer(dns_zone_t *zone, uint32_t defer) {
+ REQUIRE(DNS_ZONE_VALID(zone));
+
+ LOCK_ZONE(zone);
+ zone->notifydefer = defer;
+ UNLOCK_ZONE(zone);
+}
+
void
dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
REQUIRE(DNS_ZONE_VALID(zone));
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
{ "notify", &cfg_type_notifytype,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
+ { "notify-defer", &cfg_type_uint32,
+ CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ "notify-delay", &cfg_type_uint32,
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR },
{ "notify-source", &cfg_type_sockaddr4wild,
/*
* Notify secondaries of the change we just made.
*/
- dns_zone_notify(zone);
+ dns_zone_notify(zone, false);
} else {
update_log(client, zone, LOGLEVEL_DEBUG, "redundant request");
dns_db_closeversion(db, &ver, true);