mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-28 21:17:54 +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,
|
configure_server_quota(configctx, dns_c_ctx_getrecursiveclients,
|
||||||
&server->recursionquota, 100);
|
&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"
|
* Configure the interface manager according to the "listen-on"
|
||||||
* statement.
|
* statement.
|
||||||
|
@ -71,7 +71,7 @@ options {
|
|||||||
[ transfer-format ( one-answer | many-answers ); ] Yes
|
[ transfer-format ( one-answer | many-answers ); ] Yes
|
||||||
[ transfers-in number; ] No
|
[ transfers-in number; ] No
|
||||||
[ transfers-out number; ] Yes
|
[ transfers-out number; ] Yes
|
||||||
[ transfers-per-ns number; ] No
|
[ transfers-per-ns number; ] Yes
|
||||||
[ transfer-source ip_addr; ] Yes
|
[ transfer-source ip_addr; ] Yes
|
||||||
[ transfer-source-v6 ip_addr; ] Yes*
|
[ transfer-source-v6 ip_addr; ] Yes*
|
||||||
[ maintain-ixfr-base yes_or_no; ] Obsolete+
|
[ maintain-ixfr-base yes_or_no; ] Obsolete+
|
||||||
@ -104,7 +104,7 @@ controls No
|
|||||||
server ip_addr {
|
server ip_addr {
|
||||||
[ bogus yes_or_no; ] No
|
[ bogus yes_or_no; ] No
|
||||||
[ support-ixfr yes_or_no; ] Yes
|
[ support-ixfr yes_or_no; ] Yes
|
||||||
[ transfers number; ] No
|
[ transfers number; ] Yes
|
||||||
[ transfer-format ( one-answer | many-answers ); ] Yes
|
[ transfer-format ( one-answer | many-answers ); ] Yes
|
||||||
[ keys { key_id [key_id ... ] }; ] No
|
[ 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_keynode dns_keynode_t;
|
||||||
typedef struct dns_peer dns_peer_t;
|
typedef struct dns_peer dns_peer_t;
|
||||||
typedef struct dns_peerlist dns_peerlist_t;
|
typedef struct dns_peerlist dns_peerlist_t;
|
||||||
|
typedef struct dns_xfrinlist dns_xfrinlist_t;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
dns_labeltype_ordinary = 0,
|
dns_labeltype_ordinary = 0,
|
||||||
|
@ -31,14 +31,23 @@
|
|||||||
***/
|
***/
|
||||||
|
|
||||||
#include <isc/lang.h>
|
#include <isc/lang.h>
|
||||||
|
#include <isc/mutex.h>
|
||||||
|
|
||||||
#include <dns/types.h>
|
#include <dns/types.h>
|
||||||
|
|
||||||
/***
|
/***
|
||||||
*** Types
|
*** Types
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
/* A transfer in progress. This is an opaque type. */
|
||||||
typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;
|
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
|
*** Functions
|
||||||
***/
|
***/
|
||||||
@ -75,6 +84,10 @@ void dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
|
|||||||
* only be one reference).
|
* 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
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_XFRIN_H */
|
#endif /* DNS_XFRIN_H */
|
||||||
|
@ -821,6 +821,8 @@ dns_zone_getmctx(dns_zone_t *zone);
|
|||||||
* Get the memory context of a zone.
|
* Get the memory context of a zone.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
dns_zonemgr_t *dns_zone_getmgr(dns_zone_t *zone);
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
||||||
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
|
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
|
||||||
@ -884,6 +886,15 @@ dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, int value);
|
|||||||
int
|
int
|
||||||
dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr);
|
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
|
ISC_LANG_ENDDECLS
|
||||||
|
|
||||||
#endif /* DNS_ZONE_H */
|
#endif /* DNS_ZONE_H */
|
||||||
|
120
lib/dns/xfrin.c
120
lib/dns/xfrin.c
@ -15,7 +15,7 @@
|
|||||||
* SOFTWARE.
|
* 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>
|
#include <config.h>
|
||||||
|
|
||||||
@ -34,6 +34,7 @@
|
|||||||
#include <isc/timer.h>
|
#include <isc/timer.h>
|
||||||
#include <isc/net.h>
|
#include <isc/net.h>
|
||||||
#include <isc/print.h>
|
#include <isc/print.h>
|
||||||
|
#include <isc/util.h>
|
||||||
|
|
||||||
#include <dns/db.h>
|
#include <dns/db.h>
|
||||||
#include <dns/dbiterator.h>
|
#include <dns/dbiterator.h>
|
||||||
@ -160,6 +161,9 @@ struct dns_xfrin_ctx {
|
|||||||
dns_journal_t *journal;
|
dns_journal_t *journal;
|
||||||
|
|
||||||
} ixfr;
|
} 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_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
|
||||||
{
|
{
|
||||||
dns_name_t *zonename;
|
dns_name_t *zonename;
|
||||||
dns_xfrin_ctx_t *xfr;
|
dns_xfrin_ctx_t *xfr, *x;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_db_t *db = NULL;
|
dns_db_t *db = NULL;
|
||||||
dns_rdatatype_t xfrtype;
|
dns_rdatatype_t xfrtype;
|
||||||
dns_tsigkey_t *key = NULL;
|
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);
|
REQUIRE(xfrp != NULL && *xfrp == NULL);
|
||||||
|
|
||||||
zonename = dns_zone_getorigin(zone);
|
zonename = dns_zone_getorigin(zone);
|
||||||
|
|
||||||
xfrin_log1(ISC_LOG_INFO, zonename, masteraddr, "starting");
|
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);
|
result = dns_zone_getdb(zone, &db);
|
||||||
if (result == DNS_R_NOTLOADED)
|
if (result == DNS_R_NOTLOADED)
|
||||||
INSIST(db == NULL);
|
INSIST(db == NULL);
|
||||||
@ -523,15 +541,9 @@ dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
|||||||
"requesting AXFR of initial version");
|
"requesting AXFR of initial version");
|
||||||
xfrtype = dns_rdatatype_axfr;
|
xfrtype = dns_rdatatype_axfr;
|
||||||
} else {
|
} else {
|
||||||
dns_peer_t *peer = NULL;
|
|
||||||
isc_boolean_t use_ixfr = ISC_TRUE;
|
isc_boolean_t use_ixfr = ISC_TRUE;
|
||||||
isc_netaddr_t na;
|
if (peer != NULL &&
|
||||||
isc_netaddr_fromsockaddr(&na, masteraddr);
|
dns_peer_getsupportixfr(peer, &use_ixfr) == ISC_R_SUCCESS &&
|
||||||
if (dns_peerlist_peerbyaddr(dns_zone_getview(zone)->peers,
|
|
||||||
&na, &peer)
|
|
||||||
== ISC_R_SUCCESS &&
|
|
||||||
dns_peer_getsupportixfr(peer, &use_ixfr)
|
|
||||||
== ISC_R_SUCCESS &&
|
|
||||||
use_ixfr == ISC_FALSE)
|
use_ixfr == ISC_FALSE)
|
||||||
{
|
{
|
||||||
xfrin_log1(ISC_LOG_DEBUG(3), zonename, masteraddr,
|
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,
|
* Determine the maximum number of simultaneous transfers
|
||||||
db,
|
* allowed for this server, then count the number of
|
||||||
task,
|
* transfers already in progress and fail if the quota
|
||||||
timermgr,
|
* is already full.
|
||||||
socketmgr,
|
*
|
||||||
zonename,
|
* Count the number of transfers that are in progress from
|
||||||
dns_zone_getclass(zone), xfrtype,
|
* this master. We linearly scan a list of all transfers;
|
||||||
masteraddr, key, &xfr));
|
* 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));
|
CHECK(xfrin_start(xfr));
|
||||||
|
|
||||||
@ -679,6 +742,9 @@ xfrin_create(isc_mem_t *mctx,
|
|||||||
xfr->axfr.add_func = NULL;
|
xfr->axfr.add_func = NULL;
|
||||||
xfr->axfr.add_private = NULL;
|
xfr->axfr.add_private = NULL;
|
||||||
|
|
||||||
|
ISC_LINK_INIT(xfr, link);
|
||||||
|
xfr->transferlist = NULL;
|
||||||
|
|
||||||
CHECK(dns_name_dup(zonename, mctx, &xfr->name));
|
CHECK(dns_name_dup(zonename, mctx, &xfr->name));
|
||||||
|
|
||||||
isc_interval_set(&maxinterval, dns_zone_getmaxxfrin(xfr->zone), 0);
|
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");
|
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)
|
if (xfr->socket != NULL)
|
||||||
isc_socket_detach(&xfr->socket);
|
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);
|
xfrin_logv(level, &xfr->name, &xfr->masteraddr, fmt, ap);
|
||||||
va_end(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.
|
* 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>
|
#include <config.h>
|
||||||
|
|
||||||
@ -201,6 +201,8 @@ struct dns_zonemgr {
|
|||||||
ISC_LIST(dns_zone_t) zones;
|
ISC_LIST(dns_zone_t) zones;
|
||||||
/* Maximum locked by conflock. */
|
/* Maximum locked by conflock. */
|
||||||
isc_quota_t transfersin;
|
isc_quota_t transfersin;
|
||||||
|
int transfersperns;
|
||||||
|
dns_xfrinlist_t transferlist;
|
||||||
};
|
};
|
||||||
|
|
||||||
static isc_result_t zone_settimer(dns_zone_t *, isc_stdtime_t);
|
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 *
|
isc_mem_t *
|
||||||
dns_zone_getmctx(dns_zone_t *zone) {
|
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
|
static isc_result_t
|
||||||
@ -3148,12 +3155,21 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
|||||||
result = DNS_R_UNEXPECTED;
|
result = DNS_R_UNEXPECTED;
|
||||||
goto free_conflock;
|
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. */
|
/* Create the zone task pool. */
|
||||||
result = isc_taskpool_create(taskmgr, mctx,
|
result = isc_taskpool_create(taskmgr, mctx,
|
||||||
8 /* XXX */, 0, &zmgr->zonetasks);
|
8 /* XXX */, 0, &zmgr->zonetasks);
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto free_transfersin;
|
goto free_transferlist;
|
||||||
|
|
||||||
/* Create a single task for queueing of SOA queries. */
|
/* Create a single task for queueing of SOA queries. */
|
||||||
result = isc_task_create(taskmgr, mctx, 1, &zmgr->task);
|
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;
|
*zmgrp = zmgr;
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
|
|
||||||
|
free_transferlist:
|
||||||
|
dns_xfrinlist_destroy(&zmgr->transferlist);
|
||||||
free_taskpool:
|
free_taskpool:
|
||||||
isc_taskpool_destroy(&zmgr->zonetasks);
|
isc_taskpool_destroy(&zmgr->zonetasks);
|
||||||
free_transfersin:
|
free_transfersin:
|
||||||
@ -3303,6 +3321,21 @@ dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
|
|||||||
return (zmgr->transfersin.max);
|
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
|
#if 0
|
||||||
/* hook for ondestroy notifcation from a database. */
|
/* hook for ondestroy notifcation from a database. */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user