2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-28 13:08:06 +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

@ -802,6 +802,15 @@ load_configuration(const char *filename, ns_server_t *server,
configure_server_quota(configctx, dns_c_ctx_getrecursiveclients,
&server->recursionquota, 100);
/*
* Configure the zone manager.
*/
{
isc_int32_t transfersperns = 2;
(void) dns_c_ctx_gettransfersperns(configctx, &transfersperns);
dns_zonemgr_settransfersperns(server->zonemgr, transfersperns);
}
/*
* Configure the interface manager according to the "listen-on"
* statement.

View File

@ -71,7 +71,7 @@ options {
[ transfer-format ( one-answer | many-answers ); ] Yes
[ transfers-in number; ] No
[ transfers-out number; ] Yes
[ transfers-per-ns number; ] No
[ transfers-per-ns number; ] Yes
[ transfer-source ip_addr; ] Yes
[ transfer-source-v6 ip_addr; ] Yes*
[ maintain-ixfr-base yes_or_no; ] Obsolete+
@ -104,7 +104,7 @@ controls No
server ip_addr {
[ bogus yes_or_no; ] No
[ support-ixfr yes_or_no; ] Yes
[ transfers number; ] No
[ transfers number; ] Yes
[ transfer-format ( one-answer | many-answers ); ] Yes
[ keys { key_id [key_id ... ] }; ] No
};

View File

@ -101,6 +101,7 @@ typedef struct dns_keytable dns_keytable_t;
typedef struct dns_keynode dns_keynode_t;
typedef struct dns_peer dns_peer_t;
typedef struct dns_peerlist dns_peerlist_t;
typedef struct dns_xfrinlist dns_xfrinlist_t;
typedef enum {
dns_labeltype_ordinary = 0,

View File

@ -31,14 +31,23 @@
***/
#include <isc/lang.h>
#include <isc/mutex.h>
#include <dns/types.h>
/***
*** Types
***/
/* A transfer in progress. This is an opaque type. */
typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;
/* A list of transfers in progress. */
struct dns_xfrinlist {
isc_mutex_t lock;
ISC_LIST(dns_xfrin_ctx_t) transfers;
};
/***
*** Functions
***/
@ -75,6 +84,10 @@ void dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
* only be one reference).
*/
isc_result_t dns_xfrinlist_init(dns_xfrinlist_t *list);
void dns_xfrinlist_destroy(dns_xfrinlist_t *list);
ISC_LANG_ENDDECLS
#endif /* DNS_XFRIN_H */

View File

@ -821,6 +821,8 @@ dns_zone_getmctx(dns_zone_t *zone);
* Get the memory context of a zone.
*/
dns_zonemgr_t *dns_zone_getmgr(dns_zone_t *zone);
isc_result_t
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
@ -884,6 +886,15 @@ dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, int value);
int
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
void
dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, int value);
int
dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr);
dns_xfrinlist_t *
dns_zonemgr_gettransferlist(dns_zonemgr_t *zmgr);
ISC_LANG_ENDDECLS
#endif /* DNS_ZONE_H */

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);
}

View File

@ -15,7 +15,7 @@
* SOFTWARE.
*/
/* $Id: zone.c,v 1.82 2000/02/24 21:40:51 gson Exp $ */
/* $Id: zone.c,v 1.83 2000/02/25 00:50:38 gson Exp $ */
#include <config.h>
@ -201,6 +201,8 @@ struct dns_zonemgr {
ISC_LIST(dns_zone_t) zones;
/* Maximum locked by conflock. */
isc_quota_t transfersin;
int transfersperns;
dns_xfrinlist_t transferlist;
};
static isc_result_t zone_settimer(dns_zone_t *, isc_stdtime_t);
@ -1339,7 +1341,12 @@ dns_zone_print(dns_zone_t *zone) {
isc_mem_t *
dns_zone_getmctx(dns_zone_t *zone) {
return zone->mctx;
return (zone->mctx);
}
dns_zonemgr_t *
dns_zone_getmgr(dns_zone_t *zone) {
return (zone->zmgr);
}
static isc_result_t
@ -3148,12 +3155,21 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
result = DNS_R_UNEXPECTED;
goto free_conflock;
}
zmgr->transfersperns = 2;
result = dns_xfrinlist_init(&zmgr->transferlist);
if (result != ISC_R_SUCCESS) {
UNEXPECTED_ERROR(__FILE__, __LINE__,
"dns_transferlist_init() failed: %s",
isc_result_totext(result));
result = DNS_R_UNEXPECTED;
goto free_transfersin;
}
/* Create the zone task pool. */
result = isc_taskpool_create(taskmgr, mctx,
8 /* XXX */, 0, &zmgr->zonetasks);
if (result != ISC_R_SUCCESS)
goto free_transfersin;
goto free_transferlist;
/* Create a single task for queueing of SOA queries. */
result = isc_task_create(taskmgr, mctx, 1, &zmgr->task);
@ -3164,6 +3180,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
*zmgrp = zmgr;
return (ISC_R_SUCCESS);
free_transferlist:
dns_xfrinlist_destroy(&zmgr->transferlist);
free_taskpool:
isc_taskpool_destroy(&zmgr->zonetasks);
free_transfersin:
@ -3303,6 +3321,21 @@ dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
return (zmgr->transfersin.max);
}
void
dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, int value) {
zmgr->transfersperns = value;
}
int
dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
return (zmgr->transfersperns);
}
dns_xfrinlist_t *
dns_zonemgr_gettransferlist(dns_zonemgr_t *zmgr) {
return (&zmgr->transferlist);
}
#if 0
/* hook for ondestroy notifcation from a database. */