mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-30 22:15:20 +00:00
Abort incoming zone transfers on server shutdown. To support
this, zone transfers now use the zone's task, the zone holds a pointer to any zone transfer in progress, and the zone now registers a shutdown callback.
This commit is contained in:
@@ -26,15 +26,55 @@
|
||||
* Incoming zone transfers (AXFR + IXFR).
|
||||
*/
|
||||
|
||||
/***
|
||||
*** Imports
|
||||
***/
|
||||
|
||||
#include <isc/lang.h>
|
||||
#include <dns/types.h>
|
||||
|
||||
/***
|
||||
*** Types
|
||||
***/
|
||||
|
||||
typedef struct dns_xfrin_ctx dns_xfrin_ctx_t;
|
||||
|
||||
/***
|
||||
*** Functions
|
||||
***/
|
||||
|
||||
void dns_xfrin_start(dns_zone_t *zone, isc_sockaddr_t *master,
|
||||
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
|
||||
dns_xfrindone_t done);
|
||||
ISC_LANG_BEGINDECLS
|
||||
|
||||
isc_result_t
|
||||
dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
||||
isc_mem_t *mctx, isc_timermgr_t *timermgr,
|
||||
isc_socketmgr_t *socketmgr, isc_task_t *task,
|
||||
dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp);
|
||||
/*
|
||||
* Attempt to start an incoming zone transfer of 'zone'
|
||||
* from 'masteraddr', creating a dns_xfrin_ctx_t object to
|
||||
* manage it. Attach '*xfrp' to the newly created object.
|
||||
*
|
||||
* Iff ISC_R_SUCCESS is returned, '*done' is guaranteed to be
|
||||
* called in the context of 'task', with 'zone' and a result
|
||||
* code as arguments when the transfer finishes.
|
||||
*/
|
||||
|
||||
void dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr);
|
||||
/*
|
||||
* If the zone transfer 'xfr' has already finished,
|
||||
* do nothing. Otherwise, abort it and cause it to call
|
||||
* its done callback with a status of ISC_R_CANCELLED.
|
||||
*/
|
||||
|
||||
void dns_xfrin_detach(dns_xfrin_ctx_t **xfrp);
|
||||
/*
|
||||
* Detach a reference to a zone transfer object.
|
||||
*
|
||||
* (Because there is no attach() method, there can currently
|
||||
* only be one reference).
|
||||
*/
|
||||
|
||||
ISC_LANG_ENDDECLS
|
||||
|
||||
#endif /* DNS_XFRIN_H */
|
||||
|
179
lib/dns/xfrin.c
179
lib/dns/xfrin.c
@@ -15,7 +15,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: xfrin.c,v 1.40 2000/01/28 01:12:01 gson Exp $ */
|
||||
/* $Id: xfrin.c,v 1.41 2000/01/28 23:48:57 gson Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -65,8 +65,6 @@
|
||||
if (result != DNS_R_SUCCESS) goto failure; \
|
||||
} while (0)
|
||||
|
||||
typedef struct xfrin_ctx xfrin_ctx_t;
|
||||
|
||||
/*
|
||||
* The states of the *XFR state machine. We handle both IXFR and AXFR
|
||||
* with a single integrated state machine because they cannot be distinguished
|
||||
@@ -90,10 +88,12 @@ typedef enum {
|
||||
* Incoming zone transfer context.
|
||||
*/
|
||||
|
||||
struct xfrin_ctx {
|
||||
struct dns_xfrin_ctx {
|
||||
isc_mem_t *mctx;
|
||||
dns_zone_t *zone;
|
||||
|
||||
int refcount;
|
||||
|
||||
isc_task_t *task;
|
||||
isc_timer_t *timer;
|
||||
isc_socketmgr_t *socketmgr;
|
||||
@@ -173,44 +173,43 @@ xfrin_create(isc_mem_t *mctx,
|
||||
isc_task_t *task,
|
||||
isc_timermgr_t *timermgr,
|
||||
isc_socketmgr_t *socketmgr,
|
||||
dns_xfrindone_t done,
|
||||
dns_name_t *zonename,
|
||||
dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t reqtype,
|
||||
isc_sockaddr_t *masteraddr,
|
||||
dns_tsigkey_t *tsigkey,
|
||||
xfrin_ctx_t **xfrp);
|
||||
dns_xfrin_ctx_t **xfrp);
|
||||
|
||||
static isc_result_t axfr_init(xfrin_ctx_t *xfr);
|
||||
static isc_result_t axfr_makedb(xfrin_ctx_t *xfr, dns_db_t **dbp);
|
||||
static isc_result_t axfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
|
||||
static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
|
||||
static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
dns_name_t *name, dns_ttl_t ttl,
|
||||
dns_rdata_t *rdata);
|
||||
static isc_result_t axfr_apply(xfrin_ctx_t *xfr);
|
||||
static isc_result_t axfr_commit(xfrin_ctx_t *xfr);
|
||||
static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
|
||||
static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static isc_result_t ixfr_init(xfrin_ctx_t *xfr);
|
||||
static isc_result_t ixfr_apply(xfrin_ctx_t *xfr);
|
||||
static isc_result_t ixfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
|
||||
static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
|
||||
static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
dns_name_t *name, dns_ttl_t ttl,
|
||||
dns_rdata_t *rdata);
|
||||
static isc_result_t ixfr_commit(xfrin_ctx_t *xfr);
|
||||
static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static isc_result_t xfr_rr(xfrin_ctx_t *xfr, dns_name_t *name,
|
||||
static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
|
||||
isc_uint32_t ttl, dns_rdata_t *rdata);
|
||||
|
||||
void xfrin_start(xfrin_ctx_t *xfr);
|
||||
static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
|
||||
static isc_result_t xfrin_send_request(xfrin_ctx_t *xfr);
|
||||
static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
|
||||
static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
|
||||
static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
|
||||
|
||||
static isc_boolean_t maybe_free(xfrin_ctx_t *xfr);
|
||||
static void maybe_free(dns_xfrin_ctx_t *xfr);
|
||||
|
||||
static void xfrin_fail(xfrin_ctx_t *xfr, isc_result_t result, char *msg);
|
||||
static void xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, char *msg);
|
||||
static isc_result_t render(dns_message_t *msg, isc_buffer_t *buf);
|
||||
|
||||
static void
|
||||
@@ -220,7 +219,7 @@ static void
|
||||
xfrin_log1(int level, dns_name_t *zonename, isc_sockaddr_t *masteraddr,
|
||||
const char *fmt, ...);
|
||||
static void
|
||||
xfrin_log(xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...);
|
||||
xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...);
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
@@ -229,7 +228,7 @@ xfrin_log(xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...);
|
||||
*/
|
||||
|
||||
static isc_result_t
|
||||
axfr_init(xfrin_ctx_t *xfr) {
|
||||
axfr_init(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
xfr->is_ixfr = ISC_FALSE;
|
||||
|
||||
@@ -245,7 +244,7 @@ axfr_init(xfrin_ctx_t *xfr) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
axfr_makedb(xfrin_ctx_t *xfr, dns_db_t **dbp) {
|
||||
axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
|
||||
return (dns_db_create(xfr->mctx, /* XXX */
|
||||
"rbt", /* XXX guess */
|
||||
&xfr->name,
|
||||
@@ -256,7 +255,7 @@ axfr_makedb(xfrin_ctx_t *xfr, dns_db_t **dbp) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
axfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
|
||||
{
|
||||
isc_result_t result;
|
||||
@@ -273,7 +272,7 @@ axfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
|
||||
/* Store a set of AXFR RRs in the database. */
|
||||
static isc_result_t
|
||||
axfr_apply(xfrin_ctx_t *xfr) {
|
||||
axfr_apply(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
CHECK(dns_diff_load(&xfr->diff,
|
||||
xfr->axfr.add_func, xfr->axfr.add_private));
|
||||
@@ -285,7 +284,7 @@ axfr_apply(xfrin_ctx_t *xfr) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
axfr_commit(xfrin_ctx_t *xfr) {
|
||||
axfr_commit(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
|
||||
CHECK(axfr_apply(xfr));
|
||||
@@ -303,7 +302,7 @@ axfr_commit(xfrin_ctx_t *xfr) {
|
||||
*/
|
||||
|
||||
static isc_result_t
|
||||
ixfr_init(xfrin_ctx_t *xfr) {
|
||||
ixfr_init(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
xfr->is_ixfr = ISC_TRUE;
|
||||
INSIST(xfr->db != NULL);
|
||||
@@ -316,7 +315,7 @@ ixfr_init(xfrin_ctx_t *xfr) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ixfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
|
||||
{
|
||||
isc_result_t result;
|
||||
@@ -333,7 +332,7 @@ ixfr_putdata(xfrin_ctx_t *xfr, dns_diffop_t op,
|
||||
|
||||
/* Apply a set of IXFR changes to the database. */
|
||||
static isc_result_t
|
||||
ixfr_apply(xfrin_ctx_t *xfr) {
|
||||
ixfr_apply(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
if (xfr->ver == NULL) {
|
||||
CHECK(dns_db_newversion(xfr->db, &xfr->ver));
|
||||
@@ -349,7 +348,7 @@ ixfr_apply(xfrin_ctx_t *xfr) {
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
ixfr_commit(xfrin_ctx_t *xfr) {
|
||||
ixfr_commit(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
ixfr_apply(xfr);
|
||||
if (xfr->ver != NULL) {
|
||||
@@ -372,7 +371,7 @@ ixfr_commit(xfrin_ctx_t *xfr) {
|
||||
* state.
|
||||
*/
|
||||
static isc_result_t
|
||||
xfr_rr(xfrin_ctx_t *xfr,
|
||||
xfr_rr(dns_xfrin_ctx_t *xfr,
|
||||
dns_name_t *name, isc_uint32_t ttl, dns_rdata_t *rdata)
|
||||
{
|
||||
isc_result_t result;
|
||||
@@ -490,19 +489,19 @@ xfr_rr(xfrin_ctx_t *xfr,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
dns_xfrin_start(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
||||
isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
|
||||
isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
|
||||
dns_xfrindone_t done)
|
||||
isc_result_t
|
||||
dns_xfrin_create(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
||||
isc_mem_t *mctx, isc_timermgr_t *timermgr,
|
||||
isc_socketmgr_t *socketmgr, isc_task_t *task,
|
||||
dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
|
||||
{
|
||||
dns_name_t *zonename;
|
||||
isc_task_t *task;
|
||||
xfrin_ctx_t *xfr;
|
||||
dns_xfrin_ctx_t *xfr;
|
||||
isc_result_t result;
|
||||
dns_db_t *db = NULL;
|
||||
dns_rdatatype_t xfrtype;
|
||||
dns_tsigkey_t *key = NULL;
|
||||
REQUIRE(xfrp != NULL && *xfrp == NULL);
|
||||
|
||||
zonename = dns_zone_getorigin(zone);
|
||||
|
||||
@@ -514,10 +513,6 @@ dns_xfrin_start(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
||||
else
|
||||
CHECK(result);
|
||||
|
||||
task = NULL;
|
||||
CHECK(isc_task_create(taskmgr, mctx, 0, &task));
|
||||
isc_task_setname(task, "xfrin", zone);
|
||||
|
||||
if (db == NULL) {
|
||||
xfrin_log1(ISC_LOG_DEBUG(3), zonename, masteraddr,
|
||||
"no database exists yet, "
|
||||
@@ -535,34 +530,44 @@ dns_xfrin_start(dns_zone_t *zone, isc_sockaddr_t *masteraddr,
|
||||
task,
|
||||
timermgr,
|
||||
socketmgr,
|
||||
done,
|
||||
zonename,
|
||||
dns_zone_getclass(zone), xfrtype,
|
||||
masteraddr, key, &xfr));
|
||||
|
||||
xfrin_start(xfr);
|
||||
goto cleanup;
|
||||
CHECK(xfrin_start(xfr));
|
||||
|
||||
xfr->done = done;
|
||||
xfr->refcount++;
|
||||
*xfrp = xfr;
|
||||
|
||||
failure:
|
||||
if (done != NULL)
|
||||
(done)(zone, result);
|
||||
|
||||
cleanup:
|
||||
if (db != NULL)
|
||||
dns_db_detach(&db);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
xfrin_log1(ISC_LOG_ERROR, zonename, masteraddr,
|
||||
"zone transfer setup failed");
|
||||
return;
|
||||
return (result);
|
||||
}
|
||||
|
||||
void dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
|
||||
if (! xfr->shuttingdown)
|
||||
xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
|
||||
}
|
||||
|
||||
void dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
|
||||
dns_xfrin_ctx_t *xfr = *xfrp;
|
||||
INSIST(xfr->refcount > 0);
|
||||
xfr->refcount--;
|
||||
maybe_free(xfr);
|
||||
*xfrp = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
xfrin_fail(xfrin_ctx_t *xfr, isc_result_t result, char *msg) {
|
||||
xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, char *msg) {
|
||||
if (result != DNS_R_UPTODATE) {
|
||||
xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
|
||||
msg, isc_result_totext(result));
|
||||
}
|
||||
xfr->shuttingdown = ISC_TRUE;
|
||||
if (xfr->connects > 0) {
|
||||
isc_socket_cancel(xfr->socket, xfr->task,
|
||||
ISC_SOCKCANCEL_CONNECT);
|
||||
@@ -572,8 +577,11 @@ xfrin_fail(xfrin_ctx_t *xfr, isc_result_t result, char *msg) {
|
||||
isc_socket_cancel(xfr->socket, xfr->task,
|
||||
ISC_SOCKCANCEL_SEND);
|
||||
}
|
||||
if (xfr->done != NULL)
|
||||
xfr->shuttingdown = ISC_TRUE;
|
||||
if (xfr->done != NULL) {
|
||||
(xfr->done)(xfr->zone, result);
|
||||
xfr->done = NULL;
|
||||
}
|
||||
maybe_free(xfr);
|
||||
}
|
||||
|
||||
@@ -584,15 +592,14 @@ xfrin_create(isc_mem_t *mctx,
|
||||
isc_task_t *task,
|
||||
isc_timermgr_t *timermgr,
|
||||
isc_socketmgr_t *socketmgr,
|
||||
dns_xfrindone_t done,
|
||||
dns_name_t *zonename,
|
||||
dns_rdataclass_t rdclass,
|
||||
dns_rdatatype_t reqtype,
|
||||
isc_sockaddr_t *masteraddr,
|
||||
dns_tsigkey_t *tsigkey,
|
||||
xfrin_ctx_t **xfrp)
|
||||
dns_xfrin_ctx_t **xfrp)
|
||||
{
|
||||
xfrin_ctx_t *xfr = NULL;
|
||||
dns_xfrin_ctx_t *xfr = NULL;
|
||||
isc_result_t result;
|
||||
isc_interval_t interval;
|
||||
|
||||
@@ -600,12 +607,14 @@ xfrin_create(isc_mem_t *mctx,
|
||||
if (xfr == NULL)
|
||||
return (DNS_R_NOMEMORY);
|
||||
xfr->mctx = mctx;
|
||||
xfr->refcount = 0;
|
||||
xfr->zone = NULL;
|
||||
dns_zone_attach(zone, &xfr->zone);
|
||||
xfr->task = task;
|
||||
xfr->task = NULL;
|
||||
isc_task_attach(task, &xfr->task);
|
||||
xfr->timer = NULL;
|
||||
xfr->socketmgr = socketmgr;
|
||||
xfr->done = done;
|
||||
xfr->done = NULL;
|
||||
|
||||
xfr->connects = 0;
|
||||
xfr->sends = 0;
|
||||
@@ -672,8 +681,8 @@ xfrin_create(isc_mem_t *mctx,
|
||||
return (result);
|
||||
}
|
||||
|
||||
void
|
||||
xfrin_start(xfrin_ctx_t *xfr) {
|
||||
isc_result_t
|
||||
xfrin_start(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
CHECK(isc_socket_create(xfr->socketmgr,
|
||||
isc_sockaddr_pf(&xfr->masteraddr),
|
||||
@@ -683,9 +692,10 @@ xfrin_start(xfrin_ctx_t *xfr) {
|
||||
CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
|
||||
xfrin_connect_done, xfr));
|
||||
xfr->connects++;
|
||||
return;
|
||||
return (ISC_R_SUCCESS);
|
||||
failure:
|
||||
xfrin_fail(xfr, result, "setting up socket");
|
||||
return (result);
|
||||
}
|
||||
|
||||
/* XXX the resolver could use this, too */
|
||||
@@ -711,7 +721,7 @@ render(dns_message_t *msg, isc_buffer_t *buf) {
|
||||
static void
|
||||
xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
|
||||
isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
|
||||
xfrin_ctx_t *xfr = (xfrin_ctx_t *) event->arg;
|
||||
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->arg;
|
||||
isc_result_t evresult = cev->result;
|
||||
isc_result_t result;
|
||||
task = task; /* Unused */
|
||||
@@ -719,8 +729,10 @@ xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
|
||||
isc_event_free(&event);
|
||||
|
||||
xfr->connects--;
|
||||
if (maybe_free(xfr))
|
||||
if (xfr->shuttingdown) {
|
||||
maybe_free(xfr);
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(evresult);
|
||||
xfrin_log(xfr, ISC_LOG_DEBUG(3), "connected");
|
||||
@@ -779,7 +791,7 @@ tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
|
||||
* Build an *XFR request and send its length prefix.
|
||||
*/
|
||||
static isc_result_t
|
||||
xfrin_send_request(xfrin_ctx_t *xfr) {
|
||||
xfrin_send_request(dns_xfrin_ctx_t *xfr) {
|
||||
isc_result_t result;
|
||||
isc_region_t region;
|
||||
isc_region_t lregion;
|
||||
@@ -858,7 +870,7 @@ static void
|
||||
xfrin_sendlen_done(isc_task_t *task, isc_event_t *event)
|
||||
{
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *) event;
|
||||
xfrin_ctx_t *xfr = (xfrin_ctx_t *) event->arg;
|
||||
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->arg;
|
||||
isc_result_t evresult = sev->result;
|
||||
isc_result_t result;
|
||||
isc_region_t region;
|
||||
@@ -868,8 +880,10 @@ xfrin_sendlen_done(isc_task_t *task, isc_event_t *event)
|
||||
isc_event_free(&event);
|
||||
|
||||
xfr->sends--;
|
||||
if (maybe_free(xfr))
|
||||
if (xfr->shuttingdown) {
|
||||
maybe_free(xfr);
|
||||
return;
|
||||
}
|
||||
|
||||
xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
|
||||
CHECK(evresult);
|
||||
@@ -888,7 +902,7 @@ static void
|
||||
xfrin_send_done(isc_task_t *task, isc_event_t *event)
|
||||
{
|
||||
isc_socketevent_t *sev = (isc_socketevent_t *) event;
|
||||
xfrin_ctx_t *xfr = (xfrin_ctx_t *) event->arg;
|
||||
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->arg;
|
||||
isc_result_t result;
|
||||
|
||||
task = task; /* Unused */
|
||||
@@ -910,7 +924,7 @@ xfrin_send_done(isc_task_t *task, isc_event_t *event)
|
||||
|
||||
static void
|
||||
xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
||||
xfrin_ctx_t *xfr = (xfrin_ctx_t *) ev->arg;
|
||||
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->arg;
|
||||
isc_result_t result;
|
||||
dns_message_t *msg = NULL;
|
||||
dns_name_t *name;
|
||||
@@ -923,8 +937,10 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
||||
isc_event_free(&ev);
|
||||
|
||||
xfr->recvs--;
|
||||
if (maybe_free(xfr))
|
||||
if (xfr->shuttingdown) {
|
||||
maybe_free(xfr);
|
||||
return;
|
||||
}
|
||||
|
||||
CHECK(tcpmsg->result);
|
||||
|
||||
@@ -1032,13 +1048,15 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
||||
/*
|
||||
* Inform the caller we succeeded.
|
||||
*/
|
||||
if (xfr->done != NULL)
|
||||
if (xfr->done != NULL) {
|
||||
(xfr->done)(xfr->zone, ISC_R_SUCCESS);
|
||||
xfr->done = NULL;
|
||||
}
|
||||
/*
|
||||
* We should have no outstanding events at this
|
||||
* point, thus maybe_free() should succeed.
|
||||
*/
|
||||
RUNTIME_CHECK(maybe_free(xfr) == ISC_TRUE);
|
||||
maybe_free(xfr);
|
||||
} else {
|
||||
/* Read the next message. */
|
||||
CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
|
||||
@@ -1058,18 +1076,19 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
|
||||
|
||||
static void
|
||||
xfrin_timeout(isc_task_t *task, isc_event_t *event) {
|
||||
xfrin_ctx_t *xfr = (xfrin_ctx_t *) event->arg;
|
||||
dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->arg;
|
||||
task = task; /* Unused */
|
||||
isc_event_free(&event);
|
||||
/* This will log "giving up: timeout". */
|
||||
xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
|
||||
}
|
||||
|
||||
static isc_boolean_t
|
||||
maybe_free(xfrin_ctx_t *xfr) {
|
||||
if (! xfr->shuttingdown || xfr->connects != 0 ||
|
||||
xfr->sends != 0 || xfr->recvs != 0)
|
||||
return (ISC_FALSE);
|
||||
static void
|
||||
maybe_free(dns_xfrin_ctx_t *xfr) {
|
||||
if (! xfr->shuttingdown || xfr->refcount != 0 ||
|
||||
xfr->connects != 0 || xfr->sends != 0 ||
|
||||
xfr->recvs != 0)
|
||||
return;
|
||||
|
||||
xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
|
||||
|
||||
@@ -1080,7 +1099,7 @@ maybe_free(xfrin_ctx_t *xfr) {
|
||||
isc_timer_detach(&xfr->timer);
|
||||
|
||||
if (xfr->task != NULL)
|
||||
isc_task_destroy(&xfr->task);
|
||||
isc_task_detach(&xfr->task);
|
||||
|
||||
if (xfr->lasttsig != NULL) {
|
||||
dns_rdata_freestruct(xfr->lasttsig);
|
||||
@@ -1111,8 +1130,6 @@ maybe_free(xfrin_ctx_t *xfr) {
|
||||
dns_zone_detach(&xfr->zone);
|
||||
|
||||
isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
|
||||
|
||||
return (ISC_TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1167,7 +1184,7 @@ xfrin_log1(int level, dns_name_t *zonename, isc_sockaddr_t *masteraddr,
|
||||
/* Logging function for use when there is a xfin_ctx_t. */
|
||||
|
||||
static void
|
||||
xfrin_log(xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
|
||||
xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/* $Id: zone.c,v 1.70 2000/01/28 16:10:47 bwelling Exp $ */
|
||||
/* $Id: zone.c,v 1.71 2000/01/28 23:48:58 gson Exp $ */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
@@ -142,6 +142,7 @@ struct dns_zone {
|
||||
isc_sockaddr_t notifyfrom;
|
||||
isc_task_t * task;
|
||||
isc_sockaddr_t xfrsource;
|
||||
dns_xfrin_ctx_t * xfr;
|
||||
/* Access Control Lists */
|
||||
dns_acl_t *update_acl;
|
||||
dns_acl_t *query_acl;
|
||||
@@ -209,11 +210,11 @@ static isc_result_t default_journal(dns_zone_t *zone);
|
||||
static void releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone);
|
||||
static void xfrin_start_temporary_kludge(dns_zone_t *zone);
|
||||
static void xfrdone(dns_zone_t *zone, isc_result_t result);
|
||||
static void zone_shutdown(isc_task_t *, isc_event_t *);
|
||||
#ifdef notyet
|
||||
static void refresh_callback(isc_task_t *, isc_event_t *);
|
||||
static void soa_query(dns_zone_t *, isc_taskaction_t);
|
||||
static void checkservers_callback(isc_task_t *task, isc_event_t *event);
|
||||
static void zone_shutdown(isc_task_t *, isc_event_t *);
|
||||
static int message_count(dns_message_t *msg, dns_section_t section,
|
||||
dns_rdatatype_t type);
|
||||
static void add_address_tocheck(dns_message_t *msg,
|
||||
@@ -315,6 +316,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
|
||||
zone->idleout = DNS_DEFAULT_IDLEOUT;
|
||||
ISC_LIST_INIT(zone->checkservers);
|
||||
zone->xfrsource = sockaddr_any;
|
||||
zone->xfr = NULL;
|
||||
zone->maxxfrin = MAX_XFER_TIME;
|
||||
zone->maxxfrout = MAX_XFER_TIME;
|
||||
zone->diff_on_reload = ISC_FALSE;
|
||||
@@ -2130,15 +2132,16 @@ soa_query(dns_zone_t *zone, isc_taskaction_t callback) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef notyet
|
||||
static void
|
||||
zone_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||
dns_zone_t *zone = (dns_zone_t *)event->arg;
|
||||
dns_zone_t *zone = (dns_zone_t *) event->arg;
|
||||
isc_event_free(&event);
|
||||
task = task; /* XXX */
|
||||
zone = zone; /* XXX */
|
||||
UNUSED(task);
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
zone_log(zone, "zone_shutdown", ISC_LOG_DEBUG(3), "shutting down");
|
||||
if (zone->xfr != NULL)
|
||||
dns_xfrin_shutdown(zone->xfr);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
zone_timer(isc_task_t *task, isc_event_t *event) {
|
||||
@@ -2911,6 +2914,7 @@ xfrdone(dns_zone_t *zone, isc_result_t result) {
|
||||
LOCK(&zone->lock);
|
||||
INSIST((zone->flags & DNS_ZONE_F_REFRESH) != 0);
|
||||
zone->flags &= ~DNS_ZONE_F_REFRESH;
|
||||
|
||||
switch (result) {
|
||||
case DNS_R_UPTODATE:
|
||||
case DNS_R_SUCCESS:
|
||||
@@ -2934,6 +2938,20 @@ xfrdone(dns_zone_t *zone, isc_result_t result) {
|
||||
break;
|
||||
}
|
||||
UNLOCK(&zone->lock);
|
||||
|
||||
/*
|
||||
* If creating the transfer object failed, zone->xfr is NULL.
|
||||
* Otherwise, we are called as the done callback of a zone
|
||||
* transfer object that just entered its shutting-down
|
||||
* state. Since we are no longer responsible for shutting
|
||||
* it down, we can detach our reference.
|
||||
*/
|
||||
if (zone->xfr != NULL)
|
||||
dns_xfrin_detach(&zone->xfr);
|
||||
|
||||
/*
|
||||
* Retry with a different server if necessary.
|
||||
*/
|
||||
if (again)
|
||||
xfrin_start_temporary_kludge(zone);
|
||||
}
|
||||
@@ -2944,8 +2962,10 @@ xfrdone(dns_zone_t *zone, isc_result_t result) {
|
||||
|
||||
static void
|
||||
xfrin_start_temporary_kludge(dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
isc_sockaddr_t sa;
|
||||
in_port_t port;
|
||||
|
||||
if (zone->masterscnt < 1)
|
||||
return;
|
||||
port = zone->masterport;
|
||||
@@ -2954,10 +2974,12 @@ xfrin_start_temporary_kludge(dns_zone_t *zone) {
|
||||
isc_sockaddr_fromin(&sa,
|
||||
&zone->masters[zone->curmaster].type.sin.sin_addr,
|
||||
port);
|
||||
dns_xfrin_start(zone, &sa, zone->mctx,
|
||||
zone->zmgr->taskmgr, zone->zmgr->timermgr,
|
||||
zone->zmgr->socketmgr,
|
||||
xfrdone);
|
||||
result = dns_xfrin_create(zone, &sa, zone->mctx,
|
||||
zone->zmgr->timermgr, zone->zmgr->socketmgr,
|
||||
zone->task,
|
||||
xfrdone, &zone->xfr);
|
||||
if (result != DNS_R_SUCCESS)
|
||||
xfrdone(zone, result);
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
@@ -3054,18 +3076,25 @@ dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
|
||||
zmgr->task, zone_timer, zone,
|
||||
&zone->timer);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto failure;
|
||||
goto cleanup_task;
|
||||
|
||||
result = isc_task_onshutdown(zone->task, zone_shutdown, zone);
|
||||
if (result != ISC_R_SUCCESS)
|
||||
goto cleanup_timer;
|
||||
|
||||
zone->zmgr = zmgr;
|
||||
ISC_LIST_APPEND(zmgr->zones, zone, link);
|
||||
|
||||
goto cleanup;
|
||||
goto unlock;
|
||||
|
||||
failure:
|
||||
cleanup_timer:
|
||||
isc_timer_detach(&zone->timer);
|
||||
|
||||
cleanup_task:
|
||||
if (zone->task != NULL)
|
||||
isc_task_detach(&zone->task);
|
||||
|
||||
cleanup:
|
||||
unlock:
|
||||
UNLOCK(&zone->lock);
|
||||
RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
|
||||
return (result);
|
||||
|
Reference in New Issue
Block a user