xfrin.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2008, 2011-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /* $Id$ */
00019 
00020 /*! \file */
00021 
00022 #include <config.h>
00023 
00024 #include <isc/mem.h>
00025 #include <isc/print.h>
00026 #include <isc/random.h>
00027 #include <isc/string.h>         /* Required for HP/UX (and others?) */
00028 #include <isc/task.h>
00029 #include <isc/timer.h>
00030 #include <isc/util.h>
00031 
00032 #include <dns/callbacks.h>
00033 #include <dns/db.h>
00034 #include <dns/diff.h>
00035 #include <dns/events.h>
00036 #include <dns/journal.h>
00037 #include <dns/log.h>
00038 #include <dns/message.h>
00039 #include <dns/rdataclass.h>
00040 #include <dns/rdatalist.h>
00041 #include <dns/rdataset.h>
00042 #include <dns/result.h>
00043 #include <dns/soa.h>
00044 #include <dns/tcpmsg.h>
00045 #include <dns/timer.h>
00046 #include <dns/tsig.h>
00047 #include <dns/view.h>
00048 #include <dns/xfrin.h>
00049 #include <dns/zone.h>
00050 
00051 #include <dst/dst.h>
00052 
00053 /*
00054  * Incoming AXFR and IXFR.
00055  */
00056 
00057 /*%
00058  * It would be non-sensical (or at least obtuse) to use FAIL() with an
00059  * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
00060  * from complaining about "end-of-loop code not reached".
00061  */
00062 #define FAIL(code) \
00063         do { result = (code);                                   \
00064                 if (result != ISC_R_SUCCESS) goto failure;      \
00065         } while (0)
00066 
00067 #define CHECK(op) \
00068         do { result = (op);                                     \
00069                 if (result != ISC_R_SUCCESS) goto failure;      \
00070         } while (0)
00071 
00072 /*%
00073  * The states of the *XFR state machine.  We handle both IXFR and AXFR
00074  * with a single integrated state machine because they cannot be distinguished
00075  * immediately - an AXFR response to an IXFR request can only be detected
00076  * when the first two (2) response RRs have already been received.
00077  */
00078 typedef enum {
00079         XFRST_SOAQUERY,
00080         XFRST_GOTSOA,
00081         XFRST_INITIALSOA,
00082         XFRST_FIRSTDATA,
00083         XFRST_IXFR_DELSOA,
00084         XFRST_IXFR_DEL,
00085         XFRST_IXFR_ADDSOA,
00086         XFRST_IXFR_ADD,
00087         XFRST_IXFR_END,
00088         XFRST_AXFR,
00089         XFRST_AXFR_END
00090 } xfrin_state_t;
00091 
00092 /*%
00093  * Incoming zone transfer context.
00094  */
00095 
00096 struct dns_xfrin_ctx {
00097         unsigned int            magic;
00098         isc_mem_t               *mctx;
00099         dns_zone_t              *zone;
00100 
00101         int                     refcount;
00102 
00103         isc_task_t              *task;
00104         isc_timer_t             *timer;
00105         isc_socketmgr_t         *socketmgr;
00106 
00107         int                     connects;       /*%< Connect in progress */
00108         int                     sends;          /*%< Send in progress */
00109         int                     recvs;          /*%< Receive in progress */
00110         isc_boolean_t           shuttingdown;
00111         isc_result_t            shutdown_result;
00112 
00113         dns_name_t              name;           /*%< Name of zone to transfer */
00114         dns_rdataclass_t        rdclass;
00115 
00116         isc_boolean_t           checkid;
00117         dns_messageid_t         id;
00118 
00119         /*%
00120          * Requested transfer type (dns_rdatatype_axfr or
00121          * dns_rdatatype_ixfr).  The actual transfer type
00122          * may differ due to IXFR->AXFR fallback.
00123          */
00124         dns_rdatatype_t         reqtype;
00125         isc_dscp_t              dscp;
00126 
00127         isc_sockaddr_t          masteraddr;
00128         isc_sockaddr_t          sourceaddr;
00129         isc_socket_t            *socket;
00130 
00131         /*% Buffer for IXFR/AXFR request message */
00132         isc_buffer_t            qbuffer;
00133         unsigned char           qbuffer_data[512];
00134 
00135         /*% Incoming reply TCP message */
00136         dns_tcpmsg_t            tcpmsg;
00137         isc_boolean_t           tcpmsg_valid;
00138 
00139         dns_db_t                *db;
00140         dns_dbversion_t         *ver;
00141         dns_diff_t              diff;           /*%< Pending database changes */
00142         int                     difflen;        /*%< Number of pending tuples */
00143 
00144         xfrin_state_t           state;
00145         isc_uint32_t            end_serial;
00146         isc_boolean_t           is_ixfr;
00147 
00148         unsigned int            nmsg;           /*%< Number of messages recvd */
00149         unsigned int            nrecs;          /*%< Number of records recvd */
00150         isc_uint64_t            nbytes;         /*%< Number of bytes received */
00151 
00152         isc_time_t              start;          /*%< Start time of the transfer */
00153         isc_time_t              end;            /*%< End time of the transfer */
00154 
00155         dns_tsigkey_t           *tsigkey;       /*%< Key used to create TSIG */
00156         isc_buffer_t            *lasttsig;      /*%< The last TSIG */
00157         dst_context_t           *tsigctx;       /*%< TSIG verification context */
00158         unsigned int            sincetsig;      /*%< recvd since the last TSIG */
00159         dns_xfrindone_t         done;
00160 
00161         /*%
00162          * AXFR- and IXFR-specific data.  Only one is used at a time
00163          * according to the is_ixfr flag, so this could be a union,
00164          * but keeping them separate makes it a bit simpler to clean
00165          * things up when destroying the context.
00166          */
00167         dns_rdatacallbacks_t    axfr;
00168 
00169         struct {
00170                 isc_uint32_t    request_serial;
00171                 isc_uint32_t    current_serial;
00172                 dns_journal_t   *journal;
00173 
00174         } ixfr;
00175 };
00176 
00177 #define XFRIN_MAGIC               ISC_MAGIC('X', 'f', 'r', 'I')
00178 #define VALID_XFRIN(x)            ISC_MAGIC_VALID(x, XFRIN_MAGIC)
00179 
00180 /**************************************************************************/
00181 /*
00182  * Forward declarations.
00183  */
00184 
00185 static isc_result_t
00186 xfrin_create(isc_mem_t *mctx,
00187              dns_zone_t *zone,
00188              dns_db_t *db,
00189              isc_task_t *task,
00190              isc_timermgr_t *timermgr,
00191              isc_socketmgr_t *socketmgr,
00192              dns_name_t *zonename,
00193              dns_rdataclass_t rdclass,
00194              dns_rdatatype_t reqtype,
00195              isc_sockaddr_t *masteraddr,
00196              isc_sockaddr_t *sourceaddr,
00197              isc_dscp_t dscp,
00198              dns_tsigkey_t *tsigkey,
00199              dns_xfrin_ctx_t **xfrp);
00200 
00201 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
00202 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
00203 static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
00204                                    dns_name_t *name, dns_ttl_t ttl,
00205                                    dns_rdata_t *rdata);
00206 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
00207 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
00208 static isc_result_t axfr_finalize(dns_xfrin_ctx_t *xfr);
00209 
00210 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
00211 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
00212 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
00213                                  dns_name_t *name, dns_ttl_t ttl,
00214                                  dns_rdata_t *rdata);
00215 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
00216 
00217 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
00218                            isc_uint32_t ttl, dns_rdata_t *rdata);
00219 
00220 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
00221 
00222 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
00223 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
00224 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
00225 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
00226 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
00227 
00228 static void maybe_free(dns_xfrin_ctx_t *xfr);
00229 
00230 static void
00231 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
00232 static isc_result_t
00233 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
00234 
00235 static void
00236 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
00237            const char *fmt, va_list ap)
00238      ISC_FORMAT_PRINTF(4, 0);
00239 
00240 static void
00241 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
00242            const char *fmt, ...)
00243      ISC_FORMAT_PRINTF(4, 5);
00244 
00245 static void
00246 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
00247      ISC_FORMAT_PRINTF(3, 4);
00248 
00249 /**************************************************************************/
00250 /*
00251  * AXFR handling
00252  */
00253 
00254 static isc_result_t
00255 axfr_init(dns_xfrin_ctx_t *xfr) {
00256         isc_result_t result;
00257 
00258         xfr->is_ixfr = ISC_FALSE;
00259 
00260         if (xfr->db != NULL)
00261                 dns_db_detach(&xfr->db);
00262 
00263         CHECK(axfr_makedb(xfr, &xfr->db));
00264         dns_rdatacallbacks_init(&xfr->axfr);
00265         CHECK(dns_db_beginload(xfr->db, &xfr->axfr));
00266         result = ISC_R_SUCCESS;
00267  failure:
00268         return (result);
00269 }
00270 
00271 static isc_result_t
00272 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
00273         isc_result_t result;
00274 
00275         result = dns_db_create(xfr->mctx, /* XXX */
00276                                "rbt",   /* XXX guess */
00277                                &xfr->name,
00278                                dns_dbtype_zone,
00279                                xfr->rdclass,
00280                                0, NULL, /* XXX guess */
00281                                dbp);
00282         if (result == ISC_R_SUCCESS)
00283                 dns_zone_rpz_enable_db(xfr->zone, *dbp);
00284         return (result);
00285 }
00286 
00287 static isc_result_t
00288 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
00289              dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
00290 {
00291         isc_result_t result;
00292 
00293         dns_difftuple_t *tuple = NULL;
00294 
00295         CHECK(dns_zone_checknames(xfr->zone, name, rdata));
00296         CHECK(dns_difftuple_create(xfr->diff.mctx, op,
00297                                    name, ttl, rdata, &tuple));
00298         dns_diff_append(&xfr->diff, &tuple);
00299         if (++xfr->difflen > 100)
00300                 CHECK(axfr_apply(xfr));
00301         result = ISC_R_SUCCESS;
00302  failure:
00303         return (result);
00304 }
00305 
00306 /*
00307  * Store a set of AXFR RRs in the database.
00308  */
00309 static isc_result_t
00310 axfr_apply(dns_xfrin_ctx_t *xfr) {
00311         isc_result_t result;
00312 
00313         CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private));
00314         xfr->difflen = 0;
00315         dns_diff_clear(&xfr->diff);
00316         result = ISC_R_SUCCESS;
00317  failure:
00318         return (result);
00319 }
00320 
00321 static isc_result_t
00322 axfr_commit(dns_xfrin_ctx_t *xfr) {
00323         isc_result_t result;
00324 
00325         CHECK(axfr_apply(xfr));
00326         CHECK(dns_db_endload(xfr->db, &xfr->axfr));
00327 
00328         result = ISC_R_SUCCESS;
00329  failure:
00330         return (result);
00331 }
00332 
00333 static isc_result_t
00334 axfr_finalize(dns_xfrin_ctx_t *xfr) {
00335         isc_result_t result;
00336 
00337         CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
00338 
00339         result = ISC_R_SUCCESS;
00340  failure:
00341         return (result);
00342 }
00343 
00344 /**************************************************************************/
00345 /*
00346  * IXFR handling
00347  */
00348 
00349 static isc_result_t
00350 ixfr_init(dns_xfrin_ctx_t *xfr) {
00351         isc_result_t result;
00352         char *journalfile;
00353 
00354         if (xfr->reqtype != dns_rdatatype_ixfr) {
00355                 xfrin_log(xfr, ISC_LOG_ERROR,
00356                           "got incremental response to AXFR request");
00357                 return (DNS_R_FORMERR);
00358         }
00359 
00360         xfr->is_ixfr = ISC_TRUE;
00361         INSIST(xfr->db != NULL);
00362         xfr->difflen = 0;
00363 
00364         journalfile = dns_zone_getjournal(xfr->zone);
00365         if (journalfile != NULL)
00366                 CHECK(dns_journal_open(xfr->mctx, journalfile,
00367                                        DNS_JOURNAL_CREATE, &xfr->ixfr.journal));
00368 
00369         result = ISC_R_SUCCESS;
00370  failure:
00371         return (result);
00372 }
00373 
00374 static isc_result_t
00375 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
00376              dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
00377 {
00378         isc_result_t result;
00379 
00380         dns_difftuple_t *tuple = NULL;
00381         if (op == DNS_DIFFOP_ADD)
00382                 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
00383         CHECK(dns_difftuple_create(xfr->diff.mctx, op,
00384                                    name, ttl, rdata, &tuple));
00385         dns_diff_append(&xfr->diff, &tuple);
00386         if (++xfr->difflen > 100)
00387                 CHECK(ixfr_apply(xfr));
00388         result = ISC_R_SUCCESS;
00389  failure:
00390         return (result);
00391 }
00392 
00393 /*
00394  * Apply a set of IXFR changes to the database.
00395  */
00396 static isc_result_t
00397 ixfr_apply(dns_xfrin_ctx_t *xfr) {
00398         isc_result_t result;
00399 
00400         if (xfr->ver == NULL) {
00401                 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
00402                 if (xfr->ixfr.journal != NULL)
00403                         CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
00404         }
00405         CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
00406         if (xfr->ixfr.journal != NULL) {
00407                 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
00408                 if (result != ISC_R_SUCCESS)
00409                         goto failure;
00410         }
00411         dns_diff_clear(&xfr->diff);
00412         xfr->difflen = 0;
00413         result = ISC_R_SUCCESS;
00414  failure:
00415         return (result);
00416 }
00417 
00418 static isc_result_t
00419 ixfr_commit(dns_xfrin_ctx_t *xfr) {
00420         isc_result_t result;
00421 
00422         CHECK(ixfr_apply(xfr));
00423         if (xfr->ver != NULL) {
00424                 /* XXX enter ready-to-commit state here */
00425                 if (xfr->ixfr.journal != NULL)
00426                         CHECK(dns_journal_commit(xfr->ixfr.journal));
00427                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
00428                 dns_zone_markdirty(xfr->zone);
00429         }
00430         result = ISC_R_SUCCESS;
00431  failure:
00432         return (result);
00433 }
00434 
00435 /**************************************************************************/
00436 /*
00437  * Common AXFR/IXFR protocol code
00438  */
00439 
00440 /*
00441  * Handle a single incoming resource record according to the current
00442  * state.
00443  */
00444 static isc_result_t
00445 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
00446        dns_rdata_t *rdata)
00447 {
00448         isc_result_t result;
00449 
00450         xfr->nrecs++;
00451 
00452         if (rdata->type == dns_rdatatype_none ||
00453             dns_rdatatype_ismeta(rdata->type))
00454                 FAIL(DNS_R_FORMERR);
00455 
00456  redo:
00457         switch (xfr->state) {
00458         case XFRST_SOAQUERY:
00459                 if (rdata->type != dns_rdatatype_soa) {
00460                         xfrin_log(xfr, ISC_LOG_ERROR,
00461                                   "non-SOA response to SOA query");
00462                         FAIL(DNS_R_FORMERR);
00463                 }
00464                 xfr->end_serial = dns_soa_getserial(rdata);
00465                 if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
00466                     !dns_zone_isforced(xfr->zone)) {
00467                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
00468                                   "requested serial %u, "
00469                                   "master has %u, not updating",
00470                                   xfr->ixfr.request_serial, xfr->end_serial);
00471                         FAIL(DNS_R_UPTODATE);
00472                 }
00473                 xfr->state = XFRST_GOTSOA;
00474                 break;
00475 
00476         case XFRST_GOTSOA:
00477                 /*
00478                  * Skip other records in the answer section.
00479                  */
00480                 break;
00481 
00482         case XFRST_INITIALSOA:
00483                 if (rdata->type != dns_rdatatype_soa) {
00484                         xfrin_log(xfr, ISC_LOG_ERROR,
00485                                   "first RR in zone transfer must be SOA");
00486                         FAIL(DNS_R_FORMERR);
00487                 }
00488                 /*
00489                  * Remember the serial number in the initial SOA.
00490                  * We need it to recognize the end of an IXFR.
00491                  */
00492                 xfr->end_serial = dns_soa_getserial(rdata);
00493                 if (xfr->reqtype == dns_rdatatype_ixfr &&
00494                     ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
00495                     && !dns_zone_isforced(xfr->zone))
00496                 {
00497                         /*
00498                          * This must be the single SOA record that is
00499                          * sent when the current version on the master
00500                          * is not newer than the version in the request.
00501                          */
00502                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
00503                                   "requested serial %u, "
00504                                   "master has %u, not updating",
00505                                   xfr->ixfr.request_serial, xfr->end_serial);
00506                         FAIL(DNS_R_UPTODATE);
00507                 }
00508                 if (xfr->reqtype == dns_rdatatype_axfr)
00509                         xfr->checkid = ISC_FALSE;
00510                 xfr->state = XFRST_FIRSTDATA;
00511                 break;
00512 
00513         case XFRST_FIRSTDATA:
00514                 /*
00515                  * If the transfer begins with one SOA record, it is an AXFR,
00516                  * if it begins with two SOAs, it is an IXFR.
00517                  */
00518                 if (xfr->reqtype == dns_rdatatype_ixfr &&
00519                     rdata->type == dns_rdatatype_soa &&
00520                     xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
00521                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
00522                                   "got incremental response");
00523                         CHECK(ixfr_init(xfr));
00524                         xfr->state = XFRST_IXFR_DELSOA;
00525                 } else {
00526                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
00527                                   "got nonincremental response");
00528                         CHECK(axfr_init(xfr));
00529                         xfr->state = XFRST_AXFR;
00530                 }
00531                 goto redo;
00532 
00533         case XFRST_IXFR_DELSOA:
00534                 INSIST(rdata->type == dns_rdatatype_soa);
00535                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
00536                 xfr->state = XFRST_IXFR_DEL;
00537                 break;
00538 
00539         case XFRST_IXFR_DEL:
00540                 if (rdata->type == dns_rdatatype_soa) {
00541                         isc_uint32_t soa_serial = dns_soa_getserial(rdata);
00542                         xfr->state = XFRST_IXFR_ADDSOA;
00543                         xfr->ixfr.current_serial = soa_serial;
00544                         goto redo;
00545                 }
00546                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
00547                 break;
00548 
00549         case XFRST_IXFR_ADDSOA:
00550                 INSIST(rdata->type == dns_rdatatype_soa);
00551                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
00552                 xfr->state = XFRST_IXFR_ADD;
00553                 break;
00554 
00555         case XFRST_IXFR_ADD:
00556                 if (rdata->type == dns_rdatatype_soa) {
00557                         isc_uint32_t soa_serial = dns_soa_getserial(rdata);
00558                         if (soa_serial == xfr->end_serial) {
00559                                 CHECK(ixfr_commit(xfr));
00560                                 xfr->state = XFRST_IXFR_END;
00561                                 break;
00562                         } else if (soa_serial != xfr->ixfr.current_serial) {
00563                                 xfrin_log(xfr, ISC_LOG_ERROR,
00564                                           "IXFR out of sync: "
00565                                           "expected serial %u, got %u",
00566                                           xfr->ixfr.current_serial, soa_serial);
00567                                 FAIL(DNS_R_FORMERR);
00568                         } else {
00569                                 CHECK(ixfr_commit(xfr));
00570                                 xfr->state = XFRST_IXFR_DELSOA;
00571                                 goto redo;
00572                         }
00573                 }
00574                 if (rdata->type == dns_rdatatype_ns &&
00575                     dns_name_iswildcard(name))
00576                         FAIL(DNS_R_INVALIDNS);
00577                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
00578                 break;
00579 
00580         case XFRST_AXFR:
00581                 /*
00582                  * Old BINDs sent cross class A records for non IN classes.
00583                  */
00584                 if (rdata->type == dns_rdatatype_a &&
00585                     rdata->rdclass != xfr->rdclass &&
00586                     xfr->rdclass != dns_rdataclass_in)
00587                         break;
00588                 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
00589                 if (rdata->type == dns_rdatatype_soa) {
00590                         CHECK(axfr_commit(xfr));
00591                         xfr->state = XFRST_AXFR_END;
00592                         break;
00593                 }
00594                 break;
00595         case XFRST_AXFR_END:
00596         case XFRST_IXFR_END:
00597                 FAIL(DNS_R_EXTRADATA);
00598                 /* NOTREACHED */
00599         default:
00600                 INSIST(0);
00601                 break;
00602         }
00603         result = ISC_R_SUCCESS;
00604  failure:
00605         return (result);
00606 }
00607 
00608 isc_result_t
00609 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
00610                  isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
00611                  isc_mem_t *mctx, isc_timermgr_t *timermgr,
00612                  isc_socketmgr_t *socketmgr, isc_task_t *task,
00613                  dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
00614 {
00615         isc_sockaddr_t sourceaddr;
00616         isc_dscp_t dscp;
00617 
00618         switch (isc_sockaddr_pf(masteraddr)) {
00619         case PF_INET:
00620                 sourceaddr = *dns_zone_getxfrsource4(zone);
00621                 dscp = dns_zone_getxfrsource4dscp(zone);
00622                 break;
00623         case PF_INET6:
00624                 sourceaddr = *dns_zone_getxfrsource6(zone);
00625                 dscp = dns_zone_getxfrsource6dscp(zone);
00626                 break;
00627         default:
00628                 INSIST(0);
00629         }
00630 
00631         return(dns_xfrin_create3(zone, xfrtype, masteraddr, &sourceaddr,
00632                                  dscp, tsigkey, mctx, timermgr, socketmgr,
00633                                  task, done, xfrp));
00634 }
00635 
00636 isc_result_t
00637 dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
00638                   isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
00639                   dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
00640                   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
00641                   isc_task_t *task, dns_xfrindone_t done,
00642                   dns_xfrin_ctx_t **xfrp)
00643 {
00644         return (dns_xfrin_create3(zone, xfrtype, masteraddr, sourceaddr, -1,
00645                                   tsigkey, mctx, timermgr, socketmgr, task,
00646                                   done, xfrp));
00647 }
00648 
00649 isc_result_t
00650 dns_xfrin_create3(dns_zone_t *zone, dns_rdatatype_t xfrtype,
00651                   isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
00652                   isc_dscp_t dscp, dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
00653                   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
00654                   isc_task_t *task, dns_xfrindone_t done,
00655                   dns_xfrin_ctx_t **xfrp)
00656 {
00657         dns_name_t *zonename = dns_zone_getorigin(zone);
00658         dns_xfrin_ctx_t *xfr = NULL;
00659         isc_result_t result;
00660         dns_db_t *db = NULL;
00661 
00662         REQUIRE(xfrp != NULL && *xfrp == NULL);
00663 
00664         (void)dns_zone_getdb(zone, &db);
00665 
00666         if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
00667                 REQUIRE(db != NULL);
00668 
00669         CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
00670                            dns_zone_getclass(zone), xfrtype, masteraddr,
00671                            sourceaddr, dscp, tsigkey, &xfr));
00672 
00673         CHECK(xfrin_start(xfr));
00674 
00675         xfr->done = done;
00676         if (xfr->done != NULL)
00677                 xfr->refcount++;
00678         *xfrp = xfr;
00679 
00680  failure:
00681         if (db != NULL)
00682                 dns_db_detach(&db);
00683         if (result != ISC_R_SUCCESS) {
00684                 char zonetext[DNS_NAME_MAXTEXT+32];
00685                 dns_zone_name(zone, zonetext, sizeof(zonetext));
00686                 xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr,
00687                            "zone transfer setup failed");
00688         }
00689         return (result);
00690 }
00691 
00692 void
00693 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
00694         if (! xfr->shuttingdown)
00695                 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
00696 }
00697 
00698 void
00699 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
00700         REQUIRE(target != NULL && *target == NULL);
00701         source->refcount++;
00702         *target = source;
00703 }
00704 
00705 void
00706 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
00707         dns_xfrin_ctx_t *xfr = *xfrp;
00708         INSIST(xfr->refcount > 0);
00709         xfr->refcount--;
00710         maybe_free(xfr);
00711         *xfrp = NULL;
00712 }
00713 
00714 static void
00715 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
00716         if (xfr->connects > 0) {
00717                 isc_socket_cancel(xfr->socket, xfr->task,
00718                                   ISC_SOCKCANCEL_CONNECT);
00719         } else if (xfr->recvs > 0) {
00720                 dns_tcpmsg_cancelread(&xfr->tcpmsg);
00721         } else if (xfr->sends > 0) {
00722                 isc_socket_cancel(xfr->socket, xfr->task,
00723                                   ISC_SOCKCANCEL_SEND);
00724         }
00725 }
00726 
00727 static void
00728 xfrin_reset(dns_xfrin_ctx_t *xfr) {
00729         REQUIRE(VALID_XFRIN(xfr));
00730 
00731         xfrin_log(xfr, ISC_LOG_INFO, "resetting");
00732 
00733         xfrin_cancelio(xfr);
00734 
00735         if (xfr->socket != NULL)
00736                 isc_socket_detach(&xfr->socket);
00737 
00738         if (xfr->lasttsig != NULL)
00739                 isc_buffer_free(&xfr->lasttsig);
00740 
00741         dns_diff_clear(&xfr->diff);
00742         xfr->difflen = 0;
00743 
00744         if (xfr->ixfr.journal != NULL)
00745                 dns_journal_destroy(&xfr->ixfr.journal);
00746 
00747         if (xfr->axfr.add_private != NULL)
00748                 (void)dns_db_endload(xfr->db, &xfr->axfr);
00749 
00750         if (xfr->tcpmsg_valid) {
00751                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
00752                 xfr->tcpmsg_valid = ISC_FALSE;
00753         }
00754 
00755         if (xfr->ver != NULL)
00756                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
00757 }
00758 
00759 
00760 static void
00761 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
00762         if (result != DNS_R_UPTODATE) {
00763                 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
00764                           msg, isc_result_totext(result));
00765                 if (xfr->is_ixfr)
00766                         /* Pass special result code to force AXFR retry */
00767                         result = DNS_R_BADIXFR;
00768         }
00769         xfrin_cancelio(xfr);
00770         /*
00771          * Close the journal.
00772          */
00773         if (xfr->ixfr.journal != NULL)
00774                 dns_journal_destroy(&xfr->ixfr.journal);
00775         if (xfr->done != NULL) {
00776                 (xfr->done)(xfr->zone, result);
00777                 xfr->done = NULL;
00778         }
00779         xfr->shuttingdown = ISC_TRUE;
00780         xfr->shutdown_result = result;
00781         maybe_free(xfr);
00782 }
00783 
00784 static isc_result_t
00785 xfrin_create(isc_mem_t *mctx,
00786              dns_zone_t *zone,
00787              dns_db_t *db,
00788              isc_task_t *task,
00789              isc_timermgr_t *timermgr,
00790              isc_socketmgr_t *socketmgr,
00791              dns_name_t *zonename,
00792              dns_rdataclass_t rdclass,
00793              dns_rdatatype_t reqtype,
00794              isc_sockaddr_t *masteraddr,
00795              isc_sockaddr_t *sourceaddr,
00796              isc_dscp_t dscp,
00797              dns_tsigkey_t *tsigkey,
00798              dns_xfrin_ctx_t **xfrp)
00799 {
00800         dns_xfrin_ctx_t *xfr = NULL;
00801         isc_result_t result;
00802         isc_uint32_t tmp;
00803 
00804         xfr = isc_mem_get(mctx, sizeof(*xfr));
00805         if (xfr == NULL)
00806                 return (ISC_R_NOMEMORY);
00807         xfr->mctx = NULL;
00808         isc_mem_attach(mctx, &xfr->mctx);
00809         xfr->refcount = 0;
00810         xfr->zone = NULL;
00811         dns_zone_iattach(zone, &xfr->zone);
00812         xfr->task = NULL;
00813         isc_task_attach(task, &xfr->task);
00814         xfr->timer = NULL;
00815         xfr->socketmgr = socketmgr;
00816         xfr->done = NULL;
00817 
00818         xfr->connects = 0;
00819         xfr->sends = 0;
00820         xfr->recvs = 0;
00821         xfr->shuttingdown = ISC_FALSE;
00822         xfr->shutdown_result = ISC_R_UNSET;
00823 
00824         dns_name_init(&xfr->name, NULL);
00825         xfr->rdclass = rdclass;
00826         isc_random_get(&tmp);
00827         xfr->checkid = ISC_TRUE;
00828         xfr->id = (isc_uint16_t)(tmp & 0xffff);
00829         xfr->reqtype = reqtype;
00830         xfr->dscp = dscp;
00831 
00832         /* sockaddr */
00833         xfr->socket = NULL;
00834         /* qbuffer */
00835         /* qbuffer_data */
00836         /* tcpmsg */
00837         xfr->tcpmsg_valid = ISC_FALSE;
00838 
00839         xfr->db = NULL;
00840         if (db != NULL)
00841                 dns_db_attach(db, &xfr->db);
00842         xfr->ver = NULL;
00843         dns_diff_init(xfr->mctx, &xfr->diff);
00844         xfr->difflen = 0;
00845 
00846         if (reqtype == dns_rdatatype_soa)
00847                 xfr->state = XFRST_SOAQUERY;
00848         else
00849                 xfr->state = XFRST_INITIALSOA;
00850         /* end_serial */
00851 
00852         xfr->nmsg = 0;
00853         xfr->nrecs = 0;
00854         xfr->nbytes = 0;
00855         isc_time_now(&xfr->start);
00856 
00857         xfr->tsigkey = NULL;
00858         if (tsigkey != NULL)
00859                 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
00860         xfr->lasttsig = NULL;
00861         xfr->tsigctx = NULL;
00862         xfr->sincetsig = 0;
00863         xfr->is_ixfr = ISC_FALSE;
00864 
00865         /* ixfr.request_serial */
00866         /* ixfr.current_serial */
00867         xfr->ixfr.journal = NULL;
00868 
00869         xfr->axfr.add = NULL;
00870         xfr->axfr.add_private = NULL;
00871 
00872         CHECK(dns_name_dup(zonename, mctx, &xfr->name));
00873 
00874         CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
00875                                task, xfrin_timeout, xfr, &xfr->timer));
00876         CHECK(dns_timer_setidle(xfr->timer,
00877                                 dns_zone_getmaxxfrin(xfr->zone),
00878                                 dns_zone_getidlein(xfr->zone),
00879                                 ISC_FALSE));
00880 
00881         xfr->masteraddr = *masteraddr;
00882 
00883         INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
00884         xfr->sourceaddr = *sourceaddr;
00885         isc_sockaddr_setport(&xfr->sourceaddr, 0);
00886 
00887         /*
00888          * Reserve 2 bytes for TCP length at the begining of the buffer.
00889          */
00890         isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2],
00891                         sizeof(xfr->qbuffer_data) - 2);
00892 
00893         xfr->magic = XFRIN_MAGIC;
00894         *xfrp = xfr;
00895         return (ISC_R_SUCCESS);
00896 
00897  failure:
00898         if (xfr->timer != NULL)
00899                 isc_timer_detach(&xfr->timer);
00900         if (dns_name_dynamic(&xfr->name))
00901                 dns_name_free(&xfr->name, xfr->mctx);
00902         if (xfr->tsigkey != NULL)
00903                 dns_tsigkey_detach(&xfr->tsigkey);
00904         if (xfr->db != NULL)
00905                 dns_db_detach(&xfr->db);
00906         isc_task_detach(&xfr->task);
00907         dns_zone_idetach(&xfr->zone);
00908         isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
00909 
00910         return (result);
00911 }
00912 
00913 static isc_result_t
00914 xfrin_start(dns_xfrin_ctx_t *xfr) {
00915         isc_result_t result;
00916         CHECK(isc_socket_create(xfr->socketmgr,
00917                                 isc_sockaddr_pf(&xfr->sourceaddr),
00918                                 isc_sockettype_tcp,
00919                                 &xfr->socket));
00920         isc_socket_setname(xfr->socket, "xfrin", NULL);
00921 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
00922         CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
00923                               ISC_SOCKET_REUSEADDRESS));
00924 #endif
00925         isc_socket_dscp(xfr->socket, xfr->dscp);
00926         CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
00927                                  xfrin_connect_done, xfr));
00928         xfr->connects++;
00929         return (ISC_R_SUCCESS);
00930  failure:
00931         xfrin_fail(xfr, result, "failed setting up socket");
00932         return (result);
00933 }
00934 
00935 /* XXX the resolver could use this, too */
00936 
00937 static isc_result_t
00938 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
00939         dns_compress_t cctx;
00940         isc_boolean_t cleanup_cctx = ISC_FALSE;
00941         isc_result_t result;
00942 
00943         CHECK(dns_compress_init(&cctx, -1, mctx));
00944         cleanup_cctx = ISC_TRUE;
00945         CHECK(dns_message_renderbegin(msg, &cctx, buf));
00946         CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
00947         CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
00948         CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
00949         CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
00950         CHECK(dns_message_renderend(msg));
00951         result = ISC_R_SUCCESS;
00952  failure:
00953         if (cleanup_cctx)
00954                 dns_compress_invalidate(&cctx);
00955         return (result);
00956 }
00957 
00958 /*
00959  * A connection has been established.
00960  */
00961 static void
00962 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
00963         isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
00964         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
00965         isc_result_t result = cev->result;
00966         char sourcetext[ISC_SOCKADDR_FORMATSIZE];
00967         isc_sockaddr_t sockaddr;
00968         dns_zonemgr_t * zmgr;
00969         isc_time_t now;
00970 
00971         REQUIRE(VALID_XFRIN(xfr));
00972 
00973         UNUSED(task);
00974 
00975         INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
00976         isc_event_free(&event);
00977 
00978         xfr->connects--;
00979         if (xfr->shuttingdown) {
00980                 maybe_free(xfr);
00981                 return;
00982         }
00983 
00984         zmgr = dns_zone_getmgr(xfr->zone);
00985         if (zmgr != NULL) {
00986                 if (result != ISC_R_SUCCESS) {
00987                         TIME_NOW(&now);
00988                         dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
00989                                                    &xfr->sourceaddr, &now);
00990                         goto failure;
00991                 } else
00992                         dns_zonemgr_unreachabledel(zmgr, &xfr->masteraddr,
00993                                                    &xfr->sourceaddr);
00994         }
00995 
00996         result = isc_socket_getsockname(xfr->socket, &sockaddr);
00997         if (result == ISC_R_SUCCESS) {
00998                 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
00999         } else
01000                 strcpy(sourcetext, "<UNKNOWN>");
01001         xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
01002 
01003         dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
01004         xfr->tcpmsg_valid = ISC_TRUE;
01005 
01006         CHECK(xfrin_send_request(xfr));
01007  failure:
01008         if (result != ISC_R_SUCCESS)
01009                 xfrin_fail(xfr, result, "failed to connect");
01010 }
01011 
01012 /*
01013  * Convert a tuple into a dns_name_t suitable for inserting
01014  * into the given dns_message_t.
01015  */
01016 static isc_result_t
01017 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
01018 {
01019         isc_result_t result;
01020         dns_rdata_t *rdata = NULL;
01021         dns_rdatalist_t *rdl = NULL;
01022         dns_rdataset_t *rds = NULL;
01023         dns_name_t *name = NULL;
01024 
01025         REQUIRE(target != NULL && *target == NULL);
01026 
01027         CHECK(dns_message_gettemprdata(msg, &rdata));
01028         dns_rdata_init(rdata);
01029         dns_rdata_clone(&tuple->rdata, rdata);
01030 
01031         CHECK(dns_message_gettemprdatalist(msg, &rdl));
01032         dns_rdatalist_init(rdl);
01033         rdl->type = tuple->rdata.type;
01034         rdl->rdclass = tuple->rdata.rdclass;
01035         rdl->ttl = tuple->ttl;
01036         ISC_LIST_APPEND(rdl->rdata, rdata, link);
01037 
01038         CHECK(dns_message_gettemprdataset(msg, &rds));
01039         dns_rdataset_init(rds);
01040         CHECK(dns_rdatalist_tordataset(rdl, rds));
01041 
01042         CHECK(dns_message_gettempname(msg, &name));
01043         dns_name_init(name, NULL);
01044         dns_name_clone(&tuple->name, name);
01045         ISC_LIST_APPEND(name->list, rds, link);
01046 
01047         *target = name;
01048         return (ISC_R_SUCCESS);
01049 
01050  failure:
01051 
01052         if (rds != NULL) {
01053                 dns_rdataset_disassociate(rds);
01054                 dns_message_puttemprdataset(msg, &rds);
01055         }
01056         if (rdl != NULL) {
01057                 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
01058                 dns_message_puttemprdatalist(msg, &rdl);
01059         }
01060         if (rdata != NULL)
01061                 dns_message_puttemprdata(msg, &rdata);
01062 
01063         return (result);
01064 }
01065 
01066 
01067 /*
01068  * Build an *XFR request and send its length prefix.
01069  */
01070 static isc_result_t
01071 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
01072         isc_result_t result;
01073         isc_region_t region;
01074         dns_rdataset_t *qrdataset = NULL;
01075         dns_message_t *msg = NULL;
01076         dns_difftuple_t *soatuple = NULL;
01077         dns_name_t *qname = NULL;
01078         dns_dbversion_t *ver = NULL;
01079         dns_name_t *msgsoaname = NULL;
01080 
01081         /* Create the request message */
01082         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
01083         CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
01084 
01085         /* Create a name for the question section. */
01086         CHECK(dns_message_gettempname(msg, &qname));
01087         dns_name_init(qname, NULL);
01088         dns_name_clone(&xfr->name, qname);
01089 
01090         /* Formulate the question and attach it to the question name. */
01091         CHECK(dns_message_gettemprdataset(msg, &qrdataset));
01092         dns_rdataset_init(qrdataset);
01093         dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
01094         ISC_LIST_APPEND(qname->list, qrdataset, link);
01095         qrdataset = NULL;
01096 
01097         dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
01098         qname = NULL;
01099 
01100         if (xfr->reqtype == dns_rdatatype_ixfr) {
01101                 /* Get the SOA and add it to the authority section. */
01102                 /* XXX is using the current version the right thing? */
01103                 dns_db_currentversion(xfr->db, &ver);
01104                 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
01105                                             DNS_DIFFOP_EXISTS, &soatuple));
01106                 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
01107                 xfr->ixfr.current_serial = xfr->ixfr.request_serial;
01108                 xfrin_log(xfr, ISC_LOG_DEBUG(3),
01109                           "requesting IXFR for serial %u",
01110                           xfr->ixfr.request_serial);
01111 
01112                 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
01113                 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
01114         } else if (xfr->reqtype == dns_rdatatype_soa)
01115                 CHECK(dns_db_getsoaserial(xfr->db, NULL,
01116                                           &xfr->ixfr.request_serial));
01117 
01118         xfr->checkid = ISC_TRUE;
01119         xfr->id++;
01120         xfr->nmsg = 0;
01121         xfr->nrecs = 0;
01122         xfr->nbytes = 0;
01123         isc_time_now(&xfr->start);
01124         msg->id = xfr->id;
01125         if (xfr->tsigctx != NULL)
01126                 dst_context_destroy(&xfr->tsigctx);
01127 
01128         CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
01129 
01130         /*
01131          * Free the last tsig, if there is one.
01132          */
01133         if (xfr->lasttsig != NULL)
01134                 isc_buffer_free(&xfr->lasttsig);
01135 
01136         /*
01137          * Save the query TSIG and don't let message_destroy free it.
01138          */
01139         CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
01140 
01141         isc_buffer_usedregion(&xfr->qbuffer, &region);
01142         INSIST(region.length <= 65535);
01143 
01144         /*
01145          * Record message length and adjust region to include TCP
01146          * length field.
01147          */
01148         xfr->qbuffer_data[0] = (region.length >> 8) & 0xff;
01149         xfr->qbuffer_data[1] = region.length & 0xff;
01150         region.base -= 2;
01151         region.length += 2;
01152         CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
01153                               xfrin_send_done, xfr));
01154         xfr->sends++;
01155 
01156  failure:
01157         if (qname != NULL)
01158                 dns_message_puttempname(msg, &qname);
01159         if (qrdataset != NULL)
01160                 dns_message_puttemprdataset(msg, &qrdataset);
01161         if (msg != NULL)
01162                 dns_message_destroy(&msg);
01163         if (soatuple != NULL)
01164                 dns_difftuple_free(&soatuple);
01165         if (ver != NULL)
01166                 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
01167         return (result);
01168 }
01169 
01170 static void
01171 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
01172         isc_socketevent_t *sev = (isc_socketevent_t *) event;
01173         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
01174         isc_result_t result;
01175 
01176         REQUIRE(VALID_XFRIN(xfr));
01177 
01178         UNUSED(task);
01179 
01180         INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
01181 
01182         xfr->sends--;
01183         xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
01184         CHECK(sev->result);
01185 
01186         CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
01187                                      xfrin_recv_done, xfr));
01188         xfr->recvs++;
01189  failure:
01190         isc_event_free(&event);
01191         if (result != ISC_R_SUCCESS)
01192                 xfrin_fail(xfr, result, "failed sending request data");
01193 }
01194 
01195 
01196 static void
01197 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
01198         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
01199         isc_result_t result;
01200         dns_message_t *msg = NULL;
01201         dns_name_t *name;
01202         dns_tcpmsg_t *tcpmsg;
01203         dns_name_t *tsigowner = NULL;
01204 
01205         REQUIRE(VALID_XFRIN(xfr));
01206 
01207         UNUSED(task);
01208 
01209         INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
01210         tcpmsg = ev->ev_sender;
01211         isc_event_free(&ev);
01212 
01213         xfr->recvs--;
01214         if (xfr->shuttingdown) {
01215                 maybe_free(xfr);
01216                 return;
01217         }
01218 
01219         CHECK(tcpmsg->result);
01220 
01221         xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
01222                   tcpmsg->buffer.used);
01223 
01224         CHECK(isc_timer_touch(xfr->timer));
01225 
01226         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
01227 
01228         CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
01229         CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
01230 
01231         msg->tsigctx = xfr->tsigctx;
01232         xfr->tsigctx = NULL;
01233 
01234         if (xfr->nmsg > 0)
01235                 msg->tcp_continuation = 1;
01236 
01237         result = dns_message_parse(msg, &tcpmsg->buffer,
01238                                    DNS_MESSAGEPARSE_PRESERVEORDER);
01239 
01240         if (result == ISC_R_SUCCESS)
01241                 dns_message_logpacket2(msg, "received message from",
01242                                        &tcpmsg->address,
01243                                        DNS_LOGCATEGORY_XFER_IN,
01244                                        DNS_LOGMODULE_XFER_IN,
01245                                        ISC_LOG_DEBUG(10), xfr->mctx);
01246         else
01247                 xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s",
01248                           dns_result_totext(result));
01249 
01250         if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
01251             (xfr->checkid && msg->id != xfr->id)) {
01252                 if (result == ISC_R_SUCCESS)
01253                         result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
01254                 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
01255                         result = DNS_R_UNEXPECTEDID;
01256                 if (xfr->reqtype == dns_rdatatype_axfr ||
01257                     xfr->reqtype == dns_rdatatype_soa)
01258                         goto failure;
01259                 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
01260                        isc_result_totext(result));
01261  try_axfr:
01262                 dns_message_destroy(&msg);
01263                 xfrin_reset(xfr);
01264                 xfr->reqtype = dns_rdatatype_soa;
01265                 xfr->state = XFRST_SOAQUERY;
01266                 (void)xfrin_start(xfr);
01267                 return;
01268         }
01269 
01270         /*
01271          * Does the server know about IXFR?  If it doesn't we will get
01272          * a message with a empty answer section or a potentially a CNAME /
01273          * DNAME, the later is handled by xfr_rr() which will return FORMERR
01274          * if the first RR in the answer section is not a SOA record.
01275          */
01276         if (xfr->reqtype == dns_rdatatype_ixfr &&
01277             xfr->state == XFRST_INITIALSOA &&
01278             msg->counts[DNS_SECTION_ANSWER] == 0) {
01279                 xfrin_log(xfr, ISC_LOG_DEBUG(3),
01280                           "empty answer section, retrying with AXFR");
01281                 goto try_axfr;
01282         }
01283 
01284         if (xfr->reqtype == dns_rdatatype_soa &&
01285             (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
01286                 FAIL(DNS_R_NOTAUTHORITATIVE);
01287         }
01288 
01289 
01290         result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
01291         if (result != ISC_R_SUCCESS) {
01292                 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
01293                        isc_result_totext(result));
01294                 goto failure;
01295         }
01296 
01297         for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
01298              result == ISC_R_SUCCESS;
01299              result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
01300         {
01301                 dns_rdataset_t *rds;
01302 
01303                 name = NULL;
01304                 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
01305                 for (rds = ISC_LIST_HEAD(name->list);
01306                      rds != NULL;
01307                      rds = ISC_LIST_NEXT(rds, link))
01308                 {
01309                         for (result = dns_rdataset_first(rds);
01310                              result == ISC_R_SUCCESS;
01311                              result = dns_rdataset_next(rds))
01312                         {
01313                                 dns_rdata_t rdata = DNS_RDATA_INIT;
01314                                 dns_rdataset_current(rds, &rdata);
01315                                 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
01316                         }
01317                 }
01318         }
01319         if (result != ISC_R_NOMORE)
01320                 goto failure;
01321 
01322         if (dns_message_gettsig(msg, &tsigowner) != NULL) {
01323                 /*
01324                  * Reset the counter.
01325                  */
01326                 xfr->sincetsig = 0;
01327 
01328                 /*
01329                  * Free the last tsig, if there is one.
01330                  */
01331                 if (xfr->lasttsig != NULL)
01332                         isc_buffer_free(&xfr->lasttsig);
01333 
01334                 /*
01335                  * Update the last tsig pointer.
01336                  */
01337                 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
01338                                                &xfr->lasttsig));
01339 
01340         } else if (dns_message_gettsigkey(msg) != NULL) {
01341                 xfr->sincetsig++;
01342                 if (xfr->sincetsig > 100 || xfr->nmsg == 0 ||
01343                     xfr->state == XFRST_AXFR_END ||
01344                     xfr->state == XFRST_IXFR_END)
01345                 {
01346                         result = DNS_R_EXPECTEDTSIG;
01347                         goto failure;
01348                 }
01349         }
01350 
01351         /*
01352          * Update the number of messages received.
01353          */
01354         xfr->nmsg++;
01355 
01356         /*
01357          * Update the number of bytes received.
01358          */
01359         xfr->nbytes += tcpmsg->buffer.used;
01360 
01361         /*
01362          * Take the context back.
01363          */
01364         INSIST(xfr->tsigctx == NULL);
01365         xfr->tsigctx = msg->tsigctx;
01366         msg->tsigctx = NULL;
01367 
01368         dns_message_destroy(&msg);
01369 
01370         switch (xfr->state) {
01371         case XFRST_GOTSOA:
01372                 xfr->reqtype = dns_rdatatype_axfr;
01373                 xfr->state = XFRST_INITIALSOA;
01374                 CHECK(xfrin_send_request(xfr));
01375                 break;
01376         case XFRST_AXFR_END:
01377                 CHECK(axfr_finalize(xfr));
01378                 /* FALLTHROUGH */
01379         case XFRST_IXFR_END:
01380                 /*
01381                  * Close the journal.
01382                  */
01383                 if (xfr->ixfr.journal != NULL)
01384                         dns_journal_destroy(&xfr->ixfr.journal);
01385 
01386                 /*
01387                  * Inform the caller we succeeded.
01388                  */
01389                 if (xfr->done != NULL) {
01390                         (xfr->done)(xfr->zone, ISC_R_SUCCESS);
01391                         xfr->done = NULL;
01392                 }
01393                 /*
01394                  * We should have no outstanding events at this
01395                  * point, thus maybe_free() should succeed.
01396                  */
01397                 xfr->shuttingdown = ISC_TRUE;
01398                 xfr->shutdown_result = ISC_R_SUCCESS;
01399                 maybe_free(xfr);
01400                 break;
01401         default:
01402                 /*
01403                  * Read the next message.
01404                  */
01405                 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
01406                                              xfrin_recv_done, xfr));
01407                 xfr->recvs++;
01408         }
01409         return;
01410 
01411  failure:
01412         if (msg != NULL)
01413                 dns_message_destroy(&msg);
01414         if (result != ISC_R_SUCCESS)
01415                 xfrin_fail(xfr, result, "failed while receiving responses");
01416 }
01417 
01418 static void
01419 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
01420         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
01421 
01422         REQUIRE(VALID_XFRIN(xfr));
01423 
01424         UNUSED(task);
01425 
01426         isc_event_free(&event);
01427         /*
01428          * This will log "giving up: timeout".
01429          */
01430         xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
01431 }
01432 
01433 static void
01434 maybe_free(dns_xfrin_ctx_t *xfr) {
01435         isc_uint64_t msecs;
01436         isc_uint64_t persec;
01437         const char *result_str;
01438 
01439         REQUIRE(VALID_XFRIN(xfr));
01440 
01441         if (! xfr->shuttingdown || xfr->refcount != 0 ||
01442             xfr->connects != 0 || xfr->sends != 0 ||
01443             xfr->recvs != 0)
01444                 return;
01445 
01446         INSIST(! xfr->shuttingdown || xfr->shutdown_result != ISC_R_UNSET);
01447 
01448         /* If we're called through dns_xfrin_detach() and are not
01449          * shutting down, we can't know what the transfer status is as
01450          * we are only called when the last reference is lost.
01451          */
01452         result_str = (xfr->shuttingdown ?
01453                       isc_result_totext(xfr->shutdown_result) : "unknown");
01454         xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", result_str);
01455 
01456         /*
01457          * Calculate the length of time the transfer took,
01458          * and print a log message with the bytes and rate.
01459          */
01460         isc_time_now(&xfr->end);
01461         msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
01462         if (msecs == 0)
01463                 msecs = 1;
01464         persec = (xfr->nbytes * 1000) / msecs;
01465         xfrin_log(xfr, ISC_LOG_INFO,
01466                   "Transfer completed: %d messages, %d records, "
01467                   "%" ISC_PRINT_QUADFORMAT "u bytes, "
01468                   "%u.%03u secs (%u bytes/sec)",
01469                   xfr->nmsg, xfr->nrecs, xfr->nbytes,
01470                   (unsigned int) (msecs / 1000), (unsigned int) (msecs % 1000),
01471                   (unsigned int) persec);
01472 
01473         if (xfr->socket != NULL)
01474                 isc_socket_detach(&xfr->socket);
01475 
01476         if (xfr->timer != NULL)
01477                 isc_timer_detach(&xfr->timer);
01478 
01479         if (xfr->task != NULL)
01480                 isc_task_detach(&xfr->task);
01481 
01482         if (xfr->tsigkey != NULL)
01483                 dns_tsigkey_detach(&xfr->tsigkey);
01484 
01485         if (xfr->lasttsig != NULL)
01486                 isc_buffer_free(&xfr->lasttsig);
01487 
01488         dns_diff_clear(&xfr->diff);
01489 
01490         if (xfr->ixfr.journal != NULL)
01491                 dns_journal_destroy(&xfr->ixfr.journal);
01492 
01493         if (xfr->axfr.add_private != NULL)
01494                 (void)dns_db_endload(xfr->db, &xfr->axfr);
01495 
01496         if (xfr->tcpmsg_valid)
01497                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
01498 
01499         if (xfr->tsigctx != NULL)
01500                 dst_context_destroy(&xfr->tsigctx);
01501 
01502         if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
01503                 dns_name_free(&xfr->name, xfr->mctx);
01504 
01505         if (xfr->ver != NULL)
01506                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
01507 
01508         if (xfr->db != NULL)
01509                 dns_db_detach(&xfr->db);
01510 
01511         if (xfr->zone != NULL)
01512                 dns_zone_idetach(&xfr->zone);
01513 
01514         isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
01515 }
01516 
01517 /*
01518  * Log incoming zone transfer messages in a format like
01519  * transfer of <zone> from <address>: <message>
01520  */
01521 static void
01522 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
01523            const char *fmt, va_list ap)
01524 {
01525         char mastertext[ISC_SOCKADDR_FORMATSIZE];
01526         char msgtext[2048];
01527 
01528         isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
01529         vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
01530 
01531         isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
01532                       DNS_LOGMODULE_XFER_IN, level,
01533                       "transfer of '%s' from %s: %s",
01534                       zonetext, mastertext, msgtext);
01535 }
01536 
01537 /*
01538  * Logging function for use when a xfrin_ctx_t has not yet been created.
01539  */
01540 
01541 static void
01542 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
01543            const char *fmt, ...)
01544 {
01545         va_list ap;
01546 
01547         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
01548                 return;
01549 
01550         va_start(ap, fmt);
01551         xfrin_logv(level, zonetext, masteraddr, fmt, ap);
01552         va_end(ap);
01553 }
01554 
01555 /*
01556  * Logging function for use when there is a xfrin_ctx_t.
01557  */
01558 
01559 static void
01560 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
01561 {
01562         va_list ap;
01563         char zonetext[DNS_NAME_MAXTEXT+32];
01564 
01565         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
01566                 return;
01567 
01568         dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
01569 
01570         va_start(ap, fmt);
01571         xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap);
01572         va_end(ap);
01573 }

Generated on Tue Apr 28 17:41:02 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha