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:
parent
2bc0dee981
commit
e01ecff4b1
@ -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.
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
120
lib/dns/xfrin.c
120
lib/dns/xfrin.c
@ -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);
|
||||
}
|
||||
|
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user