mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-08 21:22:09 -04:00
changed arguments to dns_aml_checkrequest();
time out outgoing transfers (timeout is 2 hours for now); new cleanup strategy
This commit is contained in:
parent
de90a25a59
commit
d90b16946f
1 changed files with 84 additions and 48 deletions
|
|
@ -15,7 +15,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: xfrout.c,v 1.24 1999/12/01 00:27:13 gson Exp $ */
|
||||
/* $Id: xfrout.c,v 1.25 1999/12/02 22:31:13 gson Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
#include <isc/error.h>
|
||||
#include <isc/mem.h>
|
||||
#include <isc/result.h>
|
||||
#include <isc/timer.h>
|
||||
|
||||
#include <dns/aml.h>
|
||||
#include <dns/db.h>
|
||||
|
|
@ -732,6 +733,7 @@ typedef struct {
|
|||
dns_db_t *db;
|
||||
dns_dbversion_t *ver;
|
||||
rrstream_t *stream; /* The XFR RR stream */
|
||||
isc_boolean_t end_of_stream; /* EOS has been reached */
|
||||
isc_buffer_t buf; /* Buffer for message owner
|
||||
names and rdatas */
|
||||
isc_buffer_t txlenbuf; /* Transmit length buffer */
|
||||
|
|
@ -739,9 +741,11 @@ typedef struct {
|
|||
void *txmem;
|
||||
unsigned int txmemlen;
|
||||
unsigned int nmsg; /* Number of messages sent */
|
||||
|
||||
dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
|
||||
dns_rdata_any_tsig_t *lasttsig; /* the last TSIG */
|
||||
isc_timer_t *timer;
|
||||
int sends; /* Send in progress */
|
||||
isc_boolean_t shuttingdown;
|
||||
} xfrout_ctx_t;
|
||||
|
||||
static dns_result_t
|
||||
|
|
@ -749,15 +753,15 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
|
|||
unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
|
||||
dns_db_t *db, dns_dbversion_t *ver,
|
||||
rrstream_t *stream, dns_tsigkey_t *tsigkey,
|
||||
dns_rdata_any_tsig_t *lasttsig, xfrout_ctx_t **xfrp);
|
||||
dns_rdata_any_tsig_t *lasttsig, unsigned int timeout,
|
||||
xfrout_ctx_t **xfrp);
|
||||
|
||||
static void sendstream(xfrout_ctx_t *xfr);
|
||||
|
||||
static void xfrout_send_more(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrout_send_end(isc_task_t *task, isc_event_t *event);
|
||||
|
||||
static void xfrout_senddone(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrout_timeout(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrout_fail(xfrout_ctx_t *xfr, dns_result_t result, char *msg);
|
||||
|
||||
static void xfrout_maybe_destroy(xfrout_ctx_t *xfr);
|
||||
static void xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
|
||||
|
||||
/**************************************************************************/
|
||||
|
|
@ -784,7 +788,6 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype)
|
|||
isc_mem_t *mctx = client->mctx;
|
||||
dns_message_t *request = client->message;
|
||||
xfrout_ctx_t *xfr = NULL;
|
||||
dns_c_ipmatchlist_t *aml;
|
||||
|
||||
switch (reqtype) {
|
||||
case dns_rdatatype_axfr:
|
||||
|
|
@ -886,15 +889,13 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype)
|
|||
mnemonic);
|
||||
|
||||
/* Decide whether to allow this transfer. */
|
||||
aml = dns_zone_getxfracl(zone);
|
||||
if (aml == NULL)
|
||||
aml = ns_g_confctx->options->transferacl;
|
||||
if (aml != NULL) {
|
||||
CHECK(dns_aml_checkrequest(request,
|
||||
ns_client_getsockaddr(client),
|
||||
aml, ns_g_confctx->acls,
|
||||
"zone transfer", ISC_FALSE));
|
||||
}
|
||||
CHECK(dns_aml_checkrequest(request,
|
||||
ns_client_getsockaddr(client),
|
||||
ns_g_confctx->acls,
|
||||
"zone transfer",
|
||||
dns_zone_getxfracl(zone),
|
||||
ns_g_confctx->options->transferacl,
|
||||
ISC_TRUE));
|
||||
|
||||
/* AXFR over UDP is not possible. */
|
||||
if (reqtype == dns_rdatatype_axfr &&
|
||||
|
|
@ -966,7 +967,9 @@ ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype)
|
|||
*/
|
||||
CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
|
||||
reqtype, db, ver, stream, request->tsigkey,
|
||||
request->tsig, &xfr));
|
||||
request->tsig,
|
||||
2*3600, /* XXX need timeout config option */
|
||||
&xfr));
|
||||
stream = NULL;
|
||||
db = NULL;
|
||||
ver = NULL;
|
||||
|
|
@ -1013,12 +1016,14 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
|
|||
dns_name_t *qname, dns_rdatatype_t qtype,
|
||||
dns_db_t *db, dns_dbversion_t *ver,
|
||||
rrstream_t *stream, dns_tsigkey_t *tsigkey,
|
||||
dns_rdata_any_tsig_t *lasttsig, xfrout_ctx_t **xfrp)
|
||||
dns_rdata_any_tsig_t *lasttsig, unsigned int timeout,
|
||||
xfrout_ctx_t **xfrp)
|
||||
{
|
||||
xfrout_ctx_t *xfr;
|
||||
dns_result_t result;
|
||||
unsigned int len;
|
||||
void *mem;
|
||||
isc_interval_t interval;
|
||||
|
||||
INSIST(xfrp != NULL && *xfrp == NULL);
|
||||
xfr = isc_mem_get(mctx, sizeof(*xfr));
|
||||
|
|
@ -1032,12 +1037,16 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
|
|||
xfr->db = db;
|
||||
xfr->ver = ver;
|
||||
xfr->stream = stream;
|
||||
xfr->end_of_stream = ISC_FALSE;
|
||||
xfr->tsigkey = tsigkey;
|
||||
xfr->lasttsig = lasttsig;
|
||||
xfr->txmem = NULL;
|
||||
xfr->txmemlen = 0;
|
||||
xfr->nmsg = 0;
|
||||
|
||||
xfr->timer = NULL;
|
||||
xfr->sends = 0;
|
||||
xfr->shuttingdown = ISC_FALSE;
|
||||
|
||||
/*
|
||||
* Allocate a temporary buffer for the uncompressed response
|
||||
* message data. The size should be no more than 65535 bytes
|
||||
|
|
@ -1071,7 +1080,15 @@ xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
|
|||
ISC_BUFFERTYPE_BINARY);
|
||||
xfr->txmem = mem;
|
||||
xfr->txmemlen = len;
|
||||
|
||||
|
||||
isc_interval_set(&interval, timeout, 0);
|
||||
result = isc_timer_create(ns_g_timermgr, isc_timertype_once,
|
||||
NULL, &interval,
|
||||
xfr->client->task,
|
||||
xfrout_timeout, xfr, &xfr->timer);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
goto cleanup;
|
||||
|
||||
*xfrp = xfr;
|
||||
return (DNS_R_SUCCESS);
|
||||
|
||||
|
|
@ -1094,7 +1111,6 @@ sendstream(xfrout_ctx_t *xfr)
|
|||
{
|
||||
dns_message_t *msg = NULL;
|
||||
dns_result_t result;
|
||||
isc_boolean_t done = ISC_FALSE;
|
||||
isc_region_t used;
|
||||
isc_region_t region;
|
||||
dns_rdataset_t *qrdataset;
|
||||
|
|
@ -1248,7 +1264,7 @@ sendstream(xfrout_ctx_t *xfr)
|
|||
|
||||
result = xfr->stream->methods->next(xfr->stream);
|
||||
if (result == DNS_R_NOMORE) {
|
||||
done = ISC_TRUE;
|
||||
xfr->end_of_stream = ISC_TRUE;
|
||||
break;
|
||||
}
|
||||
CHECK(result);
|
||||
|
|
@ -1275,10 +1291,9 @@ sendstream(xfrout_ctx_t *xfr)
|
|||
used.length);
|
||||
CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
|
||||
®ion, xfr->client->task,
|
||||
done ?
|
||||
xfrout_send_end :
|
||||
xfrout_send_more,
|
||||
xfrout_senddone,
|
||||
xfr));
|
||||
xfr->sends++;
|
||||
} else {
|
||||
isc_log_write(XFROUT_DEBUG_LOGARGS(8),
|
||||
"sending IXFR UDP response of %d bytes",
|
||||
|
|
@ -1324,6 +1339,9 @@ static void
|
|||
xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
|
||||
xfrout_ctx_t *xfr = *xfrp;
|
||||
|
||||
INSIST(xfr->sends == 0);
|
||||
if (xfr->timer != NULL)
|
||||
isc_timer_detach(&xfr->timer);
|
||||
if (xfr->stream != NULL)
|
||||
xfr->stream->methods->destroy(&xfr->stream);
|
||||
if (xfr->buf.base != NULL)
|
||||
|
|
@ -1347,43 +1365,61 @@ xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
|
|||
}
|
||||
|
||||
static void
|
||||
xfrout_send_more(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *) event;
|
||||
xfrout_senddone(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *) event;
|
||||
xfrout_ctx_t *xfr = (xfrout_ctx_t *) event->arg;
|
||||
isc_result_t evresult = sev->result;
|
||||
task = task; /* Unused */
|
||||
INSIST(event->type == ISC_SOCKEVENT_SENDDONE);
|
||||
if (sev->result != ISC_R_SUCCESS) {
|
||||
xfrout_fail(xfr, sev->result, "send");
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
isc_event_free(&event);
|
||||
xfr->sends--;
|
||||
INSIST(xfr->sends == 0);
|
||||
if (xfr->shuttingdown == ISC_TRUE) {
|
||||
xfrout_maybe_destroy(xfr);
|
||||
} else if (evresult != ISC_R_SUCCESS) {
|
||||
xfrout_fail(xfr, evresult, "send");
|
||||
} else if (xfr->end_of_stream == ISC_FALSE) {
|
||||
sendstream(xfr);
|
||||
} else {
|
||||
/* End of zone transfer stream. */
|
||||
isc_log_write(XFROUT_DEBUG_LOGARGS(6),
|
||||
"end of outgoing zone transfer");
|
||||
ns_client_next(xfr->client, DNS_R_SUCCESS);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
}
|
||||
isc_event_free(&event);
|
||||
sendstream(xfr);
|
||||
}
|
||||
|
||||
static void
|
||||
xfrout_send_end(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *) event;
|
||||
xfrout_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
xfrout_ctx_t *xfr = (xfrout_ctx_t *) event->arg;
|
||||
task = task; /* Unused */
|
||||
isc_log_write(XFROUT_DEBUG_LOGARGS(6), "end of outgoing zone transfer");
|
||||
INSIST(event->type == ISC_SOCKEVENT_SENDDONE);
|
||||
if (sev->result != ISC_R_SUCCESS) {
|
||||
xfrout_fail(xfr, sev->result, "send");
|
||||
isc_event_free(&event);
|
||||
return;
|
||||
}
|
||||
/* This will log "giving up: timeout". */
|
||||
xfrout_fail(xfr, ISC_R_TIMEDOUT, "giving up");
|
||||
isc_event_free(&event);
|
||||
ns_client_next(xfr->client, DNS_R_SUCCESS);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
}
|
||||
|
||||
static void
|
||||
xfrout_fail(xfrout_ctx_t *xfr, dns_result_t result, char *msg)
|
||||
{
|
||||
xfr->shuttingdown = ISC_TRUE;
|
||||
isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_ERROR,
|
||||
"error in outgoing zone transfer: %s: %s",
|
||||
"outgoing zone transfer: %s: %s",
|
||||
msg, isc_result_totext(result));
|
||||
ns_client_next(xfr->client, result); /* XXX what is the result for? */
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
xfrout_maybe_destroy(xfr);
|
||||
}
|
||||
|
||||
static void
|
||||
xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
|
||||
INSIST(xfr->shuttingdown == ISC_TRUE);
|
||||
if (xfr->sends > 0) {
|
||||
/*
|
||||
* If we are currently sending, cancel it and wait for
|
||||
* cancel event before destroying the context.
|
||||
*/
|
||||
isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
|
||||
ISC_SOCKCANCEL_SEND);
|
||||
} else {
|
||||
ns_client_next(xfr->client, ISC_R_CANCELED);
|
||||
xfrout_ctx_destroy(&xfr);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue