00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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>
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
00055
00056
00057
00058
00059
00060
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
00074
00075
00076
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
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;
00108 int sends;
00109 int recvs;
00110 isc_boolean_t shuttingdown;
00111 isc_result_t shutdown_result;
00112
00113 dns_name_t name;
00114 dns_rdataclass_t rdclass;
00115
00116 isc_boolean_t checkid;
00117 dns_messageid_t id;
00118
00119
00120
00121
00122
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
00132 isc_buffer_t qbuffer;
00133 unsigned char qbuffer_data[512];
00134
00135
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;
00142 int difflen;
00143
00144 xfrin_state_t state;
00145 isc_uint32_t end_serial;
00146 isc_boolean_t is_ixfr;
00147
00148 unsigned int nmsg;
00149 unsigned int nrecs;
00150 isc_uint64_t nbytes;
00151
00152 isc_time_t start;
00153 isc_time_t end;
00154
00155 dns_tsigkey_t *tsigkey;
00156 isc_buffer_t *lasttsig;
00157 dst_context_t *tsigctx;
00158 unsigned int sincetsig;
00159 dns_xfrindone_t done;
00160
00161
00162
00163
00164
00165
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
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
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,
00276 "rbt",
00277 &xfr->name,
00278 dns_dbtype_zone,
00279 xfr->rdclass,
00280 0, NULL,
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
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
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
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
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
00438
00439
00440
00441
00442
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
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
00490
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
00499
00500
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
00516
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
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
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
00767 result = DNS_R_BADIXFR;
00768 }
00769 xfrin_cancelio(xfr);
00770
00771
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
00833 xfr->socket = NULL;
00834
00835
00836
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
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
00866
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
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
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
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
01014
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
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
01082 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
01083 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
01084
01085
01086 CHECK(dns_message_gettempname(msg, &qname));
01087 dns_name_init(qname, NULL);
01088 dns_name_clone(&xfr->name, qname);
01089
01090
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
01102
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
01132
01133 if (xfr->lasttsig != NULL)
01134 isc_buffer_free(&xfr->lasttsig);
01135
01136
01137
01138
01139 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
01140
01141 isc_buffer_usedregion(&xfr->qbuffer, ®ion);
01142 INSIST(region.length <= 65535);
01143
01144
01145
01146
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, ®ion, 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;
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
01272
01273
01274
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
01325
01326 xfr->sincetsig = 0;
01327
01328
01329
01330
01331 if (xfr->lasttsig != NULL)
01332 isc_buffer_free(&xfr->lasttsig);
01333
01334
01335
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
01353
01354 xfr->nmsg++;
01355
01356
01357
01358
01359 xfr->nbytes += tcpmsg->buffer.used;
01360
01361
01362
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
01379 case XFRST_IXFR_END:
01380
01381
01382
01383 if (xfr->ixfr.journal != NULL)
01384 dns_journal_destroy(&xfr->ixfr.journal);
01385
01386
01387
01388
01389 if (xfr->done != NULL) {
01390 (xfr->done)(xfr->zone, ISC_R_SUCCESS);
01391 xfr->done = NULL;
01392 }
01393
01394
01395
01396
01397 xfr->shuttingdown = ISC_TRUE;
01398 xfr->shutdown_result = ISC_R_SUCCESS;
01399 maybe_free(xfr);
01400 break;
01401 default:
01402
01403
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
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
01449
01450
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
01458
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
01519
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
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
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 }