mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Implement the min-transfer-rate-in configuration option
This new option sets a minimum amount of transfer rate for
an incoming zone transfer that will abort a transfer, which
for some network related reasons run very slowly.
(cherry picked from commit 91ea156203)
This commit is contained in:
parent
9b3e1facf6
commit
e6b14365ad
10 changed files with 142 additions and 0 deletions
|
|
@ -237,6 +237,7 @@ options {\n\
|
|||
max-transfer-time-out 120;\n\
|
||||
min-refresh-time 300;\n\
|
||||
min-retry-time 500;\n\
|
||||
min-transfer-rate-in 10240 5;\n\
|
||||
multi-master no;\n\
|
||||
notify yes;\n\
|
||||
notify-delay 5;\n\
|
||||
|
|
|
|||
|
|
@ -1840,6 +1840,33 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
|||
}
|
||||
dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "min-transfer-rate-in", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||
uint32_t traffic_bytes =
|
||||
cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes"));
|
||||
uint32_t time_minutes =
|
||||
cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes"));
|
||||
if (traffic_bytes == 0) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"zone '%s': 'min-transfer-rate-in' bytes"
|
||||
"value can not be '0'",
|
||||
zname);
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
/* Max. 28 days (in minutes). */
|
||||
const unsigned int time_minutes_max = 28 * 24 * 60;
|
||||
if (time_minutes < 1 || time_minutes > time_minutes_max) {
|
||||
cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
|
||||
"zone '%s': 'min-transfer-rate-in' minutes"
|
||||
"value is out of range (1..%u)",
|
||||
zname, time_minutes_max);
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
dns_zone_setminxfrratein(mayberaw, traffic_bytes,
|
||||
transferinsecs ? time_minutes
|
||||
: time_minutes * 60);
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(maps, "max-transfer-time-in", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ zone <string> [ <class> ] {
|
|||
max-types-per-name <integer>;
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
multi-master <boolean>;
|
||||
notify ( explicit | master-only | primary-only | <boolean> );
|
||||
notify-delay <integer>;
|
||||
|
|
|
|||
|
|
@ -209,6 +209,7 @@ options {
|
|||
min-ncache-ttl <duration>;
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
minimal-any <boolean>;
|
||||
minimal-responses ( no-auth | no-auth-recursive | <boolean> );
|
||||
multi-master <boolean>;
|
||||
|
|
@ -496,6 +497,7 @@ view <string> [ <class> ] {
|
|||
min-ncache-ttl <duration>;
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
minimal-any <boolean>;
|
||||
minimal-responses ( no-auth | no-auth-recursive | <boolean> );
|
||||
multi-master <boolean>;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ zone <string> [ <class> ] {
|
|||
max-types-per-name <integer>;
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
multi-master <boolean>;
|
||||
notify ( explicit | master-only | primary-only | <boolean> );
|
||||
notify-delay <integer>;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ zone <string> [ <class> ] {
|
|||
max-types-per-name <integer>;
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
multi-master <boolean>;
|
||||
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
transfer-source ( <ipv4_address> | * );
|
||||
|
|
|
|||
|
|
@ -1264,6 +1264,36 @@ dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
|
|||
*\li DNS_R_SUCCESS
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds);
|
||||
/*%<
|
||||
* Set the minumum traffic rate (in bytes per seconds) that a zone transfer in
|
||||
* (AXFR/IXFR) of this zone will use before being aborted.
|
||||
*
|
||||
* Requires:
|
||||
* \li 'zone' to be valid initialised zone.
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
dns_zone_getminxfrratebytesin(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Returns the 'bytes' portion of the minimum traffic rate for the transfer in
|
||||
* for this zone.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be valid initialised zone.
|
||||
*/
|
||||
|
||||
uint32_t
|
||||
dns_zone_getminxfrratesecondsin(dns_zone_t *zone);
|
||||
/*%<
|
||||
* Returns the 'seconds' portion of the minimum traffic rate for the transfer in
|
||||
* for this zone.
|
||||
*
|
||||
* Requires:
|
||||
*\li 'zone' to be valid initialised zone.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -158,6 +158,7 @@ struct dns_xfrin {
|
|||
|
||||
unsigned int maxrecords; /*%< The maximum number of
|
||||
* records set for the zone */
|
||||
uint64_t nbytes_saved; /*%< For enforcing the minimum transfer rate */
|
||||
|
||||
dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
|
||||
isc_buffer_t *lasttsig; /*%< The last TSIG */
|
||||
|
|
@ -189,6 +190,7 @@ struct dns_xfrin {
|
|||
|
||||
isc_loop_t *loop;
|
||||
|
||||
isc_timer_t *min_rate_timer;
|
||||
isc_timer_t *max_time_timer;
|
||||
isc_timer_t *max_idle_timer;
|
||||
|
||||
|
|
@ -265,6 +267,8 @@ xfrin_timedout(void *);
|
|||
static void
|
||||
xfrin_idledout(void *);
|
||||
static void
|
||||
xfrin_minratecheck(void *);
|
||||
static void
|
||||
xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg);
|
||||
static isc_result_t
|
||||
render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
|
||||
|
|
@ -961,6 +965,24 @@ xfrin_idledout(void *xfr) {
|
|||
xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum idle time exceeded");
|
||||
}
|
||||
|
||||
static void
|
||||
xfrin_minratecheck(void *arg) {
|
||||
dns_xfrin_t *xfr = arg;
|
||||
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
const uint64_t nbytes = atomic_load_relaxed(&xfr->nbytes);
|
||||
const uint64_t min = dns_zone_getminxfrratebytesin(xfr->zone);
|
||||
|
||||
if (nbytes - xfr->nbytes_saved < min) {
|
||||
isc_timer_stop(xfr->min_rate_timer);
|
||||
xfrin_fail(xfr, ISC_R_TIMEDOUT,
|
||||
"minimum transfer rate reached");
|
||||
} else {
|
||||
xfr->nbytes_saved = nbytes;
|
||||
}
|
||||
}
|
||||
|
||||
isc_time_t
|
||||
dns_xfrin_getstarttime(dns_xfrin_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
|
@ -1309,6 +1331,15 @@ xfrin_start(dns_xfrin_t *xfr) {
|
|||
isc_interval_set(&interval, dns_zone_getidlein(xfr->zone), 0);
|
||||
isc_timer_start(xfr->max_idle_timer, isc_timertype_once, &interval);
|
||||
|
||||
/* Set the minimum transfer rate checking timer */
|
||||
if (xfr->min_rate_timer == NULL) {
|
||||
isc_timer_create(dns_zone_getloop(xfr->zone),
|
||||
xfrin_minratecheck, xfr, &xfr->min_rate_timer);
|
||||
}
|
||||
isc_interval_set(&interval, dns_zone_getminxfrratesecondsin(xfr->zone),
|
||||
0);
|
||||
isc_timer_start(xfr->min_rate_timer, isc_timertype_ticker, &interval);
|
||||
|
||||
/*
|
||||
* The connect has to be the last thing that is called before returning,
|
||||
* as it can end synchronously and destroy the xfr object.
|
||||
|
|
@ -1589,6 +1620,8 @@ xfrin_send_request(dns_xfrin_t *xfr) {
|
|||
atomic_store_relaxed(&xfr->nbytes, 0);
|
||||
atomic_store_relaxed(&xfr->start, isc_time_now());
|
||||
|
||||
xfr->nbytes_saved = 0;
|
||||
|
||||
msg->id = xfr->id;
|
||||
if (xfr->tsigctx != NULL) {
|
||||
dst_context_destroy(&xfr->tsigctx);
|
||||
|
|
@ -1707,6 +1740,10 @@ xfrin_end(dns_xfrin_t *xfr, isc_result_t result) {
|
|||
isc_timer_stop(xfr->max_idle_timer);
|
||||
isc_timer_destroy(&xfr->max_idle_timer);
|
||||
}
|
||||
if (xfr->min_rate_timer != NULL) {
|
||||
isc_timer_stop(xfr->min_rate_timer);
|
||||
isc_timer_destroy(&xfr->min_rate_timer);
|
||||
}
|
||||
|
||||
if (xfr->shutdown_result == ISC_R_UNSET) {
|
||||
xfr->shutdown_result = result;
|
||||
|
|
@ -1987,6 +2024,7 @@ xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) {
|
|||
case XFRST_AXFR_END:
|
||||
case XFRST_IXFR_END:
|
||||
/* We are at the end, cancel the timers and IO */
|
||||
isc_timer_stop(xfr->min_rate_timer);
|
||||
isc_timer_stop(xfr->max_idle_timer);
|
||||
isc_timer_stop(xfr->max_time_timer);
|
||||
xfrin_cancelio(xfr);
|
||||
|
|
@ -2152,6 +2190,7 @@ xfrin_destroy(dns_xfrin_t *xfr) {
|
|||
|
||||
INSIST(xfr->max_time_timer == NULL);
|
||||
INSIST(xfr->max_idle_timer == NULL);
|
||||
INSIST(xfr->min_rate_timer == NULL);
|
||||
|
||||
isc_loop_detach(&xfr->loop);
|
||||
|
||||
|
|
|
|||
|
|
@ -360,6 +360,8 @@ struct dns_zone {
|
|||
dns_request_t *request;
|
||||
dns_loadctx_t *loadctx;
|
||||
dns_dumpctx_t *dumpctx;
|
||||
uint32_t minxfrratebytesin;
|
||||
uint32_t minxfrratesecondsin;
|
||||
uint32_t maxxfrin;
|
||||
uint32_t maxxfrout;
|
||||
uint32_t idlein;
|
||||
|
|
@ -16003,6 +16005,28 @@ message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
|
|||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setminxfrratein(dns_zone_t *zone, uint32_t bytes, uint32_t seconds) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
zone->minxfrratebytesin = bytes;
|
||||
zone->minxfrratesecondsin = seconds;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dns_zone_getminxfrratebytesin(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
return zone->minxfrratebytesin;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
dns_zone_getminxfrratesecondsin(dns_zone_t *zone) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
||||
return zone->minxfrratesecondsin;
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
|
|
|
|||
|
|
@ -2367,6 +2367,20 @@ static cfg_clausedef_t dnssecpolicy_clauses[] = {
|
|||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* For min-transfer-rate-in.
|
||||
*/
|
||||
static cfg_tuplefielddef_t min_transfer_rate_fields[] = {
|
||||
{ "traffic_bytes", &cfg_type_uint32, 0 },
|
||||
{ "time_minutes", &cfg_type_uint32, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_type_t cfg_type_min_transfer_rate_in = {
|
||||
"min-transfer-rate-in", cfg_parse_tuple, cfg_print_tuple,
|
||||
cfg_doc_tuple, &cfg_rep_tuple, min_transfer_rate_fields
|
||||
};
|
||||
|
||||
/*%
|
||||
* Clauses that can be found in a 'zone' statement,
|
||||
* with defaults in the 'view' or 'options' statement.
|
||||
|
|
@ -2460,6 +2474,8 @@ static cfg_clausedef_t zone_clauses[] = {
|
|||
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||||
{ "max-retry-time", &cfg_type_uint32,
|
||||
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||||
{ "min-transfer-rate-in", &cfg_type_min_transfer_rate_in,
|
||||
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||||
{ "max-transfer-idle-in", &cfg_type_uint32,
|
||||
CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR | CFG_ZONE_STUB },
|
||||
{ "max-transfer-idle-out", &cfg_type_uint32,
|
||||
|
|
|
|||
Loading…
Reference in a new issue