00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <config.h>
00021
00022 #include <isc/formatcheck.h>
00023 #include <isc/mem.h>
00024 #include <isc/timer.h>
00025 #include <isc/print.h>
00026 #include <isc/stats.h>
00027 #include <isc/util.h>
00028
00029 #include <dns/db.h>
00030 #include <dns/dbiterator.h>
00031 #include <dns/dlz.h>
00032 #include <dns/fixedname.h>
00033 #include <dns/journal.h>
00034 #include <dns/message.h>
00035 #include <dns/peer.h>
00036 #include <dns/rdataclass.h>
00037 #include <dns/rdatalist.h>
00038 #include <dns/rdataset.h>
00039 #include <dns/rdatasetiter.h>
00040 #include <dns/result.h>
00041 #include <dns/rriterator.h>
00042 #include <dns/soa.h>
00043 #include <dns/stats.h>
00044 #include <dns/timer.h>
00045 #include <dns/tsig.h>
00046 #include <dns/view.h>
00047 #include <dns/zone.h>
00048 #include <dns/zt.h>
00049
00050 #include <named/client.h>
00051 #include <named/log.h>
00052 #include <named/server.h>
00053 #include <named/xfrout.h>
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065 #define XFROUT_COMMON_LOGARGS \
00066 ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
00067
00068 #define XFROUT_PROTOCOL_LOGARGS \
00069 XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
00070
00071 #define XFROUT_DEBUG_LOGARGS(n) \
00072 XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
00073
00074 #define XFROUT_RR_LOGARGS \
00075 XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
00076
00077 #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
00078
00079
00080
00081
00082
00083
00084 #define FAILC(code, msg) \
00085 do { \
00086 result = (code); \
00087 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
00088 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
00089 "bad zone transfer request: %s (%s)", \
00090 msg, isc_result_totext(code)); \
00091 if (result != ISC_R_SUCCESS) goto failure; \
00092 } while (0)
00093
00094 #define FAILQ(code, msg, question, rdclass) \
00095 do { \
00096 char _buf1[DNS_NAME_FORMATSIZE]; \
00097 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
00098 result = (code); \
00099 dns_name_format(question, _buf1, sizeof(_buf1)); \
00100 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
00101 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
00102 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
00103 "bad zone transfer request: '%s/%s': %s (%s)", \
00104 _buf1, _buf2, msg, isc_result_totext(code)); \
00105 if (result != ISC_R_SUCCESS) goto failure; \
00106 } while (0)
00107
00108 #define CHECK(op) \
00109 do { result = (op); \
00110 if (result != ISC_R_SUCCESS) goto failure; \
00111 } while (0)
00112
00113
00114
00115 static inline void
00116 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
00117 isc_stats_increment(ns_g_server->nsstats, counter);
00118 if (zone != NULL) {
00119 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
00120 if (zonestats != NULL)
00121 isc_stats_increment(zonestats, counter);
00122 }
00123 }
00124
00125
00126
00127
00128
00129 static void
00130 log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
00131 isc_result_t result;
00132 isc_buffer_t buf;
00133 char mem[2000];
00134 dns_rdatalist_t rdl;
00135 dns_rdataset_t rds;
00136 dns_rdata_t rd = DNS_RDATA_INIT;
00137
00138 dns_rdatalist_init(&rdl);
00139 rdl.type = rdata->type;
00140 rdl.rdclass = rdata->rdclass;
00141 rdl.ttl = ttl;
00142 if (rdata->type == dns_rdatatype_sig ||
00143 rdata->type == dns_rdatatype_rrsig)
00144 rdl.covers = dns_rdata_covers(rdata);
00145 else
00146 rdl.covers = dns_rdatatype_none;
00147 dns_rdataset_init(&rds);
00148 dns_rdata_init(&rd);
00149 dns_rdata_clone(rdata, &rd);
00150 ISC_LIST_APPEND(rdl.rdata, &rd, link);
00151 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
00152
00153 isc_buffer_init(&buf, mem, sizeof(mem));
00154 result = dns_rdataset_totext(&rds, name,
00155 ISC_FALSE, ISC_FALSE, &buf);
00156
00157
00158
00159
00160
00161 if (result == ISC_R_SUCCESS) {
00162
00163
00164
00165 INSIST(buf.used >= 1 &&
00166 ((char *) buf.base)[buf.used - 1] == '\n');
00167 buf.used--;
00168
00169 isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
00170 (int)isc_buffer_usedlength(&buf),
00171 (char *)isc_buffer_base(&buf));
00172 } else {
00173 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
00174 }
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184 typedef struct rrstream_methods rrstream_methods_t;
00185
00186 typedef struct rrstream {
00187 isc_mem_t *mctx;
00188 rrstream_methods_t *methods;
00189 } rrstream_t;
00190
00191 struct rrstream_methods {
00192 isc_result_t (*first)(rrstream_t *);
00193 isc_result_t (*next)(rrstream_t *);
00194 void (*current)(rrstream_t *,
00195 dns_name_t **,
00196 isc_uint32_t *,
00197 dns_rdata_t **);
00198 void (*pause)(rrstream_t *);
00199 void (*destroy)(rrstream_t **);
00200 };
00201
00202 static void
00203 rrstream_noop_pause(rrstream_t *rs) {
00204 UNUSED(rs);
00205 }
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 typedef struct ixfr_rrstream {
00219 rrstream_t common;
00220 dns_journal_t *journal;
00221 } ixfr_rrstream_t;
00222
00223
00224 static void
00225 ixfr_rrstream_destroy(rrstream_t **sp);
00226
00227 static rrstream_methods_t ixfr_rrstream_methods;
00228
00229
00230
00231
00232
00233
00234 static isc_result_t
00235 ixfr_rrstream_create(isc_mem_t *mctx,
00236 const char *journal_filename,
00237 isc_uint32_t begin_serial,
00238 isc_uint32_t end_serial,
00239 rrstream_t **sp)
00240 {
00241 ixfr_rrstream_t *s;
00242 isc_result_t result;
00243
00244 INSIST(sp != NULL && *sp == NULL);
00245
00246 s = isc_mem_get(mctx, sizeof(*s));
00247 if (s == NULL)
00248 return (ISC_R_NOMEMORY);
00249 s->common.mctx = NULL;
00250 isc_mem_attach(mctx, &s->common.mctx);
00251 s->common.methods = &ixfr_rrstream_methods;
00252 s->journal = NULL;
00253
00254 CHECK(dns_journal_open(mctx, journal_filename,
00255 DNS_JOURNAL_READ, &s->journal));
00256 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
00257
00258 *sp = (rrstream_t *) s;
00259 return (ISC_R_SUCCESS);
00260
00261 failure:
00262 ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
00263 return (result);
00264 }
00265
00266 static isc_result_t
00267 ixfr_rrstream_first(rrstream_t *rs) {
00268 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
00269 return (dns_journal_first_rr(s->journal));
00270 }
00271
00272 static isc_result_t
00273 ixfr_rrstream_next(rrstream_t *rs) {
00274 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
00275 return (dns_journal_next_rr(s->journal));
00276 }
00277
00278 static void
00279 ixfr_rrstream_current(rrstream_t *rs,
00280 dns_name_t **name, isc_uint32_t *ttl,
00281 dns_rdata_t **rdata)
00282 {
00283 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
00284 dns_journal_current_rr(s->journal, name, ttl, rdata);
00285 }
00286
00287 static void
00288 ixfr_rrstream_destroy(rrstream_t **rsp) {
00289 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
00290 if (s->journal != 0)
00291 dns_journal_destroy(&s->journal);
00292 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
00293 }
00294
00295 static rrstream_methods_t ixfr_rrstream_methods = {
00296 ixfr_rrstream_first,
00297 ixfr_rrstream_next,
00298 ixfr_rrstream_current,
00299 rrstream_noop_pause,
00300 ixfr_rrstream_destroy
00301 };
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 typedef struct axfr_rrstream {
00313 rrstream_t common;
00314 dns_rriterator_t it;
00315 isc_boolean_t it_valid;
00316 } axfr_rrstream_t;
00317
00318
00319
00320
00321 static void
00322 axfr_rrstream_destroy(rrstream_t **rsp);
00323
00324 static rrstream_methods_t axfr_rrstream_methods;
00325
00326 static isc_result_t
00327 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
00328 rrstream_t **sp)
00329 {
00330 axfr_rrstream_t *s;
00331 isc_result_t result;
00332
00333 INSIST(sp != NULL && *sp == NULL);
00334
00335 s = isc_mem_get(mctx, sizeof(*s));
00336 if (s == NULL)
00337 return (ISC_R_NOMEMORY);
00338 s->common.mctx = NULL;
00339 isc_mem_attach(mctx, &s->common.mctx);
00340 s->common.methods = &axfr_rrstream_methods;
00341 s->it_valid = ISC_FALSE;
00342
00343 CHECK(dns_rriterator_init(&s->it, db, ver, 0));
00344 s->it_valid = ISC_TRUE;
00345
00346 *sp = (rrstream_t *) s;
00347 return (ISC_R_SUCCESS);
00348
00349 failure:
00350 axfr_rrstream_destroy((rrstream_t **) (void *)&s);
00351 return (result);
00352 }
00353
00354 static isc_result_t
00355 axfr_rrstream_first(rrstream_t *rs) {
00356 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
00357 isc_result_t result;
00358 result = dns_rriterator_first(&s->it);
00359 if (result != ISC_R_SUCCESS)
00360 return (result);
00361
00362 for (;;) {
00363 dns_name_t *name_dummy = NULL;
00364 isc_uint32_t ttl_dummy;
00365 dns_rdata_t *rdata = NULL;
00366 dns_rriterator_current(&s->it, &name_dummy,
00367 &ttl_dummy, NULL, &rdata);
00368 if (rdata->type != dns_rdatatype_soa)
00369 break;
00370 result = dns_rriterator_next(&s->it);
00371 if (result != ISC_R_SUCCESS)
00372 break;
00373 }
00374 return (result);
00375 }
00376
00377 static isc_result_t
00378 axfr_rrstream_next(rrstream_t *rs) {
00379 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
00380 isc_result_t result;
00381
00382
00383 for (;;) {
00384 dns_name_t *name_dummy = NULL;
00385 isc_uint32_t ttl_dummy;
00386 dns_rdata_t *rdata = NULL;
00387 result = dns_rriterator_next(&s->it);
00388 if (result != ISC_R_SUCCESS)
00389 break;
00390 dns_rriterator_current(&s->it, &name_dummy,
00391 &ttl_dummy, NULL, &rdata);
00392 if (rdata->type != dns_rdatatype_soa)
00393 break;
00394 }
00395 return (result);
00396 }
00397
00398 static void
00399 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
00400 dns_rdata_t **rdata)
00401 {
00402 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
00403 dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
00404 }
00405
00406 static void
00407 axfr_rrstream_pause(rrstream_t *rs) {
00408 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
00409 dns_rriterator_pause(&s->it);
00410 }
00411
00412 static void
00413 axfr_rrstream_destroy(rrstream_t **rsp) {
00414 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
00415 if (s->it_valid)
00416 dns_rriterator_destroy(&s->it);
00417 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
00418 }
00419
00420 static rrstream_methods_t axfr_rrstream_methods = {
00421 axfr_rrstream_first,
00422 axfr_rrstream_next,
00423 axfr_rrstream_current,
00424 axfr_rrstream_pause,
00425 axfr_rrstream_destroy
00426 };
00427
00428
00429
00430
00431
00432
00433
00434 typedef struct soa_rrstream {
00435 rrstream_t common;
00436 dns_difftuple_t *soa_tuple;
00437 } soa_rrstream_t;
00438
00439
00440
00441
00442 static void
00443 soa_rrstream_destroy(rrstream_t **rsp);
00444
00445 static rrstream_methods_t soa_rrstream_methods;
00446
00447 static isc_result_t
00448 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
00449 rrstream_t **sp)
00450 {
00451 soa_rrstream_t *s;
00452 isc_result_t result;
00453
00454 INSIST(sp != NULL && *sp == NULL);
00455
00456 s = isc_mem_get(mctx, sizeof(*s));
00457 if (s == NULL)
00458 return (ISC_R_NOMEMORY);
00459 s->common.mctx = NULL;
00460 isc_mem_attach(mctx, &s->common.mctx);
00461 s->common.methods = &soa_rrstream_methods;
00462 s->soa_tuple = NULL;
00463
00464 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
00465 &s->soa_tuple));
00466
00467 *sp = (rrstream_t *) s;
00468 return (ISC_R_SUCCESS);
00469
00470 failure:
00471 soa_rrstream_destroy((rrstream_t **) (void *)&s);
00472 return (result);
00473 }
00474
00475 static isc_result_t
00476 soa_rrstream_first(rrstream_t *rs) {
00477 UNUSED(rs);
00478 return (ISC_R_SUCCESS);
00479 }
00480
00481 static isc_result_t
00482 soa_rrstream_next(rrstream_t *rs) {
00483 UNUSED(rs);
00484 return (ISC_R_NOMORE);
00485 }
00486
00487 static void
00488 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
00489 dns_rdata_t **rdata)
00490 {
00491 soa_rrstream_t *s = (soa_rrstream_t *) rs;
00492 *name = &s->soa_tuple->name;
00493 *ttl = s->soa_tuple->ttl;
00494 *rdata = &s->soa_tuple->rdata;
00495 }
00496
00497 static void
00498 soa_rrstream_destroy(rrstream_t **rsp) {
00499 soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
00500 if (s->soa_tuple != NULL)
00501 dns_difftuple_free(&s->soa_tuple);
00502 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
00503 }
00504
00505 static rrstream_methods_t soa_rrstream_methods = {
00506 soa_rrstream_first,
00507 soa_rrstream_next,
00508 soa_rrstream_current,
00509 rrstream_noop_pause,
00510 soa_rrstream_destroy
00511 };
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 typedef struct compound_rrstream {
00525 rrstream_t common;
00526 rrstream_t *components[3];
00527 int state;
00528 isc_result_t result;
00529 } compound_rrstream_t;
00530
00531
00532
00533
00534 static void
00535 compound_rrstream_destroy(rrstream_t **rsp);
00536
00537 static isc_result_t
00538 compound_rrstream_next(rrstream_t *rs);
00539
00540 static rrstream_methods_t compound_rrstream_methods;
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static isc_result_t
00556 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
00557 rrstream_t **data_stream, rrstream_t **sp)
00558 {
00559 compound_rrstream_t *s;
00560
00561 INSIST(sp != NULL && *sp == NULL);
00562
00563 s = isc_mem_get(mctx, sizeof(*s));
00564 if (s == NULL)
00565 return (ISC_R_NOMEMORY);
00566 s->common.mctx = NULL;
00567 isc_mem_attach(mctx, &s->common.mctx);
00568 s->common.methods = &compound_rrstream_methods;
00569 s->components[0] = *soa_stream;
00570 s->components[1] = *data_stream;
00571 s->components[2] = *soa_stream;
00572 s->state = -1;
00573 s->result = ISC_R_FAILURE;
00574
00575 *soa_stream = NULL;
00576 *data_stream = NULL;
00577 *sp = (rrstream_t *) s;
00578 return (ISC_R_SUCCESS);
00579 }
00580
00581 static isc_result_t
00582 compound_rrstream_first(rrstream_t *rs) {
00583 compound_rrstream_t *s = (compound_rrstream_t *) rs;
00584 s->state = 0;
00585 do {
00586 rrstream_t *curstream = s->components[s->state];
00587 s->result = curstream->methods->first(curstream);
00588 } while (s->result == ISC_R_NOMORE && s->state < 2);
00589 return (s->result);
00590 }
00591
00592 static isc_result_t
00593 compound_rrstream_next(rrstream_t *rs) {
00594 compound_rrstream_t *s = (compound_rrstream_t *) rs;
00595 rrstream_t *curstream = s->components[s->state];
00596 s->result = curstream->methods->next(curstream);
00597 while (s->result == ISC_R_NOMORE) {
00598
00599
00600
00601
00602 curstream->methods->pause(curstream);
00603 if (s->state == 2)
00604 return (ISC_R_NOMORE);
00605 s->state++;
00606 curstream = s->components[s->state];
00607 s->result = curstream->methods->first(curstream);
00608 }
00609 return (s->result);
00610 }
00611
00612 static void
00613 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
00614 dns_rdata_t **rdata)
00615 {
00616 compound_rrstream_t *s = (compound_rrstream_t *) rs;
00617 rrstream_t *curstream;
00618 INSIST(0 <= s->state && s->state < 3);
00619 INSIST(s->result == ISC_R_SUCCESS);
00620 curstream = s->components[s->state];
00621 curstream->methods->current(curstream, name, ttl, rdata);
00622 }
00623
00624 static void
00625 compound_rrstream_pause(rrstream_t *rs)
00626 {
00627 compound_rrstream_t *s = (compound_rrstream_t *) rs;
00628 rrstream_t *curstream;
00629 INSIST(0 <= s->state && s->state < 3);
00630 curstream = s->components[s->state];
00631 curstream->methods->pause(curstream);
00632 }
00633
00634 static void
00635 compound_rrstream_destroy(rrstream_t **rsp) {
00636 compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
00637 s->components[0]->methods->destroy(&s->components[0]);
00638 s->components[1]->methods->destroy(&s->components[1]);
00639 s->components[2] = NULL;
00640 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
00641 }
00642
00643 static rrstream_methods_t compound_rrstream_methods = {
00644 compound_rrstream_first,
00645 compound_rrstream_next,
00646 compound_rrstream_current,
00647 compound_rrstream_pause,
00648 compound_rrstream_destroy
00649 };
00650
00651
00652
00653
00654
00655
00656
00657 typedef struct {
00658 isc_mem_t *mctx;
00659 ns_client_t *client;
00660 unsigned int id;
00661 dns_name_t *qname;
00662 dns_rdatatype_t qtype;
00663 dns_rdataclass_t qclass;
00664 dns_zone_t *zone;
00665 dns_db_t *db;
00666 dns_dbversion_t *ver;
00667 isc_quota_t *quota;
00668 rrstream_t *stream;
00669 isc_boolean_t end_of_stream;
00670 isc_buffer_t buf;
00671
00672 isc_buffer_t txlenbuf;
00673 isc_buffer_t txbuf;
00674 void *txmem;
00675 unsigned int txmemlen;
00676 unsigned int nmsg;
00677 dns_tsigkey_t *tsigkey;
00678 isc_buffer_t *lasttsig;
00679 isc_boolean_t many_answers;
00680 int sends;
00681 isc_boolean_t shuttingdown;
00682 const char *mnemonic;
00683 } xfrout_ctx_t;
00684
00685 static isc_result_t
00686 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
00687 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
00688 dns_rdataclass_t qclass, dns_zone_t *zone,
00689 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
00690 rrstream_t *stream, dns_tsigkey_t *tsigkey,
00691 isc_buffer_t *lasttsig,
00692 unsigned int maxtime,
00693 unsigned int idletime,
00694 isc_boolean_t many_answers,
00695 xfrout_ctx_t **xfrp);
00696
00697 static void
00698 sendstream(xfrout_ctx_t *xfr);
00699
00700 static void
00701 xfrout_senddone(isc_task_t *task, isc_event_t *event);
00702
00703 static void
00704 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
00705
00706 static void
00707 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
00708
00709 static void
00710 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
00711
00712 static void
00713 xfrout_client_shutdown(void *arg, isc_result_t result);
00714
00715 static void
00716 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
00717 dns_rdataclass_t rdclass, int level,
00718 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
00719
00720 static void
00721 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
00722 ISC_FORMAT_PRINTF(3, 4);
00723
00724
00725
00726 void
00727 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
00728 isc_result_t result;
00729 dns_name_t *question_name;
00730 dns_rdataset_t *question_rdataset;
00731 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
00732 dns_db_t *db = NULL;
00733 dns_dbversion_t *ver = NULL;
00734 dns_rdataclass_t question_class;
00735 rrstream_t *soa_stream = NULL;
00736 rrstream_t *data_stream = NULL;
00737 rrstream_t *stream = NULL;
00738 dns_difftuple_t *current_soa_tuple = NULL;
00739 dns_name_t *soa_name;
00740 dns_rdataset_t *soa_rdataset;
00741 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
00742 isc_boolean_t have_soa = ISC_FALSE;
00743 const char *mnemonic = NULL;
00744 isc_mem_t *mctx = client->mctx;
00745 dns_message_t *request = client->message;
00746 xfrout_ctx_t *xfr = NULL;
00747 isc_quota_t *quota = NULL;
00748 dns_transfer_format_t format = client->view->transfer_format;
00749 isc_netaddr_t na;
00750 dns_peer_t *peer = NULL;
00751 isc_buffer_t *tsigbuf = NULL;
00752 char *journalfile;
00753 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
00754 char keyname[DNS_NAME_FORMATSIZE];
00755 isc_boolean_t is_poll = ISC_FALSE;
00756 isc_boolean_t is_dlz = ISC_FALSE;
00757 isc_boolean_t is_ixfr = ISC_FALSE;
00758 isc_uint32_t begin_serial = 0, current_serial;
00759
00760 switch (reqtype) {
00761 case dns_rdatatype_axfr:
00762 mnemonic = "AXFR";
00763 break;
00764 case dns_rdatatype_ixfr:
00765 mnemonic = "IXFR";
00766 break;
00767 default:
00768 INSIST(0);
00769 break;
00770 }
00771
00772 ns_client_log(client,
00773 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
00774 ISC_LOG_DEBUG(6), "%s request", mnemonic);
00775
00776
00777
00778 result = isc_quota_attach(&ns_g_server->xfroutquota, "a);
00779 if (result != ISC_R_SUCCESS) {
00780 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
00781 "%s request denied: %s", mnemonic,
00782 isc_result_totext(result));
00783 goto failure;
00784 }
00785
00786
00787
00788
00789 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
00790 INSIST(result == ISC_R_SUCCESS);
00791
00792
00793
00794
00795
00796 question_name = NULL;
00797 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
00798 question_rdataset = ISC_LIST_HEAD(question_name->list);
00799 question_class = question_rdataset->rdclass;
00800 INSIST(question_rdataset->type == reqtype);
00801 if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
00802 FAILC(DNS_R_FORMERR, "multiple questions");
00803 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
00804 if (result != ISC_R_NOMORE)
00805 FAILC(DNS_R_FORMERR, "multiple questions");
00806
00807 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
00808 &zone);
00809
00810 if (result != ISC_R_SUCCESS) {
00811
00812
00813
00814
00815
00816 if (! ISC_LIST_EMPTY(client->view->dlz_searched)) {
00817 result = dns_dlzallowzonexfr(client->view,
00818 question_name,
00819 &client->peeraddr,
00820 &db);
00821
00822 if (result == ISC_R_NOPERM) {
00823 char _buf1[DNS_NAME_FORMATSIZE];
00824 char _buf2[DNS_RDATACLASS_FORMATSIZE];
00825
00826 result = DNS_R_REFUSED;
00827 dns_name_format(question_name, _buf1,
00828 sizeof(_buf1));
00829 dns_rdataclass_format(question_class,
00830 _buf2, sizeof(_buf2));
00831 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
00832 NS_LOGMODULE_XFER_OUT,
00833 ISC_LOG_ERROR,
00834 "zone transfer '%s/%s' denied",
00835 _buf1, _buf2);
00836 goto failure;
00837 }
00838 if (result != ISC_R_SUCCESS)
00839 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
00840 question_name, question_class);
00841 is_dlz = ISC_TRUE;
00842 } else {
00843
00844
00845
00846
00847 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
00848 question_name, question_class);
00849 }
00850 } else {
00851
00852 switch(dns_zone_gettype(zone)) {
00853
00854 case dns_zone_master:
00855 case dns_zone_slave:
00856 case dns_zone_dlz:
00857 break;
00858 default:
00859 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
00860 question_name, question_class);
00861 }
00862 CHECK(dns_zone_getdb(zone, &db));
00863 dns_db_currentversion(db, &ver);
00864 }
00865
00866 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
00867 "%s question section OK", mnemonic);
00868
00869
00870
00871
00872
00873 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
00874 result == ISC_R_SUCCESS;
00875 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
00876 {
00877 soa_name = NULL;
00878 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
00879 &soa_name);
00880
00881
00882
00883
00884 if (! dns_name_equal(soa_name, question_name))
00885 continue;
00886
00887 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
00888 soa_rdataset != NULL;
00889 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
00890 {
00891
00892
00893
00894 if (soa_rdataset->type != dns_rdatatype_soa)
00895 continue;
00896 if (soa_rdataset->rdclass != question_class)
00897 continue;
00898
00899 CHECK(dns_rdataset_first(soa_rdataset));
00900 dns_rdataset_current(soa_rdataset, &soa_rdata);
00901 result = dns_rdataset_next(soa_rdataset);
00902 if (result == ISC_R_SUCCESS)
00903 FAILC(DNS_R_FORMERR,
00904 "IXFR authority section "
00905 "has multiple SOAs");
00906 have_soa = ISC_TRUE;
00907 goto got_soa;
00908 }
00909 }
00910 got_soa:
00911 if (result != ISC_R_NOMORE)
00912 CHECK(result);
00913
00914 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
00915 "%s authority section OK", mnemonic);
00916
00917
00918
00919
00920 if (!is_dlz) {
00921 ns_client_aclmsg("zone transfer", question_name, reqtype,
00922 client->view->rdclass, msg, sizeof(msg));
00923 CHECK(ns_client_checkacl(client, NULL, msg,
00924 dns_zone_getxfracl(zone),
00925 ISC_TRUE, ISC_LOG_ERROR));
00926 }
00927
00928
00929
00930
00931 if (reqtype == dns_rdatatype_axfr &&
00932 (client->attributes & NS_CLIENTATTR_TCP) == 0)
00933 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
00934
00935
00936
00937
00938 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
00939 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
00940
00941
00942
00943
00944 if (peer != NULL)
00945 (void)dns_peer_gettransferformat(peer, &format);
00946
00947
00948
00949
00950 if (is_dlz)
00951 dns_db_currentversion(db, &ver);
00952
00953 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
00954 ¤t_soa_tuple));
00955
00956 current_serial = dns_soa_getserial(¤t_soa_tuple->rdata);
00957 if (reqtype == dns_rdatatype_ixfr) {
00958 isc_boolean_t provide_ixfr;
00959
00960
00961
00962
00963
00964 provide_ixfr = client->view->provideixfr;
00965 if (peer != NULL)
00966 (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
00967 if (provide_ixfr == ISC_FALSE)
00968 goto axfr_fallback;
00969
00970 if (! have_soa)
00971 FAILC(DNS_R_FORMERR,
00972 "IXFR request missing SOA");
00973
00974 begin_serial = dns_soa_getserial(&soa_rdata);
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
00988 (client->attributes & NS_CLIENTATTR_TCP) == 0)
00989 {
00990 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
00991 is_poll = ISC_TRUE;
00992 goto have_stream;
00993 }
00994 journalfile = is_dlz ? NULL : dns_zone_getjournal(zone);
00995 if (journalfile != NULL)
00996 result = ixfr_rrstream_create(mctx,
00997 journalfile,
00998 begin_serial,
00999 current_serial,
01000 &data_stream);
01001 else
01002 result = ISC_R_NOTFOUND;
01003 if (result == ISC_R_NOTFOUND ||
01004 result == ISC_R_RANGE) {
01005 xfrout_log1(client, question_name, question_class,
01006 ISC_LOG_DEBUG(4),
01007 "IXFR version not in journal, "
01008 "falling back to AXFR");
01009 mnemonic = "AXFR-style IXFR";
01010 goto axfr_fallback;
01011 }
01012 CHECK(result);
01013 is_ixfr = ISC_TRUE;
01014 } else {
01015 axfr_fallback:
01016 CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream));
01017 }
01018
01019
01020
01021
01022 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
01023 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
01024 &stream));
01025 soa_stream = NULL;
01026 data_stream = NULL;
01027
01028 have_stream:
01029 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
01030
01031
01032
01033
01034
01035
01036
01037 if (is_dlz)
01038 CHECK(xfrout_ctx_create(mctx, client, request->id,
01039 question_name, reqtype, question_class,
01040 zone, db, ver, quota, stream,
01041 dns_message_gettsigkey(request),
01042 tsigbuf,
01043 3600,
01044 3600,
01045 (format == dns_many_answers) ?
01046 ISC_TRUE : ISC_FALSE,
01047 &xfr));
01048 else
01049 CHECK(xfrout_ctx_create(mctx, client, request->id,
01050 question_name, reqtype, question_class,
01051 zone, db, ver, quota, stream,
01052 dns_message_gettsigkey(request),
01053 tsigbuf,
01054 dns_zone_getmaxxfrout(zone),
01055 dns_zone_getidleout(zone),
01056 (format == dns_many_answers) ?
01057 ISC_TRUE : ISC_FALSE,
01058 &xfr));
01059
01060 xfr->mnemonic = mnemonic;
01061 stream = NULL;
01062 quota = NULL;
01063
01064 CHECK(xfr->stream->methods->first(xfr->stream));
01065
01066 if (xfr->tsigkey != NULL)
01067 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
01068 else
01069 keyname[0] = '\0';
01070 if (is_poll)
01071 xfrout_log1(client, question_name, question_class,
01072 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
01073 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
01074 else if (is_ixfr)
01075 xfrout_log1(client, question_name, question_class,
01076 ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)",
01077 mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
01078 keyname, begin_serial, current_serial);
01079 else
01080 xfrout_log1(client, question_name, question_class,
01081 ISC_LOG_INFO, "%s started%s%s (serial %u)",
01082 mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
01083 keyname, current_serial);
01084
01085
01086 if (zone != NULL) {
01087 dns_zone_getraw(zone, &raw);
01088 mayberaw = (raw != NULL) ? raw : zone;
01089 if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
01090 dns_zone_gettype(mayberaw) == dns_zone_slave) {
01091 isc_time_t expiretime;
01092 isc_uint32_t secs;
01093 dns_zone_getexpiretime(zone, &expiretime);
01094 secs = isc_time_seconds(&expiretime);
01095 if (secs >= client->now && result == ISC_R_SUCCESS) {
01096 client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
01097 client->expire = secs - client->now;
01098 }
01099 }
01100 if (raw != NULL)
01101 dns_zone_detach(&raw);
01102 }
01103
01104
01105
01106
01107
01108
01109 sendstream(xfr);
01110 xfr = NULL;
01111
01112 result = ISC_R_SUCCESS;
01113
01114 failure:
01115 if (result == DNS_R_REFUSED)
01116 inc_stats(zone, dns_nsstatscounter_xfrrej);
01117 if (quota != NULL)
01118 isc_quota_detach("a);
01119 if (current_soa_tuple != NULL)
01120 dns_difftuple_free(¤t_soa_tuple);
01121 if (stream != NULL)
01122 stream->methods->destroy(&stream);
01123 if (soa_stream != NULL)
01124 soa_stream->methods->destroy(&soa_stream);
01125 if (data_stream != NULL)
01126 data_stream->methods->destroy(&data_stream);
01127 if (ver != NULL)
01128 dns_db_closeversion(db, &ver, ISC_FALSE);
01129 if (db != NULL)
01130 dns_db_detach(&db);
01131 if (zone != NULL)
01132 dns_zone_detach(&zone);
01133
01134 if (xfr != NULL) {
01135 xfrout_fail(xfr, result, "setting up zone transfer");
01136 } else if (result != ISC_R_SUCCESS) {
01137 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
01138 NS_LOGMODULE_XFER_OUT,
01139 ISC_LOG_DEBUG(3), "zone transfer setup failed");
01140 ns_client_error(client, result);
01141 }
01142 }
01143
01144 static isc_result_t
01145 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
01146 dns_name_t *qname, dns_rdatatype_t qtype,
01147 dns_rdataclass_t qclass, dns_zone_t *zone,
01148 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
01149 rrstream_t *stream, dns_tsigkey_t *tsigkey,
01150 isc_buffer_t *lasttsig, unsigned int maxtime,
01151 unsigned int idletime, isc_boolean_t many_answers,
01152 xfrout_ctx_t **xfrp)
01153 {
01154 xfrout_ctx_t *xfr;
01155 isc_result_t result;
01156 unsigned int len;
01157 void *mem;
01158
01159 INSIST(xfrp != NULL && *xfrp == NULL);
01160 xfr = isc_mem_get(mctx, sizeof(*xfr));
01161 if (xfr == NULL)
01162 return (ISC_R_NOMEMORY);
01163 xfr->mctx = NULL;
01164 isc_mem_attach(mctx, &xfr->mctx);
01165 xfr->client = NULL;
01166 ns_client_attach(client, &xfr->client);
01167 xfr->id = id;
01168 xfr->qname = qname;
01169 xfr->qtype = qtype;
01170 xfr->qclass = qclass;
01171 xfr->zone = NULL;
01172 xfr->db = NULL;
01173 xfr->ver = NULL;
01174 if (zone != NULL)
01175 dns_zone_attach(zone, &xfr->zone);
01176 dns_db_attach(db, &xfr->db);
01177 dns_db_attachversion(db, ver, &xfr->ver);
01178 xfr->end_of_stream = ISC_FALSE;
01179 xfr->tsigkey = tsigkey;
01180 xfr->lasttsig = lasttsig;
01181 xfr->txmem = NULL;
01182 xfr->txmemlen = 0;
01183 xfr->nmsg = 0;
01184 xfr->many_answers = many_answers,
01185 xfr->sends = 0;
01186 xfr->shuttingdown = ISC_FALSE;
01187 xfr->mnemonic = NULL;
01188 xfr->buf.base = NULL;
01189 xfr->buf.length = 0;
01190 xfr->txmem = NULL;
01191 xfr->txmemlen = 0;
01192 xfr->stream = NULL;
01193 xfr->quota = NULL;
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 len = 65535;
01206 mem = isc_mem_get(mctx, len);
01207 if (mem == NULL) {
01208 result = ISC_R_NOMEMORY;
01209 goto failure;
01210 }
01211 isc_buffer_init(&xfr->buf, mem, len);
01212
01213
01214
01215
01216
01217 len = 2 + 65535;
01218 mem = isc_mem_get(mctx, len);
01219 if (mem == NULL) {
01220 result = ISC_R_NOMEMORY;
01221 goto failure;
01222 }
01223 isc_buffer_init(&xfr->txlenbuf, mem, 2);
01224 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
01225 xfr->txmem = mem;
01226 xfr->txmemlen = len;
01227
01228 CHECK(dns_timer_setidle(xfr->client->timer,
01229 maxtime, idletime, ISC_FALSE));
01230
01231
01232
01233
01234
01235
01236 xfr->client->shutdown = xfrout_client_shutdown;
01237 xfr->client->shutdown_arg = xfr;
01238
01239
01240
01241
01242 xfr->quota = quota;
01243 xfr->stream = stream;
01244
01245 *xfrp = xfr;
01246 return (ISC_R_SUCCESS);
01247
01248 failure:
01249 xfrout_ctx_destroy(&xfr);
01250 return (result);
01251 }
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262 static void
01263 sendstream(xfrout_ctx_t *xfr) {
01264 dns_message_t *tcpmsg = NULL;
01265 dns_message_t *msg = NULL;
01266 isc_result_t result;
01267 isc_region_t used;
01268 isc_region_t region;
01269 dns_rdataset_t *qrdataset;
01270 dns_name_t *msgname = NULL;
01271 dns_rdata_t *msgrdata = NULL;
01272 dns_rdatalist_t *msgrdl = NULL;
01273 dns_rdataset_t *msgrds = NULL;
01274 dns_compress_t cctx;
01275 isc_boolean_t cleanup_cctx = ISC_FALSE;
01276
01277 int n_rrs;
01278
01279 isc_buffer_clear(&xfr->buf);
01280 isc_buffer_clear(&xfr->txlenbuf);
01281 isc_buffer_clear(&xfr->txbuf);
01282
01283 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
01284
01285
01286
01287
01288 msg = xfr->client->message;
01289 CHECK(dns_message_reply(msg, ISC_TRUE));
01290 } else {
01291
01292
01293
01294
01295
01296
01297
01298
01299 CHECK(dns_message_create(xfr->mctx,
01300 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
01301 msg = tcpmsg;
01302
01303 msg->id = xfr->id;
01304 msg->rcode = dns_rcode_noerror;
01305 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
01306 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
01307 msg->flags |= DNS_MESSAGEFLAG_RA;
01308 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
01309 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
01310 if (xfr->lasttsig != NULL)
01311 isc_buffer_free(&xfr->lasttsig);
01312
01313
01314
01315
01316 if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
01317 dns_rdataset_t *opt = NULL;
01318
01319 CHECK(ns_client_addopt(xfr->client, msg, &opt));
01320 CHECK(dns_message_setopt(msg, opt));
01321
01322
01323
01324 xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
01325 xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
01326 }
01327
01328
01329
01330
01331 if (xfr->tsigkey != NULL)
01332 INSIST(msg->reserved != 0U);
01333 isc_buffer_add(&xfr->buf, msg->reserved);
01334
01335
01336
01337
01338
01339
01340 if (xfr->nmsg == 0) {
01341 dns_name_t *qname = NULL;
01342 isc_region_t r;
01343
01344
01345
01346
01347
01348 isc_buffer_add(&xfr->buf, 12 + 4);
01349
01350 qrdataset = NULL;
01351 result = dns_message_gettemprdataset(msg, &qrdataset);
01352 if (result != ISC_R_SUCCESS)
01353 goto failure;
01354 dns_rdataset_init(qrdataset);
01355 dns_rdataset_makequestion(qrdataset,
01356 xfr->client->message->rdclass,
01357 xfr->qtype);
01358
01359 result = dns_message_gettempname(msg, &qname);
01360 if (result != ISC_R_SUCCESS)
01361 goto failure;
01362 dns_name_init(qname, NULL);
01363 isc_buffer_availableregion(&xfr->buf, &r);
01364 INSIST(r.length >= xfr->qname->length);
01365 r.length = xfr->qname->length;
01366 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
01367 xfr->qname->length);
01368 dns_name_fromregion(qname, &r);
01369 ISC_LIST_INIT(qname->list);
01370 ISC_LIST_APPEND(qname->list, qrdataset, link);
01371
01372 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
01373 } else {
01374
01375
01376
01377 isc_buffer_add(&xfr->buf, 12);
01378 msg->tcp_continuation = 1;
01379 }
01380 }
01381
01382
01383
01384
01385
01386 for (n_rrs = 0; ; n_rrs++) {
01387 dns_name_t *name = NULL;
01388 isc_uint32_t ttl;
01389 dns_rdata_t *rdata = NULL;
01390
01391 unsigned int size;
01392 isc_region_t r;
01393
01394 msgname = NULL;
01395 msgrdata = NULL;
01396 msgrdl = NULL;
01397 msgrds = NULL;
01398
01399 xfr->stream->methods->current(xfr->stream,
01400 &name, &ttl, &rdata);
01401 size = name->length + 10 + rdata->length;
01402 isc_buffer_availableregion(&xfr->buf, &r);
01403 if (size >= r.length) {
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416 if (n_rrs == 0) {
01417 xfrout_log(xfr, ISC_LOG_WARNING,
01418 "RR too large for zone transfer "
01419 "(%d bytes)", size);
01420
01421 result = ISC_R_NOSPACE;
01422 goto failure;
01423 }
01424 break;
01425 }
01426
01427 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
01428 log_rr(name, rdata, ttl);
01429
01430 result = dns_message_gettempname(msg, &msgname);
01431 if (result != ISC_R_SUCCESS)
01432 goto failure;
01433 dns_name_init(msgname, NULL);
01434 isc_buffer_availableregion(&xfr->buf, &r);
01435 INSIST(r.length >= name->length);
01436 r.length = name->length;
01437 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
01438 dns_name_fromregion(msgname, &r);
01439
01440
01441 isc_buffer_add(&xfr->buf, 10);
01442
01443 result = dns_message_gettemprdata(msg, &msgrdata);
01444 if (result != ISC_R_SUCCESS)
01445 goto failure;
01446 isc_buffer_availableregion(&xfr->buf, &r);
01447 r.length = rdata->length;
01448 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
01449 dns_rdata_init(msgrdata);
01450 dns_rdata_fromregion(msgrdata,
01451 rdata->rdclass, rdata->type, &r);
01452
01453 result = dns_message_gettemprdatalist(msg, &msgrdl);
01454 if (result != ISC_R_SUCCESS)
01455 goto failure;
01456 msgrdl->type = rdata->type;
01457 msgrdl->rdclass = rdata->rdclass;
01458 msgrdl->ttl = ttl;
01459 if (rdata->type == dns_rdatatype_sig ||
01460 rdata->type == dns_rdatatype_rrsig)
01461 msgrdl->covers = dns_rdata_covers(rdata);
01462 else
01463 msgrdl->covers = dns_rdatatype_none;
01464 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
01465
01466 result = dns_message_gettemprdataset(msg, &msgrds);
01467 if (result != ISC_R_SUCCESS)
01468 goto failure;
01469 dns_rdataset_init(msgrds);
01470 result = dns_rdatalist_tordataset(msgrdl, msgrds);
01471 INSIST(result == ISC_R_SUCCESS);
01472
01473 ISC_LIST_APPEND(msgname->list, msgrds, link);
01474
01475 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
01476 msgname = NULL;
01477
01478 result = xfr->stream->methods->next(xfr->stream);
01479 if (result == ISC_R_NOMORE) {
01480 xfr->end_of_stream = ISC_TRUE;
01481 break;
01482 }
01483 CHECK(result);
01484
01485 if (! xfr->many_answers)
01486 break;
01487 }
01488
01489 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
01490 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
01491 dns_compress_setsensitive(&cctx, ISC_TRUE);
01492 cleanup_cctx = ISC_TRUE;
01493 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
01494 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
01495 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
01496 CHECK(dns_message_renderend(msg));
01497 dns_compress_invalidate(&cctx);
01498 cleanup_cctx = ISC_FALSE;
01499
01500 isc_buffer_usedregion(&xfr->txbuf, &used);
01501 isc_buffer_putuint16(&xfr->txlenbuf,
01502 (isc_uint16_t)used.length);
01503 region.base = xfr->txlenbuf.base;
01504 region.length = 2 + used.length;
01505 xfrout_log(xfr, ISC_LOG_DEBUG(8),
01506 "sending TCP message of %d bytes",
01507 used.length);
01508 CHECK(isc_socket_send(xfr->client->tcpsocket,
01509 ®ion, xfr->client->task,
01510 xfrout_senddone,
01511 xfr));
01512 xfr->sends++;
01513 } else {
01514 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
01515 ns_client_send(xfr->client);
01516 xfr->stream->methods->pause(xfr->stream);
01517 xfrout_ctx_destroy(&xfr);
01518 return;
01519 }
01520
01521
01522 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
01523
01524 xfr->nmsg++;
01525
01526 failure:
01527 if (msgname != NULL) {
01528 if (msgrds != NULL) {
01529 if (dns_rdataset_isassociated(msgrds))
01530 dns_rdataset_disassociate(msgrds);
01531 dns_message_puttemprdataset(msg, &msgrds);
01532 }
01533 if (msgrdl != NULL) {
01534 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
01535 dns_message_puttemprdatalist(msg, &msgrdl);
01536 }
01537 if (msgrdata != NULL)
01538 dns_message_puttemprdata(msg, &msgrdata);
01539 dns_message_puttempname(msg, &msgname);
01540 }
01541
01542 if (tcpmsg != NULL)
01543 dns_message_destroy(&tcpmsg);
01544
01545 if (cleanup_cctx)
01546 dns_compress_invalidate(&cctx);
01547
01548
01549
01550
01551 xfr->stream->methods->pause(xfr->stream);
01552
01553 if (result == ISC_R_SUCCESS)
01554 return;
01555
01556 xfrout_fail(xfr, result, "sending zone data");
01557 }
01558
01559 static void
01560 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
01561 xfrout_ctx_t *xfr = *xfrp;
01562 ns_client_t *client = NULL;
01563
01564 INSIST(xfr->sends == 0);
01565
01566 xfr->client->shutdown = NULL;
01567 xfr->client->shutdown_arg = NULL;
01568
01569 if (xfr->stream != NULL)
01570 xfr->stream->methods->destroy(&xfr->stream);
01571 if (xfr->buf.base != NULL)
01572 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
01573 if (xfr->txmem != NULL)
01574 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
01575 if (xfr->lasttsig != NULL)
01576 isc_buffer_free(&xfr->lasttsig);
01577 if (xfr->quota != NULL)
01578 isc_quota_detach(&xfr->quota);
01579 if (xfr->ver != NULL)
01580 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
01581 if (xfr->zone != NULL)
01582 dns_zone_detach(&xfr->zone);
01583 if (xfr->db != NULL)
01584 dns_db_detach(&xfr->db);
01585
01586
01587
01588
01589
01590 ns_client_attach(xfr->client, &client);
01591 ns_client_detach(&xfr->client);
01592 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
01593 ns_client_detach(&client);
01594
01595 *xfrp = NULL;
01596 }
01597
01598 static void
01599 xfrout_senddone(isc_task_t *task, isc_event_t *event) {
01600 isc_socketevent_t *sev = (isc_socketevent_t *)event;
01601 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
01602 isc_result_t evresult = sev->result;
01603
01604 UNUSED(task);
01605
01606 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
01607
01608 isc_event_free(&event);
01609 xfr->sends--;
01610 INSIST(xfr->sends == 0);
01611
01612 (void)isc_timer_touch(xfr->client->timer);
01613 if (xfr->shuttingdown == ISC_TRUE) {
01614 xfrout_maybe_destroy(xfr);
01615 } else if (evresult != ISC_R_SUCCESS) {
01616 xfrout_fail(xfr, evresult, "send");
01617 } else if (xfr->end_of_stream == ISC_FALSE) {
01618 sendstream(xfr);
01619 } else {
01620
01621 inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
01622 xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
01623 ns_client_next(xfr->client, ISC_R_SUCCESS);
01624 xfrout_ctx_destroy(&xfr);
01625 }
01626 }
01627
01628 static void
01629 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
01630 xfr->shuttingdown = ISC_TRUE;
01631 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
01632 msg, isc_result_totext(result));
01633 xfrout_maybe_destroy(xfr);
01634 }
01635
01636 static void
01637 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
01638 INSIST(xfr->shuttingdown == ISC_TRUE);
01639 if (xfr->sends > 0) {
01640
01641
01642
01643
01644 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
01645 ISC_SOCKCANCEL_SEND);
01646 } else {
01647 ns_client_next(xfr->client, ISC_R_CANCELED);
01648 xfrout_ctx_destroy(&xfr);
01649 }
01650 }
01651
01652 static void
01653 xfrout_client_shutdown(void *arg, isc_result_t result) {
01654 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
01655 xfrout_fail(xfr, result, "aborted");
01656 }
01657
01658
01659
01660
01661
01662
01663 static void
01664 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
01665 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
01666 ISC_FORMAT_PRINTF(5, 0);
01667
01668 static void
01669 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
01670 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
01671 {
01672 char msgbuf[2048];
01673 char namebuf[DNS_NAME_FORMATSIZE];
01674 char classbuf[DNS_RDATACLASS_FORMATSIZE];
01675
01676 dns_name_format(zonename, namebuf, sizeof(namebuf));
01677 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
01678 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
01679 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
01680 NS_LOGMODULE_XFER_OUT, level,
01681 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
01682 }
01683
01684
01685
01686
01687 static void
01688 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
01689 dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
01690 va_list ap;
01691 va_start(ap, fmt);
01692 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
01693 va_end(ap);
01694 }
01695
01696
01697
01698
01699 static void
01700 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
01701 va_list ap;
01702 va_start(ap, fmt);
01703 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
01704 va_end(ap);
01705 }