mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-28 04:34:54 -04:00
Implement maximum global and idle time for incoming XFR
After the dns_xfrin was changed to use network manager, the maximum
global (max-transfer-time-in) and idle (max-transfer-idle-in) times for
incoming transfers were turned inoperational because of missing
implementation.
Restore this functionality by implementing the timers for the incoming
transfers.
(cherry picked from commit d2377f8e04)
This commit is contained in:
parent
cf6a8987b3
commit
fa2cb06c75
5 changed files with 99 additions and 2 deletions
|
|
@ -3450,6 +3450,12 @@ options apply to zone transfers.
|
|||
terminated. The default is 60 minutes (1 hour). The maximum value
|
||||
is 28 days (40320 minutes).
|
||||
|
||||
.. note:: The inbound zone transfers are also affected by
|
||||
``tcp-idle-timeout``, the ``max-transfer-idle-in`` will close the
|
||||
inbound zone transfer if there was no complete AXFR or no complete
|
||||
IXFR chunk. The ``tcp-idle-timeout`` will close the connection if
|
||||
there's no progress on the TCP level.
|
||||
|
||||
.. namedconf:statement:: max-transfer-time-out
|
||||
:tags: transfer
|
||||
:short: Specifies the number of minutes after which outbound zone transfers are terminated.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
***/
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/tls.h>
|
||||
|
||||
#include <dns/transport.h>
|
||||
|
|
|
|||
|
|
@ -1769,6 +1769,12 @@ dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr);
|
|||
* Get the tasmkgr object attached to 'zmgr'.
|
||||
*/
|
||||
|
||||
isc_timermgr_t *
|
||||
dns_zonemgr_gettimermgr(dns_zonemgr_t *zmgr);
|
||||
/*%
|
||||
* Get the timermgr object attached to 'zmgr'.
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value);
|
||||
/*%<
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
#include <isc/random.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/string.h> /* Required for HP/UX (and others?) */
|
||||
#include <isc/task.h>
|
||||
#include <isc/timer.h>
|
||||
#include <isc/util.h>
|
||||
|
||||
#include <dns/callbacks.h>
|
||||
|
|
@ -185,6 +187,9 @@ struct dns_xfrin_ctx {
|
|||
unsigned char *firstsoa_data;
|
||||
|
||||
isc_tlsctx_cache_t *tlsctx_cache;
|
||||
|
||||
isc_timer_t *max_time_timer;
|
||||
isc_timer_t *max_idle_timer;
|
||||
};
|
||||
|
||||
#define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
|
||||
|
|
@ -247,6 +252,10 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
|
|||
static void
|
||||
xfrin_destroy(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static void
|
||||
xfrin_timedout(struct isc_task *, struct isc_event *);
|
||||
static void
|
||||
xfrin_idledout(struct isc_task *, struct isc_event *);
|
||||
static void
|
||||
xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
|
||||
static isc_result_t
|
||||
|
|
@ -758,6 +767,28 @@ dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
|
|||
static void
|
||||
xfrin_cancelio(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static void
|
||||
xfrin_timedout(struct isc_task *task, struct isc_event *event) {
|
||||
UNUSED(task);
|
||||
|
||||
dns_xfrin_ctx_t *xfr = event->ev_arg;
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum transfer time exceeded");
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
static void
|
||||
xfrin_idledout(struct isc_task *task, struct isc_event *event) {
|
||||
UNUSED(task);
|
||||
|
||||
dns_xfrin_ctx_t *xfr = event->ev_arg;
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
||||
xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum idle time exceeded");
|
||||
isc_event_free(&event);
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
|
||||
REQUIRE(VALID_XFRIN(xfr));
|
||||
|
|
@ -833,6 +864,11 @@ xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
|
|||
if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false },
|
||||
true))
|
||||
{
|
||||
(void)isc_timer_reset(xfr->max_time_timer,
|
||||
isc_timertype_inactive, NULL, NULL, true);
|
||||
(void)isc_timer_reset(xfr->max_idle_timer,
|
||||
isc_timertype_inactive, NULL, NULL, true);
|
||||
|
||||
if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS)
|
||||
{
|
||||
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
|
||||
|
|
@ -866,6 +902,9 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
|
|||
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
|
||||
dns_xfrin_ctx_t **xfrp) {
|
||||
dns_xfrin_ctx_t *xfr = NULL;
|
||||
dns_zonemgr_t *zmgr = dns_zone_getmgr(zone);
|
||||
isc_timermgr_t *timermgr = dns_zonemgr_gettimermgr(zmgr);
|
||||
isc_task_t *ztask = NULL;
|
||||
|
||||
xfr = isc_mem_get(mctx, sizeof(*xfr));
|
||||
*xfr = (dns_xfrin_ctx_t){ .netmgr = netmgr,
|
||||
|
|
@ -876,7 +915,8 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
|
|||
.maxrecords = dns_zone_getmaxrecords(zone),
|
||||
.primaryaddr = *primaryaddr,
|
||||
.sourceaddr = *sourceaddr,
|
||||
.firstsoa = DNS_RDATA_INIT };
|
||||
.firstsoa = DNS_RDATA_INIT,
|
||||
.magic = XFRIN_MAGIC };
|
||||
|
||||
isc_mem_attach(mctx, &xfr->mctx);
|
||||
dns_zone_iattach(zone, &xfr->zone);
|
||||
|
|
@ -923,7 +963,12 @@ xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_nm_t *netmgr,
|
|||
|
||||
isc_tlsctx_cache_attach(tlsctx_cache, &xfr->tlsctx_cache);
|
||||
|
||||
xfr->magic = XFRIN_MAGIC;
|
||||
dns_zone_gettask(zone, &ztask);
|
||||
isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, ztask,
|
||||
xfrin_timedout, xfr, &xfr->max_time_timer);
|
||||
isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, ztask,
|
||||
xfrin_idledout, xfr, &xfr->max_idle_timer);
|
||||
isc_task_detach(&ztask); /* dns_zone_task() attaches to the task */
|
||||
|
||||
*xfrp = xfr;
|
||||
}
|
||||
|
|
@ -1146,6 +1191,8 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
|
|||
dns_transport_type_t transport_type = DNS_TRANSPORT_TCP;
|
||||
isc_tlsctx_t *tlsctx = NULL;
|
||||
isc_tlsctx_client_session_cache_t *sess_cache = NULL;
|
||||
isc_interval_t interval;
|
||||
isc_time_t next;
|
||||
|
||||
(void)isc_refcount_increment0(&xfr->connects);
|
||||
dns_xfrin_attach(xfr, &connect_xfr);
|
||||
|
|
@ -1154,6 +1201,20 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
|
|||
transport_type = dns_transport_get_type(xfr->transport);
|
||||
}
|
||||
|
||||
/* Set the maximum timer */
|
||||
isc_interval_set(&interval, dns_zone_getmaxxfrin(xfr->zone), 0);
|
||||
isc_time_nowplusinterval(&next, &interval);
|
||||
result = isc_timer_reset(xfr->max_time_timer, isc_timertype_once, &next,
|
||||
NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
/* Set the idle timer */
|
||||
isc_interval_set(&interval, dns_zone_getidlein(xfr->zone), 0);
|
||||
isc_time_nowplusinterval(&next, &interval);
|
||||
result = isc_timer_reset(xfr->max_idle_timer, isc_timertype_once, &next,
|
||||
NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
|
||||
/*
|
||||
* XXX: timeouts are hard-coded to 30 seconds; this needs to be
|
||||
* configurable.
|
||||
|
|
@ -1500,6 +1561,10 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
|
|||
result = ISC_R_SHUTTINGDOWN;
|
||||
}
|
||||
|
||||
/* Stop the idle timer */
|
||||
(void)isc_timer_reset(xfr->max_idle_timer, isc_timertype_inactive, NULL,
|
||||
NULL, true);
|
||||
|
||||
CHECK(result);
|
||||
|
||||
xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes", region->length);
|
||||
|
|
@ -1754,6 +1819,8 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
|
|||
}
|
||||
|
||||
atomic_store(&xfr->shuttingdown, true);
|
||||
(void)isc_timer_reset(xfr->max_time_timer,
|
||||
isc_timertype_inactive, NULL, NULL, true);
|
||||
xfr->shutdown_result = ISC_R_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1765,6 +1832,13 @@ xfrin_recv_done(isc_nmhandle_t *handle, isc_result_t result,
|
|||
dns_message_detach(&msg);
|
||||
isc_refcount_increment0(&xfr->recvs);
|
||||
isc_nm_read(xfr->handle, xfrin_recv_done, xfr);
|
||||
isc_time_t next;
|
||||
isc_interval_t interval;
|
||||
isc_interval_set(&interval, dns_zone_getidlein(xfr->zone), 0);
|
||||
isc_time_nowplusinterval(&next, &interval);
|
||||
result = isc_timer_reset(xfr->max_idle_timer,
|
||||
isc_timertype_once, &next, NULL, true);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1891,6 +1965,9 @@ xfrin_destroy(dns_xfrin_ctx_t *xfr) {
|
|||
isc_tlsctx_cache_detach(&xfr->tlsctx_cache);
|
||||
}
|
||||
|
||||
isc_timer_destroy(&xfr->max_idle_timer);
|
||||
isc_timer_destroy(&xfr->max_time_timer);
|
||||
|
||||
isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19215,6 +19215,13 @@ dns_zonemgr_gettaskmgr(dns_zonemgr_t *zmgr) {
|
|||
return (zmgr->taskmgr);
|
||||
}
|
||||
|
||||
isc_timermgr_t *
|
||||
dns_zonemgr_gettimermgr(dns_zonemgr_t *zmgr) {
|
||||
REQUIRE(DNS_ZONEMGR_VALID(zmgr));
|
||||
|
||||
return (zmgr->timermgr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to start a new incoming zone transfer to fill a quota
|
||||
* slot that was just vacated.
|
||||
|
|
|
|||
Loading…
Reference in a new issue