]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
changed arguments to dns_aml_checkrequest();
authorAndreas Gustafsson <source@isc.org>
Thu, 2 Dec 1999 22:31:13 +0000 (22:31 +0000)
committerAndreas Gustafsson <source@isc.org>
Thu, 2 Dec 1999 22:31:13 +0000 (22:31 +0000)
time out outgoing transfers (timeout is 2 hours for now);
new cleanup strategy

bin/named/xfrout.c

index 305e929d8c8c6ab364c6ae7f8a12daa4d6b7ea7f..d4655fe4a011385560642901a41577aaf68bd7f7 100644 (file)
@@ -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 */
                                      &region, 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);
+       }
 }