xfrout.c revision 135446
1/* 2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: xfrout.c,v 1.101.2.5.2.10 2004/04/02 06:08:17 marka Exp $ */ 19 20#include <config.h> 21 22#include <isc/formatcheck.h> 23#include <isc/mem.h> 24#include <isc/timer.h> 25#include <isc/print.h> 26#include <isc/util.h> 27 28#include <dns/db.h> 29#include <dns/dbiterator.h> 30#include <dns/fixedname.h> 31#include <dns/journal.h> 32#include <dns/message.h> 33#include <dns/peer.h> 34#include <dns/rdataclass.h> 35#include <dns/rdatalist.h> 36#include <dns/rdataset.h> 37#include <dns/rdatasetiter.h> 38#include <dns/result.h> 39#include <dns/soa.h> 40#include <dns/timer.h> 41#include <dns/tsig.h> 42#include <dns/view.h> 43#include <dns/zone.h> 44#include <dns/zt.h> 45 46#include <named/client.h> 47#include <named/log.h> 48#include <named/server.h> 49#include <named/xfrout.h> 50 51/* 52 * Outgoing AXFR and IXFR. 53 */ 54 55/* 56 * TODO: 57 * - IXFR over UDP 58 */ 59 60#define XFROUT_COMMON_LOGARGS \ 61 ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT 62 63#define XFROUT_PROTOCOL_LOGARGS \ 64 XFROUT_COMMON_LOGARGS, ISC_LOG_INFO 65 66#define XFROUT_DEBUG_LOGARGS(n) \ 67 XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n) 68 69#define XFROUT_RR_LOGARGS \ 70 XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL 71 72#define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8) 73 74/* 75 * Fail unconditionally and log as a client error. 76 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler 77 * from complaining about "end-of-loop code not reached". 78 */ 79#define FAILC(code, msg) \ 80 do { \ 81 result = (code); \ 82 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \ 83 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \ 84 "bad zone transfer request: %s (%s)", \ 85 msg, isc_result_totext(code)); \ 86 if (result != ISC_R_SUCCESS) goto failure; \ 87 } while (0) 88 89#define FAILQ(code, msg, question, rdclass) \ 90 do { \ 91 char _buf1[DNS_NAME_FORMATSIZE]; \ 92 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \ 93 result = (code); \ 94 dns_name_format(question, _buf1, sizeof(_buf1)); \ 95 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \ 96 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \ 97 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \ 98 "bad zone transfer request: '%s/%s': %s (%s)", \ 99 _buf1, _buf2, msg, isc_result_totext(code)); \ 100 if (result != ISC_R_SUCCESS) goto failure; \ 101 } while (0) 102 103#define CHECK(op) \ 104 do { result = (op); \ 105 if (result != ISC_R_SUCCESS) goto failure; \ 106 } while (0) 107 108/**************************************************************************/ 109/* 110 * A db_rr_iterator_t is an iterator that iterates over an entire database, 111 * returning one RR at a time, in some arbitrary order. 112 */ 113 114typedef struct db_rr_iterator db_rr_iterator_t; 115 116struct db_rr_iterator { 117 isc_result_t result; 118 dns_db_t *db; 119 dns_dbiterator_t *dbit; 120 dns_dbversion_t *ver; 121 isc_stdtime_t now; 122 dns_dbnode_t *node; 123 dns_fixedname_t fixedname; 124 dns_rdatasetiter_t *rdatasetit; 125 dns_rdataset_t rdataset; 126 dns_rdata_t rdata; 127}; 128 129static isc_result_t 130db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 131 isc_stdtime_t now); 132 133static isc_result_t 134db_rr_iterator_first(db_rr_iterator_t *it); 135 136static isc_result_t 137db_rr_iterator_next(db_rr_iterator_t *it); 138 139static void 140db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, 141 isc_uint32_t *ttl, dns_rdata_t **rdata); 142 143static void 144db_rr_iterator_destroy(db_rr_iterator_t *it); 145 146static isc_result_t 147db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver, 148 isc_stdtime_t now) 149{ 150 isc_result_t result; 151 it->db = db; 152 it->dbit = NULL; 153 it->ver = ver; 154 it->now = now; 155 it->node = NULL; 156 result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit); 157 if (result != ISC_R_SUCCESS) 158 return (result); 159 it->rdatasetit = NULL; 160 dns_rdata_init(&it->rdata); 161 dns_rdataset_init(&it->rdataset); 162 dns_fixedname_init(&it->fixedname); 163 INSIST(! dns_rdataset_isassociated(&it->rdataset)); 164 it->result = ISC_R_SUCCESS; 165 return (it->result); 166} 167 168static isc_result_t 169db_rr_iterator_first(db_rr_iterator_t *it) { 170 it->result = dns_dbiterator_first(it->dbit); 171 /* 172 * The top node may be empty when out of zone glue exists. 173 * Walk the tree to find the first node with data. 174 */ 175 while (it->result == ISC_R_SUCCESS) { 176 it->result = dns_dbiterator_current(it->dbit, &it->node, 177 dns_fixedname_name(&it->fixedname)); 178 if (it->result != ISC_R_SUCCESS) 179 return (it->result); 180 181 it->result = dns_db_allrdatasets(it->db, it->node, 182 it->ver, it->now, 183 &it->rdatasetit); 184 if (it->result != ISC_R_SUCCESS) 185 return (it->result); 186 187 it->result = dns_rdatasetiter_first(it->rdatasetit); 188 if (it->result != ISC_R_SUCCESS) { 189 /* 190 * This node is empty. Try next node. 191 */ 192 dns_rdatasetiter_destroy(&it->rdatasetit); 193 dns_db_detachnode(it->db, &it->node); 194 it->result = dns_dbiterator_next(it->dbit); 195 continue; 196 } 197 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 198 199 it->result = dns_rdataset_first(&it->rdataset); 200 return (it->result); 201 } 202 return (it->result); 203} 204 205 206static isc_result_t 207db_rr_iterator_next(db_rr_iterator_t *it) { 208 if (it->result != ISC_R_SUCCESS) 209 return (it->result); 210 211 INSIST(it->dbit != NULL); 212 INSIST(it->node != NULL); 213 INSIST(it->rdatasetit != NULL); 214 215 it->result = dns_rdataset_next(&it->rdataset); 216 if (it->result == ISC_R_NOMORE) { 217 dns_rdataset_disassociate(&it->rdataset); 218 it->result = dns_rdatasetiter_next(it->rdatasetit); 219 /* 220 * The while loop body is executed more than once 221 * only when an empty dbnode needs to be skipped. 222 */ 223 while (it->result == ISC_R_NOMORE) { 224 dns_rdatasetiter_destroy(&it->rdatasetit); 225 dns_db_detachnode(it->db, &it->node); 226 it->result = dns_dbiterator_next(it->dbit); 227 if (it->result == ISC_R_NOMORE) { 228 /* We are at the end of the entire database. */ 229 return (it->result); 230 } 231 if (it->result != ISC_R_SUCCESS) 232 return (it->result); 233 it->result = dns_dbiterator_current(it->dbit, 234 &it->node, 235 dns_fixedname_name(&it->fixedname)); 236 if (it->result != ISC_R_SUCCESS) 237 return (it->result); 238 it->result = dns_db_allrdatasets(it->db, it->node, 239 it->ver, it->now, 240 &it->rdatasetit); 241 if (it->result != ISC_R_SUCCESS) 242 return (it->result); 243 it->result = dns_rdatasetiter_first(it->rdatasetit); 244 } 245 if (it->result != ISC_R_SUCCESS) 246 return (it->result); 247 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset); 248 it->result = dns_rdataset_first(&it->rdataset); 249 if (it->result != ISC_R_SUCCESS) 250 return (it->result); 251 } 252 return (it->result); 253} 254 255static void 256db_rr_iterator_pause(db_rr_iterator_t *it) { 257 RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS); 258} 259 260static void 261db_rr_iterator_destroy(db_rr_iterator_t *it) { 262 if (dns_rdataset_isassociated(&it->rdataset)) 263 dns_rdataset_disassociate(&it->rdataset); 264 if (it->rdatasetit != NULL) 265 dns_rdatasetiter_destroy(&it->rdatasetit); 266 if (it->node != NULL) 267 dns_db_detachnode(it->db, &it->node); 268 dns_dbiterator_destroy(&it->dbit); 269} 270 271static void 272db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name, 273 isc_uint32_t *ttl, dns_rdata_t **rdata) 274{ 275 REQUIRE(name != NULL && *name == NULL); 276 REQUIRE(it->result == ISC_R_SUCCESS); 277 *name = dns_fixedname_name(&it->fixedname); 278 *ttl = it->rdataset.ttl; 279 dns_rdata_reset(&it->rdata); 280 dns_rdataset_current(&it->rdataset, &it->rdata); 281 *rdata = &it->rdata; 282} 283 284/**************************************************************************/ 285 286/* Log an RR (for debugging) */ 287 288static void 289log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) { 290 isc_result_t result; 291 isc_buffer_t buf; 292 char mem[2000]; 293 dns_rdatalist_t rdl; 294 dns_rdataset_t rds; 295 dns_rdata_t rd = DNS_RDATA_INIT; 296 297 rdl.type = rdata->type; 298 rdl.rdclass = rdata->rdclass; 299 rdl.ttl = ttl; 300 ISC_LIST_INIT(rdl.rdata); 301 ISC_LINK_INIT(&rdl, link); 302 dns_rdataset_init(&rds); 303 dns_rdata_init(&rd); 304 dns_rdata_clone(rdata, &rd); 305 ISC_LIST_APPEND(rdl.rdata, &rd, link); 306 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS); 307 308 isc_buffer_init(&buf, mem, sizeof(mem)); 309 result = dns_rdataset_totext(&rds, name, 310 ISC_FALSE, ISC_FALSE, &buf); 311 312 /* 313 * We could use xfrout_log(), but that would produce 314 * very long lines with a repetitive prefix. 315 */ 316 if (result == ISC_R_SUCCESS) { 317 /* 318 * Get rid of final newline. 319 */ 320 INSIST(buf.used >= 1 && 321 ((char *) buf.base)[buf.used - 1] == '\n'); 322 buf.used--; 323 324 isc_log_write(XFROUT_RR_LOGARGS, "%.*s", 325 (int)isc_buffer_usedlength(&buf), 326 (char *)isc_buffer_base(&buf)); 327 } else { 328 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>"); 329 } 330} 331 332/**************************************************************************/ 333/* 334 * An 'rrstream_t' is a polymorphic iterator that returns 335 * a stream of resource records. There are multiple implementations, 336 * e.g. for generating AXFR and IXFR records streams. 337 */ 338 339typedef struct rrstream_methods rrstream_methods_t; 340 341typedef struct rrstream { 342 isc_mem_t *mctx; 343 rrstream_methods_t *methods; 344} rrstream_t; 345 346struct rrstream_methods { 347 isc_result_t (*first)(rrstream_t *); 348 isc_result_t (*next)(rrstream_t *); 349 void (*current)(rrstream_t *, 350 dns_name_t **, 351 isc_uint32_t *, 352 dns_rdata_t **); 353 void (*pause)(rrstream_t *); 354 void (*destroy)(rrstream_t **); 355}; 356 357static void 358rrstream_noop_pause(rrstream_t *rs) { 359 UNUSED(rs); 360} 361 362/**************************************************************************/ 363/* 364 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns 365 * an IXFR-like RR stream from a journal file. 366 * 367 * The SOA at the beginning of each sequence of additions 368 * or deletions are included in the stream, but the extra 369 * SOAs at the beginning and end of the entire transfer are 370 * not included. 371 */ 372 373typedef struct ixfr_rrstream { 374 rrstream_t common; 375 dns_journal_t *journal; 376} ixfr_rrstream_t; 377 378/* Forward declarations. */ 379static void 380ixfr_rrstream_destroy(rrstream_t **sp); 381 382static rrstream_methods_t ixfr_rrstream_methods; 383 384/* 385 * Returns: anything dns_journal_open() or dns_journal_iter_init() 386 * may return. 387 */ 388 389static isc_result_t 390ixfr_rrstream_create(isc_mem_t *mctx, 391 const char *journal_filename, 392 isc_uint32_t begin_serial, 393 isc_uint32_t end_serial, 394 rrstream_t **sp) 395{ 396 ixfr_rrstream_t *s; 397 isc_result_t result; 398 399 INSIST(sp != NULL && *sp == NULL); 400 401 s = isc_mem_get(mctx, sizeof(*s)); 402 if (s == NULL) 403 return (ISC_R_NOMEMORY); 404 s->common.mctx = mctx; 405 s->common.methods = &ixfr_rrstream_methods; 406 s->journal = NULL; 407 408 CHECK(dns_journal_open(mctx, journal_filename, 409 ISC_FALSE, &s->journal)); 410 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial)); 411 412 *sp = (rrstream_t *) s; 413 return (ISC_R_SUCCESS); 414 415 failure: 416 ixfr_rrstream_destroy((rrstream_t **) (void *)&s); 417 return (result); 418} 419 420static isc_result_t 421ixfr_rrstream_first(rrstream_t *rs) { 422 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; 423 return (dns_journal_first_rr(s->journal)); 424} 425 426static isc_result_t 427ixfr_rrstream_next(rrstream_t *rs) { 428 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; 429 return (dns_journal_next_rr(s->journal)); 430} 431 432static void 433ixfr_rrstream_current(rrstream_t *rs, 434 dns_name_t **name, isc_uint32_t *ttl, 435 dns_rdata_t **rdata) 436{ 437 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs; 438 dns_journal_current_rr(s->journal, name, ttl, rdata); 439} 440 441static void 442ixfr_rrstream_destroy(rrstream_t **rsp) { 443 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp; 444 if (s->journal != 0) 445 dns_journal_destroy(&s->journal); 446 isc_mem_put(s->common.mctx, s, sizeof(*s)); 447} 448 449static rrstream_methods_t ixfr_rrstream_methods = { 450 ixfr_rrstream_first, 451 ixfr_rrstream_next, 452 ixfr_rrstream_current, 453 rrstream_noop_pause, 454 ixfr_rrstream_destroy 455}; 456 457/**************************************************************************/ 458/* 459 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns 460 * an AXFR-like RR stream from a database. 461 * 462 * The SOAs at the beginning and end of the transfer are 463 * not included in the stream. 464 */ 465 466typedef struct axfr_rrstream { 467 rrstream_t common; 468 db_rr_iterator_t it; 469 isc_boolean_t it_valid; 470} axfr_rrstream_t; 471 472/* 473 * Forward declarations. 474 */ 475static void 476axfr_rrstream_destroy(rrstream_t **rsp); 477 478static rrstream_methods_t axfr_rrstream_methods; 479 480static isc_result_t 481axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, 482 rrstream_t **sp) 483{ 484 axfr_rrstream_t *s; 485 isc_result_t result; 486 487 INSIST(sp != NULL && *sp == NULL); 488 489 s = isc_mem_get(mctx, sizeof(*s)); 490 if (s == NULL) 491 return (ISC_R_NOMEMORY); 492 s->common.mctx = mctx; 493 s->common.methods = &axfr_rrstream_methods; 494 s->it_valid = ISC_FALSE; 495 496 CHECK(db_rr_iterator_init(&s->it, db, ver, 0)); 497 s->it_valid = ISC_TRUE; 498 499 *sp = (rrstream_t *) s; 500 return (ISC_R_SUCCESS); 501 502 failure: 503 axfr_rrstream_destroy((rrstream_t **) (void *)&s); 504 return (result); 505} 506 507static isc_result_t 508axfr_rrstream_first(rrstream_t *rs) { 509 axfr_rrstream_t *s = (axfr_rrstream_t *) rs; 510 isc_result_t result; 511 result = db_rr_iterator_first(&s->it); 512 if (result != ISC_R_SUCCESS) 513 return (result); 514 /* Skip SOA records. */ 515 for (;;) { 516 dns_name_t *name_dummy = NULL; 517 isc_uint32_t ttl_dummy; 518 dns_rdata_t *rdata = NULL; 519 db_rr_iterator_current(&s->it, &name_dummy, 520 &ttl_dummy, &rdata); 521 if (rdata->type != dns_rdatatype_soa) 522 break; 523 result = db_rr_iterator_next(&s->it); 524 if (result != ISC_R_SUCCESS) 525 break; 526 } 527 return (result); 528} 529 530static isc_result_t 531axfr_rrstream_next(rrstream_t *rs) { 532 axfr_rrstream_t *s = (axfr_rrstream_t *) rs; 533 isc_result_t result; 534 535 /* Skip SOA records. */ 536 for (;;) { 537 dns_name_t *name_dummy = NULL; 538 isc_uint32_t ttl_dummy; 539 dns_rdata_t *rdata = NULL; 540 result = db_rr_iterator_next(&s->it); 541 if (result != ISC_R_SUCCESS) 542 break; 543 db_rr_iterator_current(&s->it, &name_dummy, 544 &ttl_dummy, &rdata); 545 if (rdata->type != dns_rdatatype_soa) 546 break; 547 } 548 return (result); 549} 550 551static void 552axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, 553 dns_rdata_t **rdata) 554{ 555 axfr_rrstream_t *s = (axfr_rrstream_t *) rs; 556 db_rr_iterator_current(&s->it, name, ttl, rdata); 557} 558 559static void 560axfr_rrstream_pause(rrstream_t *rs) { 561 axfr_rrstream_t *s = (axfr_rrstream_t *) rs; 562 db_rr_iterator_pause(&s->it); 563} 564 565static void 566axfr_rrstream_destroy(rrstream_t **rsp) { 567 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp; 568 if (s->it_valid) 569 db_rr_iterator_destroy(&s->it); 570 isc_mem_put(s->common.mctx, s, sizeof(*s)); 571} 572 573static rrstream_methods_t axfr_rrstream_methods = { 574 axfr_rrstream_first, 575 axfr_rrstream_next, 576 axfr_rrstream_current, 577 axfr_rrstream_pause, 578 axfr_rrstream_destroy 579}; 580 581/**************************************************************************/ 582/* 583 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns 584 * a single SOA record. 585 */ 586 587typedef struct soa_rrstream { 588 rrstream_t common; 589 dns_difftuple_t *soa_tuple; 590} soa_rrstream_t; 591 592/* 593 * Forward declarations. 594 */ 595static void 596soa_rrstream_destroy(rrstream_t **rsp); 597 598static rrstream_methods_t soa_rrstream_methods; 599 600static isc_result_t 601soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver, 602 rrstream_t **sp) 603{ 604 soa_rrstream_t *s; 605 isc_result_t result; 606 607 INSIST(sp != NULL && *sp == NULL); 608 609 s = isc_mem_get(mctx, sizeof(*s)); 610 if (s == NULL) 611 return (ISC_R_NOMEMORY); 612 s->common.mctx = mctx; 613 s->common.methods = &soa_rrstream_methods; 614 s->soa_tuple = NULL; 615 616 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, 617 &s->soa_tuple)); 618 619 *sp = (rrstream_t *) s; 620 return (ISC_R_SUCCESS); 621 622 failure: 623 soa_rrstream_destroy((rrstream_t **) (void *)&s); 624 return (result); 625} 626 627static isc_result_t 628soa_rrstream_first(rrstream_t *rs) { 629 UNUSED(rs); 630 return (ISC_R_SUCCESS); 631} 632 633static isc_result_t 634soa_rrstream_next(rrstream_t *rs) { 635 UNUSED(rs); 636 return (ISC_R_NOMORE); 637} 638 639static void 640soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, 641 dns_rdata_t **rdata) 642{ 643 soa_rrstream_t *s = (soa_rrstream_t *) rs; 644 *name = &s->soa_tuple->name; 645 *ttl = s->soa_tuple->ttl; 646 *rdata = &s->soa_tuple->rdata; 647} 648 649static void 650soa_rrstream_destroy(rrstream_t **rsp) { 651 soa_rrstream_t *s = (soa_rrstream_t *) *rsp; 652 if (s->soa_tuple != NULL) 653 dns_difftuple_free(&s->soa_tuple); 654 isc_mem_put(s->common.mctx, s, sizeof(*s)); 655} 656 657static rrstream_methods_t soa_rrstream_methods = { 658 soa_rrstream_first, 659 soa_rrstream_next, 660 soa_rrstream_current, 661 rrstream_noop_pause, 662 soa_rrstream_destroy 663}; 664 665/**************************************************************************/ 666/* 667 * A 'compound_rrstream_t' objects owns a soa_rrstream 668 * and another rrstream, the "data stream". It returns 669 * a concatenated stream consisting of the soa_rrstream, then 670 * the data stream, then the soa_rrstream again. 671 * 672 * The component streams are owned by the compound_rrstream_t 673 * and are destroyed with it. 674 */ 675 676typedef struct compound_rrstream { 677 rrstream_t common; 678 rrstream_t *components[3]; 679 int state; 680 isc_result_t result; 681} compound_rrstream_t; 682 683/* 684 * Forward declarations. 685 */ 686static void 687compound_rrstream_destroy(rrstream_t **rsp); 688 689static isc_result_t 690compound_rrstream_next(rrstream_t *rs); 691 692static rrstream_methods_t compound_rrstream_methods; 693 694/* 695 * Requires: 696 * soa_stream != NULL && *soa_stream != NULL 697 * data_stream != NULL && *data_stream != NULL 698 * sp != NULL && *sp == NULL 699 * 700 * Ensures: 701 * *soa_stream == NULL 702 * *data_stream == NULL 703 * *sp points to a valid compound_rrstream_t 704 * The soa and data streams will be destroyed 705 * when the compound_rrstream_t is destroyed. 706 */ 707static isc_result_t 708compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream, 709 rrstream_t **data_stream, rrstream_t **sp) 710{ 711 compound_rrstream_t *s; 712 713 INSIST(sp != NULL && *sp == NULL); 714 715 s = isc_mem_get(mctx, sizeof(*s)); 716 if (s == NULL) 717 return (ISC_R_NOMEMORY); 718 s->common.mctx = mctx; 719 s->common.methods = &compound_rrstream_methods; 720 s->components[0] = *soa_stream; 721 s->components[1] = *data_stream; 722 s->components[2] = *soa_stream; 723 s->state = -1; 724 s->result = ISC_R_FAILURE; 725 726 *soa_stream = NULL; 727 *data_stream = NULL; 728 *sp = (rrstream_t *) s; 729 return (ISC_R_SUCCESS); 730} 731 732static isc_result_t 733compound_rrstream_first(rrstream_t *rs) { 734 compound_rrstream_t *s = (compound_rrstream_t *) rs; 735 s->state = 0; 736 do { 737 rrstream_t *curstream = s->components[s->state]; 738 s->result = curstream->methods->first(curstream); 739 } while (s->result == ISC_R_NOMORE && s->state < 2); 740 return (s->result); 741} 742 743static isc_result_t 744compound_rrstream_next(rrstream_t *rs) { 745 compound_rrstream_t *s = (compound_rrstream_t *) rs; 746 rrstream_t *curstream = s->components[s->state]; 747 s->result = curstream->methods->next(curstream); 748 while (s->result == ISC_R_NOMORE) { 749 /* 750 * Make sure locks held by the current stream 751 * are released before we switch streams. 752 */ 753 curstream->methods->pause(curstream); 754 if (s->state == 2) 755 return (ISC_R_NOMORE); 756 s->state++; 757 curstream = s->components[s->state]; 758 s->result = curstream->methods->first(curstream); 759 } 760 return (s->result); 761} 762 763static void 764compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl, 765 dns_rdata_t **rdata) 766{ 767 compound_rrstream_t *s = (compound_rrstream_t *) rs; 768 rrstream_t *curstream; 769 INSIST(0 <= s->state && s->state < 3); 770 INSIST(s->result == ISC_R_SUCCESS); 771 curstream = s->components[s->state]; 772 curstream->methods->current(curstream, name, ttl, rdata); 773} 774 775static void 776compound_rrstream_pause(rrstream_t *rs) 777{ 778 compound_rrstream_t *s = (compound_rrstream_t *) rs; 779 rrstream_t *curstream; 780 INSIST(0 <= s->state && s->state < 3); 781 curstream = s->components[s->state]; 782 curstream->methods->pause(curstream); 783} 784 785static void 786compound_rrstream_destroy(rrstream_t **rsp) { 787 compound_rrstream_t *s = (compound_rrstream_t *) *rsp; 788 s->components[0]->methods->destroy(&s->components[0]); 789 s->components[1]->methods->destroy(&s->components[1]); 790 s->components[2] = NULL; /* Copy of components[0]. */ 791 isc_mem_put(s->common.mctx, s, sizeof(*s)); 792} 793 794static rrstream_methods_t compound_rrstream_methods = { 795 compound_rrstream_first, 796 compound_rrstream_next, 797 compound_rrstream_current, 798 compound_rrstream_pause, 799 compound_rrstream_destroy 800}; 801 802/**************************************************************************/ 803/* 804 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR 805 * in progress. 806 */ 807 808typedef struct { 809 isc_mem_t *mctx; 810 ns_client_t *client; 811 unsigned int id; /* ID of request */ 812 dns_name_t *qname; /* Question name of request */ 813 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */ 814 dns_rdataclass_t qclass; 815 dns_db_t *db; 816 dns_dbversion_t *ver; 817 isc_quota_t *quota; 818 rrstream_t *stream; /* The XFR RR stream */ 819 isc_boolean_t end_of_stream; /* EOS has been reached */ 820 isc_buffer_t buf; /* Buffer for message owner 821 names and rdatas */ 822 isc_buffer_t txlenbuf; /* Transmit length buffer */ 823 isc_buffer_t txbuf; /* Transmit message buffer */ 824 void *txmem; 825 unsigned int txmemlen; 826 unsigned int nmsg; /* Number of messages sent */ 827 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */ 828 isc_buffer_t *lasttsig; /* the last TSIG */ 829 isc_boolean_t many_answers; 830 int sends; /* Send in progress */ 831 isc_boolean_t shuttingdown; 832 const char *mnemonic; /* Style of transfer */ 833} xfrout_ctx_t; 834 835static isc_result_t 836xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, 837 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype, 838 dns_rdataclass_t qclass, 839 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, 840 rrstream_t *stream, dns_tsigkey_t *tsigkey, 841 isc_buffer_t *lasttsig, 842 unsigned int maxtime, 843 unsigned int idletime, 844 isc_boolean_t many_answers, 845 xfrout_ctx_t **xfrp); 846 847static void 848sendstream(xfrout_ctx_t *xfr); 849 850static void 851xfrout_senddone(isc_task_t *task, isc_event_t *event); 852 853static void 854xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg); 855 856static void 857xfrout_maybe_destroy(xfrout_ctx_t *xfr); 858 859static void 860xfrout_ctx_destroy(xfrout_ctx_t **xfrp); 861 862static void 863xfrout_client_shutdown(void *arg, isc_result_t result); 864 865static void 866xfrout_log1(ns_client_t *client, dns_name_t *zonename, 867 dns_rdataclass_t rdclass, int level, 868 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6); 869 870static void 871xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) 872 ISC_FORMAT_PRINTF(3, 4); 873 874/**************************************************************************/ 875 876void 877ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { 878 isc_result_t result; 879 dns_name_t *question_name; 880 dns_rdataset_t *question_rdataset; 881 dns_zone_t *zone = NULL; 882 dns_db_t *db = NULL; 883 dns_dbversion_t *ver = NULL; 884 dns_rdataclass_t question_class; 885 rrstream_t *soa_stream = NULL; 886 rrstream_t *data_stream = NULL; 887 rrstream_t *stream = NULL; 888 dns_difftuple_t *current_soa_tuple = NULL; 889 dns_name_t *soa_name; 890 dns_rdataset_t *soa_rdataset; 891 dns_rdata_t soa_rdata = DNS_RDATA_INIT; 892 isc_boolean_t have_soa = ISC_FALSE; 893 const char *mnemonic = NULL; 894 isc_mem_t *mctx = client->mctx; 895 dns_message_t *request = client->message; 896 xfrout_ctx_t *xfr = NULL; 897 isc_quota_t *quota = NULL; 898 dns_transfer_format_t format = client->view->transfer_format; 899 isc_netaddr_t na; 900 dns_peer_t *peer = NULL; 901 isc_buffer_t *tsigbuf = NULL; 902 char *journalfile; 903 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")]; 904 char keyname[DNS_NAME_FORMATSIZE]; 905 isc_boolean_t is_poll = ISC_FALSE; 906 907 switch (reqtype) { 908 case dns_rdatatype_axfr: 909 mnemonic = "AXFR"; 910 break; 911 case dns_rdatatype_ixfr: 912 mnemonic = "IXFR"; 913 break; 914 default: 915 INSIST(0); 916 break; 917 } 918 919 ns_client_log(client, 920 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, 921 ISC_LOG_DEBUG(6), "%s request", mnemonic); 922 /* 923 * Apply quota. 924 */ 925 result = isc_quota_attach(&ns_g_server->xfroutquota, "a); 926 if (result != ISC_R_SUCCESS) { 927 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, 928 "%s request denied: %s", mnemonic, 929 isc_result_totext(result)); 930 goto failure; 931 } 932 933 /* 934 * Interpret the question section. 935 */ 936 result = dns_message_firstname(request, DNS_SECTION_QUESTION); 937 INSIST(result == ISC_R_SUCCESS); 938 939 /* 940 * The question section must contain exactly one question, and 941 * it must be for AXFR/IXFR as appropriate. 942 */ 943 question_name = NULL; 944 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name); 945 question_rdataset = ISC_LIST_HEAD(question_name->list); 946 question_class = question_rdataset->rdclass; 947 INSIST(question_rdataset->type == reqtype); 948 if (ISC_LIST_NEXT(question_rdataset, link) != NULL) 949 FAILC(DNS_R_FORMERR, "multiple questions"); 950 result = dns_message_nextname(request, DNS_SECTION_QUESTION); 951 if (result != ISC_R_NOMORE) 952 FAILC(DNS_R_FORMERR, "multiple questions"); 953 954 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL, 955 &zone); 956 if (result != ISC_R_SUCCESS) 957 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", 958 question_name, question_class); 959 switch(dns_zone_gettype(zone)) { 960 case dns_zone_master: 961 case dns_zone_slave: 962 break; /* Master and slave zones are OK for transfer. */ 963 default: 964 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", 965 question_name, question_class); 966 } 967 CHECK(dns_zone_getdb(zone, &db)); 968 dns_db_currentversion(db, &ver); 969 970 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), 971 "%s question section OK", mnemonic); 972 973 /* 974 * Check the authority section. Look for a SOA record with 975 * the same name and class as the question. 976 */ 977 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY); 978 result == ISC_R_SUCCESS; 979 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY)) 980 { 981 soa_name = NULL; 982 dns_message_currentname(request, DNS_SECTION_AUTHORITY, 983 &soa_name); 984 985 /* 986 * Ignore data whose owner name is not the zone apex. 987 */ 988 if (! dns_name_equal(soa_name, question_name)) 989 continue; 990 991 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list); 992 soa_rdataset != NULL; 993 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link)) 994 { 995 /* 996 * Ignore non-SOA data. 997 */ 998 if (soa_rdataset->type != dns_rdatatype_soa) 999 continue; 1000 if (soa_rdataset->rdclass != question_class) 1001 continue; 1002 1003 CHECK(dns_rdataset_first(soa_rdataset)); 1004 dns_rdataset_current(soa_rdataset, &soa_rdata); 1005 result = dns_rdataset_next(soa_rdataset); 1006 if (result == ISC_R_SUCCESS) 1007 FAILC(DNS_R_FORMERR, 1008 "IXFR authority section " 1009 "has multiple SOAs"); 1010 have_soa = ISC_TRUE; 1011 goto got_soa; 1012 } 1013 } 1014 got_soa: 1015 if (result != ISC_R_NOMORE) 1016 CHECK(result); 1017 1018 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), 1019 "%s authority section OK", mnemonic); 1020 1021 /* 1022 * Decide whether to allow this transfer. 1023 */ 1024 ns_client_aclmsg("zone transfer", question_name, reqtype, 1025 client->view->rdclass, msg, sizeof(msg)); 1026 CHECK(ns_client_checkacl(client, msg, 1027 dns_zone_getxfracl(zone), ISC_TRUE, 1028 ISC_LOG_ERROR)); 1029 1030 /* 1031 * AXFR over UDP is not possible. 1032 */ 1033 if (reqtype == dns_rdatatype_axfr && 1034 (client->attributes & NS_CLIENTATTR_TCP) == 0) 1035 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); 1036 1037 /* 1038 * Look up the requesting server in the peer table. 1039 */ 1040 isc_netaddr_fromsockaddr(&na, &client->peeraddr); 1041 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer); 1042 1043 /* 1044 * Decide on the transfer format (one-answer or many-answers). 1045 */ 1046 if (peer != NULL) 1047 (void)dns_peer_gettransferformat(peer, &format); 1048 1049 /* 1050 * Get a dynamically allocated copy of the current SOA. 1051 */ 1052 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, 1053 ¤t_soa_tuple)); 1054 1055 if (reqtype == dns_rdatatype_ixfr) { 1056 isc_uint32_t begin_serial, current_serial; 1057 isc_boolean_t provide_ixfr; 1058 1059 /* 1060 * Outgoing IXFR may have been disabled for this peer 1061 * or globally. 1062 */ 1063 provide_ixfr = client->view->provideixfr; 1064 if (peer != NULL) 1065 (void) dns_peer_getprovideixfr(peer, &provide_ixfr); 1066 if (provide_ixfr == ISC_FALSE) 1067 goto axfr_fallback; 1068 1069 if (! have_soa) 1070 FAILC(DNS_R_FORMERR, 1071 "IXFR request missing SOA"); 1072 1073 begin_serial = dns_soa_getserial(&soa_rdata); 1074 current_serial = dns_soa_getserial(¤t_soa_tuple->rdata); 1075 1076 /* 1077 * RFC1995 says "If an IXFR query with the same or 1078 * newer version number than that of the server 1079 * is received, it is replied to with a single SOA 1080 * record of the server's current version, just as 1081 * in AXFR". The claim about AXFR is incorrect, 1082 * but other than that, we do as the RFC says. 1083 * 1084 * Sending a single SOA record is also how we refuse 1085 * IXFR over UDP (currently, we always do). 1086 */ 1087 if (DNS_SERIAL_GE(begin_serial, current_serial) || 1088 (client->attributes & NS_CLIENTATTR_TCP) == 0) 1089 { 1090 CHECK(soa_rrstream_create(mctx, db, ver, &stream)); 1091 is_poll = ISC_TRUE; 1092 goto have_stream; 1093 } 1094 journalfile = dns_zone_getjournal(zone); 1095 if (journalfile != NULL) 1096 result = ixfr_rrstream_create(mctx, 1097 journalfile, 1098 begin_serial, 1099 current_serial, 1100 &data_stream); 1101 else 1102 result = ISC_R_NOTFOUND; 1103 if (result == ISC_R_NOTFOUND || 1104 result == ISC_R_RANGE) { 1105 xfrout_log1(client, question_name, question_class, 1106 ISC_LOG_DEBUG(4), 1107 "IXFR version not in journal, " 1108 "falling back to AXFR"); 1109 mnemonic = "AXFR-style IXFR"; 1110 goto axfr_fallback; 1111 } 1112 CHECK(result); 1113 } else { 1114 axfr_fallback: 1115 CHECK(axfr_rrstream_create(mctx, db, ver, 1116 &data_stream)); 1117 } 1118 1119 /* 1120 * Bracket the the data stream with SOAs. 1121 */ 1122 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream)); 1123 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream, 1124 &stream)); 1125 soa_stream = NULL; 1126 data_stream = NULL; 1127 1128 have_stream: 1129 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); 1130 /* 1131 * Create the xfrout context object. This transfers the ownership 1132 * of "stream", "db", "ver", and "quota" to the xfrout context object. 1133 */ 1134 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, 1135 reqtype, question_class, db, ver, quota, 1136 stream, dns_message_gettsigkey(request), 1137 tsigbuf, 1138 dns_zone_getmaxxfrout(zone), 1139 dns_zone_getidleout(zone), 1140 (format == dns_many_answers) ? 1141 ISC_TRUE : ISC_FALSE, 1142 &xfr)); 1143 xfr->mnemonic = mnemonic; 1144 stream = NULL; 1145 quota = NULL; 1146 1147 CHECK(xfr->stream->methods->first(xfr->stream)); 1148 1149 if (xfr->tsigkey != NULL) { 1150 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname)); 1151 } else 1152 keyname[0] = '\0'; 1153 if (is_poll) 1154 xfrout_log1(client, question_name, question_class, 1155 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s", 1156 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname); 1157 else 1158 xfrout_log1(client, question_name, question_class, 1159 ISC_LOG_INFO, "%s started%s%s", mnemonic, 1160 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname); 1161 1162 /* 1163 * Hand the context over to sendstream(). Set xfr to NULL; 1164 * sendstream() is responsible for either passing the 1165 * context on to a later event handler or destroying it. 1166 */ 1167 sendstream(xfr); 1168 xfr = NULL; 1169 1170 result = ISC_R_SUCCESS; 1171 1172 failure: 1173 if (quota != NULL) 1174 isc_quota_detach("a); 1175 if (current_soa_tuple != NULL) 1176 dns_difftuple_free(¤t_soa_tuple); 1177 if (stream != NULL) 1178 stream->methods->destroy(&stream); 1179 if (soa_stream != NULL) 1180 soa_stream->methods->destroy(&soa_stream); 1181 if (data_stream != NULL) 1182 data_stream->methods->destroy(&data_stream); 1183 if (ver != NULL) 1184 dns_db_closeversion(db, &ver, ISC_FALSE); 1185 if (db != NULL) 1186 dns_db_detach(&db); 1187 if (zone != NULL) 1188 dns_zone_detach(&zone); 1189 /* XXX kludge */ 1190 if (xfr != NULL) { 1191 xfrout_fail(xfr, result, "setting up zone transfer"); 1192 } else if (result != ISC_R_SUCCESS) { 1193 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, 1194 NS_LOGMODULE_XFER_OUT, 1195 ISC_LOG_DEBUG(3), "zone transfer setup failed"); 1196 ns_client_error(client, result); 1197 } 1198} 1199 1200static isc_result_t 1201xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id, 1202 dns_name_t *qname, dns_rdatatype_t qtype, 1203 dns_rdataclass_t qclass, 1204 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota, 1205 rrstream_t *stream, dns_tsigkey_t *tsigkey, 1206 isc_buffer_t *lasttsig, unsigned int maxtime, 1207 unsigned int idletime, isc_boolean_t many_answers, 1208 xfrout_ctx_t **xfrp) 1209{ 1210 xfrout_ctx_t *xfr; 1211 isc_result_t result; 1212 unsigned int len; 1213 void *mem; 1214 1215 INSIST(xfrp != NULL && *xfrp == NULL); 1216 xfr = isc_mem_get(mctx, sizeof(*xfr)); 1217 if (xfr == NULL) 1218 return (ISC_R_NOMEMORY); 1219 xfr->mctx = mctx; 1220 xfr->client = NULL; 1221 ns_client_attach(client, &xfr->client); 1222 xfr->id = id; 1223 xfr->qname = qname; 1224 xfr->qtype = qtype; 1225 xfr->qclass = qclass; 1226 xfr->db = NULL; 1227 xfr->ver = NULL; 1228 dns_db_attach(db, &xfr->db); 1229 dns_db_attachversion(db, ver, &xfr->ver); 1230 xfr->end_of_stream = ISC_FALSE; 1231 xfr->tsigkey = tsigkey; 1232 xfr->lasttsig = lasttsig; 1233 xfr->txmem = NULL; 1234 xfr->txmemlen = 0; 1235 xfr->nmsg = 0; 1236 xfr->many_answers = many_answers, 1237 xfr->sends = 0; 1238 xfr->shuttingdown = ISC_FALSE; 1239 xfr->mnemonic = NULL; 1240 xfr->buf.base = NULL; 1241 xfr->buf.length = 0; 1242 xfr->txmem = NULL; 1243 xfr->txmemlen = 0; 1244 xfr->stream = NULL; 1245 xfr->quota = NULL; 1246 1247 /* 1248 * Allocate a temporary buffer for the uncompressed response 1249 * message data. The size should be no more than 65535 bytes 1250 * so that the compressed data will fit in a TCP message, 1251 * and no less than 65535 bytes so that an almost maximum-sized 1252 * RR will fit. Note that although 65535-byte RRs are allowed 1253 * in principle, they cannot be zone-transferred (at least not 1254 * if uncompressible), because the message and RR headers would 1255 * push the size of the TCP message over the 65536 byte limit. 1256 */ 1257 len = 65535; 1258 mem = isc_mem_get(mctx, len); 1259 if (mem == NULL) { 1260 result = ISC_R_NOMEMORY; 1261 goto failure; 1262 } 1263 isc_buffer_init(&xfr->buf, mem, len); 1264 1265 /* 1266 * Allocate another temporary buffer for the compressed 1267 * response message and its TCP length prefix. 1268 */ 1269 len = 2 + 65535; 1270 mem = isc_mem_get(mctx, len); 1271 if (mem == NULL) { 1272 result = ISC_R_NOMEMORY; 1273 goto failure; 1274 } 1275 isc_buffer_init(&xfr->txlenbuf, mem, 2); 1276 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2); 1277 xfr->txmem = mem; 1278 xfr->txmemlen = len; 1279 1280 CHECK(dns_timer_setidle(xfr->client->timer, 1281 maxtime, idletime, ISC_FALSE)); 1282 1283 /* 1284 * Register a shutdown callback with the client, so that we 1285 * can stop the transfer immediately when the client task 1286 * gets a shutdown event. 1287 */ 1288 xfr->client->shutdown = xfrout_client_shutdown; 1289 xfr->client->shutdown_arg = xfr; 1290 /* 1291 * These MUST be after the last "goto failure;" / CHECK to 1292 * prevent a double free by the caller. 1293 */ 1294 xfr->quota = quota; 1295 xfr->stream = stream; 1296 1297 *xfrp = xfr; 1298 return (ISC_R_SUCCESS); 1299 1300failure: 1301 xfrout_ctx_destroy(&xfr); 1302 return (result); 1303} 1304 1305 1306/* 1307 * Arrange to send as much as we can of "stream" without blocking. 1308 * 1309 * Requires: 1310 * The stream iterator is initialized and points at an RR, 1311 * or possiby at the end of the stream (that is, the 1312 * _first method of the iterator has been called). 1313 */ 1314static void 1315sendstream(xfrout_ctx_t *xfr) { 1316 dns_message_t *tcpmsg = NULL; 1317 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */ 1318 isc_result_t result; 1319 isc_region_t used; 1320 isc_region_t region; 1321 dns_rdataset_t *qrdataset; 1322 dns_name_t *msgname = NULL; 1323 dns_rdata_t *msgrdata = NULL; 1324 dns_rdatalist_t *msgrdl = NULL; 1325 dns_rdataset_t *msgrds = NULL; 1326 dns_compress_t cctx; 1327 isc_boolean_t cleanup_cctx = ISC_FALSE; 1328 1329 int n_rrs; 1330 1331 isc_buffer_clear(&xfr->buf); 1332 isc_buffer_clear(&xfr->txlenbuf); 1333 isc_buffer_clear(&xfr->txbuf); 1334 1335 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) { 1336 /* 1337 * In the UDP case, we put the response data directly into 1338 * the client message. 1339 */ 1340 msg = xfr->client->message; 1341 CHECK(dns_message_reply(msg, ISC_TRUE)); 1342 } else { 1343 /* 1344 * TCP. Build a response dns_message_t, temporarily storing 1345 * the raw, uncompressed owner names and RR data contiguously 1346 * in xfr->buf. We know that if the uncompressed data fits 1347 * in xfr->buf, the compressed data will surely fit in a TCP 1348 * message. 1349 */ 1350 1351 CHECK(dns_message_create(xfr->mctx, 1352 DNS_MESSAGE_INTENTRENDER, &tcpmsg)); 1353 msg = tcpmsg; 1354 1355 msg->id = xfr->id; 1356 msg->rcode = dns_rcode_noerror; 1357 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA; 1358 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) 1359 msg->flags |= DNS_MESSAGEFLAG_RA; 1360 CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); 1361 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); 1362 if (xfr->lasttsig != NULL) 1363 isc_buffer_free(&xfr->lasttsig); 1364 1365 /* 1366 * Include a question section in the first message only. 1367 * BIND 8.2.1 will not recognize an IXFR if it does not 1368 * have a question section. 1369 */ 1370 if (xfr->nmsg == 0) { 1371 dns_name_t *qname = NULL; 1372 isc_region_t r; 1373 1374 /* 1375 * Reserve space for the 12-byte message header 1376 * and 4 bytes of question. 1377 */ 1378 isc_buffer_add(&xfr->buf, 12 + 4); 1379 1380 qrdataset = NULL; 1381 result = dns_message_gettemprdataset(msg, &qrdataset); 1382 if (result != ISC_R_SUCCESS) 1383 goto failure; 1384 dns_rdataset_init(qrdataset); 1385 dns_rdataset_makequestion(qrdataset, 1386 xfr->client->message->rdclass, 1387 xfr->qtype); 1388 1389 result = dns_message_gettempname(msg, &qname); 1390 if (result != ISC_R_SUCCESS) 1391 goto failure; 1392 dns_name_init(qname, NULL); 1393 isc_buffer_availableregion(&xfr->buf, &r); 1394 INSIST(r.length >= xfr->qname->length); 1395 r.length = xfr->qname->length; 1396 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, 1397 xfr->qname->length); 1398 dns_name_fromregion(qname, &r); 1399 ISC_LIST_INIT(qname->list); 1400 ISC_LIST_APPEND(qname->list, qrdataset, link); 1401 1402 dns_message_addname(msg, qname, DNS_SECTION_QUESTION); 1403 } 1404 else 1405 msg->tcp_continuation = 1; 1406 } 1407 1408 /* 1409 * Try to fit in as many RRs as possible, unless "one-answer" 1410 * format has been requested. 1411 */ 1412 for (n_rrs = 0; ; n_rrs++) { 1413 dns_name_t *name = NULL; 1414 isc_uint32_t ttl; 1415 dns_rdata_t *rdata = NULL; 1416 1417 unsigned int size; 1418 isc_region_t r; 1419 1420 msgname = NULL; 1421 msgrdata = NULL; 1422 msgrdl = NULL; 1423 msgrds = NULL; 1424 1425 xfr->stream->methods->current(xfr->stream, 1426 &name, &ttl, &rdata); 1427 size = name->length + 10 + rdata->length; 1428 isc_buffer_availableregion(&xfr->buf, &r); 1429 if (size >= r.length) { 1430 /* 1431 * RR would not fit. If there are other RRs in the 1432 * buffer, send them now and leave this RR to the 1433 * next message. If this RR overflows the buffer 1434 * all by itself, fail. 1435 * 1436 * In theory some RRs might fit in a TCP message 1437 * when compressed even if they do not fit when 1438 * uncompressed, but surely we don't want 1439 * to send such monstrosities to an unsuspecting 1440 * slave. 1441 */ 1442 if (n_rrs == 0) { 1443 xfrout_log(xfr, ISC_LOG_WARNING, 1444 "RR too large for zone transfer " 1445 "(%d bytes)", size); 1446 /* XXX DNS_R_RRTOOLARGE? */ 1447 result = ISC_R_NOSPACE; 1448 goto failure; 1449 } 1450 break; 1451 } 1452 1453 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL)) 1454 log_rr(name, rdata, ttl); /* XXX */ 1455 1456 result = dns_message_gettempname(msg, &msgname); 1457 if (result != ISC_R_SUCCESS) 1458 goto failure; 1459 dns_name_init(msgname, NULL); 1460 isc_buffer_availableregion(&xfr->buf, &r); 1461 INSIST(r.length >= name->length); 1462 r.length = name->length; 1463 isc_buffer_putmem(&xfr->buf, name->ndata, name->length); 1464 dns_name_fromregion(msgname, &r); 1465 1466 /* Reserve space for RR header. */ 1467 isc_buffer_add(&xfr->buf, 10); 1468 1469 result = dns_message_gettemprdata(msg, &msgrdata); 1470 if (result != ISC_R_SUCCESS) 1471 goto failure; 1472 isc_buffer_availableregion(&xfr->buf, &r); 1473 r.length = rdata->length; 1474 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length); 1475 dns_rdata_init(msgrdata); 1476 dns_rdata_fromregion(msgrdata, 1477 rdata->rdclass, rdata->type, &r); 1478 1479 result = dns_message_gettemprdatalist(msg, &msgrdl); 1480 if (result != ISC_R_SUCCESS) 1481 goto failure; 1482 msgrdl->type = rdata->type; 1483 msgrdl->rdclass = rdata->rdclass; 1484 msgrdl->ttl = ttl; 1485 ISC_LINK_INIT(msgrdl, link); 1486 ISC_LIST_INIT(msgrdl->rdata); 1487 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link); 1488 1489 result = dns_message_gettemprdataset(msg, &msgrds); 1490 if (result != ISC_R_SUCCESS) 1491 goto failure; 1492 dns_rdataset_init(msgrds); 1493 result = dns_rdatalist_tordataset(msgrdl, msgrds); 1494 INSIST(result == ISC_R_SUCCESS); 1495 1496 ISC_LIST_APPEND(msgname->list, msgrds, link); 1497 1498 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER); 1499 msgname = NULL; 1500 1501 result = xfr->stream->methods->next(xfr->stream); 1502 if (result == ISC_R_NOMORE) { 1503 xfr->end_of_stream = ISC_TRUE; 1504 break; 1505 } 1506 CHECK(result); 1507 1508 if (! xfr->many_answers) 1509 break; 1510 } 1511 1512 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) { 1513 CHECK(dns_compress_init(&cctx, -1, xfr->mctx)); 1514 cleanup_cctx = ISC_TRUE; 1515 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf)); 1516 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); 1517 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); 1518 CHECK(dns_message_renderend(msg)); 1519 dns_compress_invalidate(&cctx); 1520 cleanup_cctx = ISC_FALSE; 1521 1522 isc_buffer_usedregion(&xfr->txbuf, &used); 1523 isc_buffer_putuint16(&xfr->txlenbuf, 1524 (isc_uint16_t)used.length); 1525 region.base = xfr->txlenbuf.base; 1526 region.length = 2 + used.length; 1527 xfrout_log(xfr, ISC_LOG_DEBUG(8), 1528 "sending TCP message of %d bytes", 1529 used.length); 1530 CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */ 1531 ®ion, xfr->client->task, 1532 xfrout_senddone, 1533 xfr)); 1534 xfr->sends++; 1535 } else { 1536 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response"); 1537 ns_client_send(xfr->client); 1538 xfr->stream->methods->pause(xfr->stream); 1539 xfrout_ctx_destroy(&xfr); 1540 return; 1541 } 1542 1543 /* Advance lasttsig to be the last TSIG generated */ 1544 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); 1545 1546 xfr->nmsg++; 1547 1548 failure: 1549 if (msgname != NULL) { 1550 if (msgrds != NULL) { 1551 if (dns_rdataset_isassociated(msgrds)) 1552 dns_rdataset_disassociate(msgrds); 1553 dns_message_puttemprdataset(msg, &msgrds); 1554 } 1555 if (msgrdl != NULL) { 1556 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link); 1557 dns_message_puttemprdatalist(msg, &msgrdl); 1558 } 1559 if (msgrdata != NULL) 1560 dns_message_puttemprdata(msg, &msgrdata); 1561 dns_message_puttempname(msg, &msgname); 1562 } 1563 1564 if (tcpmsg != NULL) 1565 dns_message_destroy(&tcpmsg); 1566 1567 if (cleanup_cctx) 1568 dns_compress_invalidate(&cctx); 1569 /* 1570 * Make sure to release any locks held by database 1571 * iterators before returning from the event handler. 1572 */ 1573 xfr->stream->methods->pause(xfr->stream); 1574 1575 if (result == ISC_R_SUCCESS) 1576 return; 1577 1578 xfrout_fail(xfr, result, "sending zone data"); 1579} 1580 1581static void 1582xfrout_ctx_destroy(xfrout_ctx_t **xfrp) { 1583 xfrout_ctx_t *xfr = *xfrp; 1584 1585 INSIST(xfr->sends == 0); 1586 1587 xfr->client->shutdown = NULL; 1588 xfr->client->shutdown_arg = NULL; 1589 1590 if (xfr->stream != NULL) 1591 xfr->stream->methods->destroy(&xfr->stream); 1592 if (xfr->buf.base != NULL) 1593 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length); 1594 if (xfr->txmem != NULL) 1595 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen); 1596 if (xfr->lasttsig != NULL) 1597 isc_buffer_free(&xfr->lasttsig); 1598 if (xfr->quota != NULL) 1599 isc_quota_detach(&xfr->quota); 1600 if (xfr->ver != NULL) 1601 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE); 1602 if (xfr->db != NULL) 1603 dns_db_detach(&xfr->db); 1604 1605 ns_client_detach(&xfr->client); 1606 1607 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr)); 1608 1609 *xfrp = NULL; 1610} 1611 1612static void 1613xfrout_senddone(isc_task_t *task, isc_event_t *event) { 1614 isc_socketevent_t *sev = (isc_socketevent_t *)event; 1615 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg; 1616 isc_result_t evresult = sev->result; 1617 1618 UNUSED(task); 1619 1620 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE); 1621 1622 isc_event_free(&event); 1623 xfr->sends--; 1624 INSIST(xfr->sends == 0); 1625 1626 (void)isc_timer_touch(xfr->client->timer); 1627 if (xfr->shuttingdown == ISC_TRUE) { 1628 xfrout_maybe_destroy(xfr); 1629 } else if (evresult != ISC_R_SUCCESS) { 1630 xfrout_fail(xfr, evresult, "send"); 1631 } else if (xfr->end_of_stream == ISC_FALSE) { 1632 sendstream(xfr); 1633 } else { 1634 /* End of zone transfer stream. */ 1635 xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic); 1636 ns_client_next(xfr->client, ISC_R_SUCCESS); 1637 xfrout_ctx_destroy(&xfr); 1638 } 1639} 1640 1641static void 1642xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) { 1643 xfr->shuttingdown = ISC_TRUE; 1644 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s", 1645 msg, isc_result_totext(result)); 1646 xfrout_maybe_destroy(xfr); 1647} 1648 1649static void 1650xfrout_maybe_destroy(xfrout_ctx_t *xfr) { 1651 INSIST(xfr->shuttingdown == ISC_TRUE); 1652 if (xfr->sends > 0) { 1653 /* 1654 * If we are currently sending, cancel it and wait for 1655 * cancel event before destroying the context. 1656 */ 1657 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task, 1658 ISC_SOCKCANCEL_SEND); 1659 } else { 1660 ns_client_next(xfr->client, ISC_R_CANCELED); 1661 xfrout_ctx_destroy(&xfr); 1662 } 1663} 1664 1665static void 1666xfrout_client_shutdown(void *arg, isc_result_t result) { 1667 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg; 1668 xfrout_fail(xfr, result, "aborted"); 1669} 1670 1671/* 1672 * Log outgoing zone transfer messages in a format like 1673 * <client>: transfer of <zone>: <message> 1674 */ 1675 1676static void 1677xfrout_logv(ns_client_t *client, dns_name_t *zonename, 1678 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap) 1679 ISC_FORMAT_PRINTF(5, 0); 1680 1681static void 1682xfrout_logv(ns_client_t *client, dns_name_t *zonename, 1683 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap) 1684{ 1685 char msgbuf[2048]; 1686 char namebuf[DNS_NAME_FORMATSIZE]; 1687 char classbuf[DNS_RDATACLASS_FORMATSIZE]; 1688 1689 dns_name_format(zonename, namebuf, sizeof(namebuf)); 1690 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); 1691 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); 1692 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, 1693 NS_LOGMODULE_XFER_OUT, level, 1694 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf); 1695} 1696 1697/* 1698 * Logging function for use when a xfrout_ctx_t has not yet been created. 1699 */ 1700static void 1701xfrout_log1(ns_client_t *client, dns_name_t *zonename, 1702 dns_rdataclass_t rdclass, int level, const char *fmt, ...) { 1703 va_list ap; 1704 va_start(ap, fmt); 1705 xfrout_logv(client, zonename, rdclass, level, fmt, ap); 1706 va_end(ap); 1707} 1708 1709/* 1710 * Logging function for use when there is a xfrout_ctx_t. 1711 */ 1712static void 1713xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) { 1714 va_list ap; 1715 va_start(ap, fmt); 1716 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap); 1717 va_end(ap); 1718} 1719