2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

Implemented the 'transfers' clause of the 'server' statement

> and the 'transfers-per-ns' option.
This commit is contained in:
Andreas Gustafsson
2000-02-25 00:52:11 +00:00
parent 2bc0dee981
commit e01ecff4b1
7 changed files with 173 additions and 24 deletions

View File

@@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: xfrin.c,v 1.49 2000/02/24 21:43:11 gson Exp $ */
/* $Id: xfrin.c,v 1.50 2000/02/25 00:50:36 gson Exp $ */
#include <config.h>
@@ -34,6 +34,7 @@
#include <isc/timer.h>
#include <isc/net.h>
#include <isc/print.h>
#include <isc/util.h>
#include <dns/db.h>
#include <dns/dbiterator.h>
@@ -160,6 +161,9 @@ struct dns_xfrin_ctx {
dns_journal_t *journal;
} ixfr;
ISC_LINK(dns_xfrin_ctx_t) link;
dns_xfrinlist_t *transferlist;
};
/**************************************************************************/
@@ -497,17 +501,31 @@ dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
{
dns_name_t *zonename;
dns_xfrin_ctx_t *xfr;
dns_xfrin_ctx_t *xfr, *x;
isc_result_t result;
dns_db_t *db = NULL;
dns_rdatatype_t xfrtype;
dns_tsigkey_t *key = NULL;
isc_netaddr_t masterip;
dns_peer_t *peer = NULL;
int maxtransfers;
dns_xfrinlist_t *transferlist;
int nxfrs;
REQUIRE(xfrp != NULL && *xfrp == NULL);
zonename = dns_zone_getorigin(zone);
xfrin_log1(ISC_LOG_INFO, zonename, masteraddr, "starting");
/*
* Find any configured information about the server we are about
* to transfer from.
*/
isc_netaddr_fromsockaddr(&masterip, masteraddr);
(void) dns_peerlist_peerbyaddr(dns_zone_getview(zone)->peers,
&masterip, &peer);
result = dns_zone_getdb(zone, &db);
if (result == DNS_R_NOTLOADED)
INSIST(db == NULL);
@@ -523,15 +541,9 @@ dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
"requesting AXFR of initial version");
xfrtype = dns_rdatatype_axfr;
} else {
dns_peer_t *peer = NULL;
isc_boolean_t use_ixfr = ISC_TRUE;
isc_netaddr_t na;
isc_netaddr_fromsockaddr(&na, masteraddr);
if (dns_peerlist_peerbyaddr(dns_zone_getview(zone)->peers,
&na, &peer)
== ISC_R_SUCCESS &&
dns_peer_getsupportixfr(peer, &use_ixfr)
== ISC_R_SUCCESS &&
if (peer != NULL &&
dns_peer_getsupportixfr(peer, &use_ixfr) == ISC_R_SUCCESS &&
use_ixfr == ISC_FALSE)
{
xfrin_log1(ISC_LOG_DEBUG(3), zonename, masteraddr,
@@ -544,15 +556,66 @@ dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
}
}
CHECK(xfrin_create(mctx,
zone,
db,
task,
timermgr,
socketmgr,
zonename,
dns_zone_getclass(zone), xfrtype,
masteraddr, key, &xfr));
/*
* Determine the maximum number of simultaneous transfers
* allowed for this server, then count the number of
* transfers already in progress and fail if the quota
* is already full.
*
* Count the number of transfers that are in progress from
* this master. We linearly scan a list of all transfers;
* if this turns out to be too slow, we could hash on the
* master address.
*
* Note that we must keep the transfer list locked for an
* awkwardly long time because the scanning of the list
* and the creation of a new entry must be done atomically,
* and we don't want to create the transfer object until we
* know there is quota available.
*/
maxtransfers = dns_zonemgr_getttransfersperns(dns_zone_getmgr(zone));
if (peer != NULL) {
(void) dns_peer_gettransfers(peer, &maxtransfers);
}
transferlist = dns_zonemgr_gettransferlist(dns_zone_getmgr(zone));
LOCK(&transferlist->lock);
nxfrs = 0;
for (x = ISC_LIST_HEAD(transferlist->transfers);
x != NULL;
x = ISC_LIST_NEXT(x, link))
{
isc_netaddr_t xip;
isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
if (isc_netaddr_equal(&xip, &masterip))
nxfrs++;
}
if (nxfrs >= maxtransfers) {
result = ISC_R_QUOTA;
xfrin_log1(ISC_LOG_INFO, zonename, masteraddr,
"deferred: %s", isc_result_totext(result));
goto unlock;
}
result = xfrin_create(mctx,
zone,
db,
task,
timermgr,
socketmgr,
zonename,
dns_zone_getclass(zone), xfrtype,
masteraddr, key, &xfr);
if (result != ISC_R_SUCCESS)
goto unlock;
xfr->transferlist = transferlist;
ISC_LIST_APPEND(transferlist->transfers, xfr, link);
unlock:
UNLOCK(&transferlist->lock);
CHECK(result);
CHECK(xfrin_start(xfr));
@@ -679,6 +742,9 @@ xfrin_create(isc_mem_t *mctx,
xfr->axfr.add_func = NULL;
xfr->axfr.add_private = NULL;
ISC_LINK_INIT(xfr, link);
xfr->transferlist = NULL;
CHECK(dns_name_dup(zonename, mctx, &xfr->name));
isc_interval_set(&maxinterval, dns_zone_getmaxxfrin(xfr->zone), 0);
@@ -1122,6 +1188,13 @@ maybe_free(dns_xfrin_ctx_t *xfr) {
xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
if (xfr->transferlist != NULL) {
LOCK(&xfr->transferlist->lock);
ISC_LIST_UNLINK(xfr->transferlist->transfers, xfr, link);
UNLOCK(&xfr->transferlist->lock);
xfr->transferlist = NULL;
}
if (xfr->socket != NULL)
isc_socket_detach(&xfr->socket);
@@ -1225,3 +1298,12 @@ xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
xfrin_logv(level, &xfr->name, &xfr->masteraddr, fmt, ap);
va_end(ap);
}
isc_result_t dns_xfrinlist_init(dns_xfrinlist_t *list) {
ISC_LIST_INIT(list->transfers);
return (isc_mutex_init(&list->lock));
}
void dns_xfrinlist_destroy(dns_xfrinlist_t *list) {
isc_mutex_destroy(&list->lock);
}