1/* $NetBSD: xfrin.c,v 1.1 2024/02/18 20:57:34 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16/*! \file */ 17 18#include <inttypes.h> 19#include <stdbool.h> 20 21#include <isc/mem.h> 22#include <isc/print.h> 23#include <isc/random.h> 24#include <isc/string.h> /* Required for HP/UX (and others?) */ 25#include <isc/task.h> 26#include <isc/timer.h> 27#include <isc/util.h> 28 29#include <dns/callbacks.h> 30#include <dns/catz.h> 31#include <dns/db.h> 32#include <dns/diff.h> 33#include <dns/events.h> 34#include <dns/journal.h> 35#include <dns/log.h> 36#include <dns/message.h> 37#include <dns/rdataclass.h> 38#include <dns/rdatalist.h> 39#include <dns/rdataset.h> 40#include <dns/result.h> 41#include <dns/soa.h> 42#include <dns/tcpmsg.h> 43#include <dns/timer.h> 44#include <dns/tsig.h> 45#include <dns/view.h> 46#include <dns/xfrin.h> 47#include <dns/zone.h> 48 49#include <dst/dst.h> 50 51/* 52 * Incoming AXFR and IXFR. 53 */ 54 55/*% 56 * It would be non-sensical (or at least obtuse) to use FAIL() with an 57 * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler 58 * from complaining about "end-of-loop code not reached". 59 */ 60#define FAIL(code) \ 61 do { \ 62 result = (code); \ 63 if (result != ISC_R_SUCCESS) \ 64 goto failure; \ 65 } while (0) 66 67#define CHECK(op) \ 68 do { \ 69 result = (op); \ 70 if (result != ISC_R_SUCCESS) \ 71 goto failure; \ 72 } while (0) 73 74/*% 75 * The states of the *XFR state machine. We handle both IXFR and AXFR 76 * with a single integrated state machine because they cannot be distinguished 77 * immediately - an AXFR response to an IXFR request can only be detected 78 * when the first two (2) response RRs have already been received. 79 */ 80typedef enum { 81 XFRST_SOAQUERY, 82 XFRST_GOTSOA, 83 XFRST_INITIALSOA, 84 XFRST_FIRSTDATA, 85 XFRST_IXFR_DELSOA, 86 XFRST_IXFR_DEL, 87 XFRST_IXFR_ADDSOA, 88 XFRST_IXFR_ADD, 89 XFRST_IXFR_END, 90 XFRST_AXFR, 91 XFRST_AXFR_END 92} xfrin_state_t; 93 94/*% 95 * Incoming zone transfer context. 96 */ 97 98struct dns_xfrin_ctx { 99 unsigned int magic; 100 isc_mem_t *mctx; 101 dns_zone_t *zone; 102 103 int refcount; 104 105 isc_task_t *task; 106 isc_timer_t *timer; 107 isc_socketmgr_t *socketmgr; 108 109 int connects; /*%< Connect in progress */ 110 int sends; /*%< Send in progress */ 111 int recvs; /*%< Receive in progress */ 112 bool shuttingdown; 113 isc_result_t shutdown_result; 114 115 dns_name_t name; /*%< Name of zone to transfer */ 116 dns_rdataclass_t rdclass; 117 118 bool checkid, logit; 119 dns_messageid_t id; 120 121 /*% 122 * Requested transfer type (dns_rdatatype_axfr or 123 * dns_rdatatype_ixfr). The actual transfer type 124 * may differ due to IXFR->AXFR fallback. 125 */ 126 dns_rdatatype_t reqtype; 127 isc_dscp_t dscp; 128 129 isc_sockaddr_t masteraddr; 130 isc_sockaddr_t sourceaddr; 131 isc_socket_t *socket; 132 133 /*% Buffer for IXFR/AXFR request message */ 134 isc_buffer_t qbuffer; 135 unsigned char qbuffer_data[512]; 136 137 /*% Incoming reply TCP message */ 138 dns_tcpmsg_t tcpmsg; 139 bool tcpmsg_valid; 140 141 /*% 142 * Whether the zone originally had a database attached at the time this 143 * transfer context was created. Used by maybe_free() when making 144 * logging decisions. 145 */ 146 bool zone_had_db; 147 148 dns_db_t *db; 149 dns_dbversion_t *ver; 150 dns_diff_t diff; /*%< Pending database changes */ 151 int difflen; /*%< Number of pending tuples */ 152 153 xfrin_state_t state; 154 uint32_t end_serial; 155 bool is_ixfr; 156 157 unsigned int nmsg; /*%< Number of messages recvd */ 158 unsigned int nrecs; /*%< Number of records recvd */ 159 uint64_t nbytes; /*%< Number of bytes received */ 160 161 unsigned int maxrecords; /*%< The maximum number of 162 * records set for the zone */ 163 164 isc_time_t start; /*%< Start time of the transfer */ 165 isc_time_t end; /*%< End time of the transfer */ 166 167 dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */ 168 isc_buffer_t *lasttsig; /*%< The last TSIG */ 169 dst_context_t *tsigctx; /*%< TSIG verification context */ 170 unsigned int sincetsig; /*%< recvd since the last TSIG */ 171 dns_xfrindone_t done; 172 173 /*% 174 * AXFR- and IXFR-specific data. Only one is used at a time 175 * according to the is_ixfr flag, so this could be a union, 176 * but keeping them separate makes it a bit simpler to clean 177 * things up when destroying the context. 178 */ 179 dns_rdatacallbacks_t axfr; 180 181 struct { 182 uint32_t request_serial; 183 uint32_t current_serial; 184 dns_journal_t *journal; 185 } ixfr; 186 187 dns_rdata_t firstsoa; 188 unsigned char *firstsoa_data; 189}; 190 191#define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I') 192#define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC) 193 194/**************************************************************************/ 195/* 196 * Forward declarations. 197 */ 198 199static isc_result_t 200xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task, 201 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, 202 dns_name_t *zonename, dns_rdataclass_t rdclass, 203 dns_rdatatype_t reqtype, const isc_sockaddr_t *masteraddr, 204 const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp, 205 dns_tsigkey_t *tsigkey, dns_xfrin_ctx_t **xfrp); 206 207static isc_result_t 208axfr_init(dns_xfrin_ctx_t *xfr); 209static isc_result_t 210axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp); 211static isc_result_t 212axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, 213 dns_ttl_t ttl, dns_rdata_t *rdata); 214static isc_result_t 215axfr_apply(dns_xfrin_ctx_t *xfr); 216static isc_result_t 217axfr_commit(dns_xfrin_ctx_t *xfr); 218static isc_result_t 219axfr_finalize(dns_xfrin_ctx_t *xfr); 220 221static isc_result_t 222ixfr_init(dns_xfrin_ctx_t *xfr); 223static isc_result_t 224ixfr_apply(dns_xfrin_ctx_t *xfr); 225static isc_result_t 226ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, 227 dns_ttl_t ttl, dns_rdata_t *rdata); 228static isc_result_t 229ixfr_commit(dns_xfrin_ctx_t *xfr); 230 231static isc_result_t 232xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl, 233 dns_rdata_t *rdata); 234 235static isc_result_t 236xfrin_start(dns_xfrin_ctx_t *xfr); 237 238static void 239xfrin_connect_done(isc_task_t *task, isc_event_t *event); 240static isc_result_t 241xfrin_send_request(dns_xfrin_ctx_t *xfr); 242static void 243xfrin_send_done(isc_task_t *task, isc_event_t *event); 244static void 245xfrin_recv_done(isc_task_t *task, isc_event_t *event); 246static void 247xfrin_timeout(isc_task_t *task, isc_event_t *event); 248 249static void 250maybe_free(dns_xfrin_ctx_t *xfr); 251 252static void 253xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg); 254static isc_result_t 255render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf); 256 257static void 258xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *masteraddr, 259 const char *fmt, va_list ap) ISC_FORMAT_PRINTF(4, 0); 260 261static void 262xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *masteraddr, 263 const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5); 264 265static void 266xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) 267 ISC_FORMAT_PRINTF(3, 4); 268 269/**************************************************************************/ 270/* 271 * AXFR handling 272 */ 273 274static isc_result_t 275axfr_init(dns_xfrin_ctx_t *xfr) { 276 isc_result_t result; 277 278 xfr->is_ixfr = false; 279 280 if (xfr->db != NULL) { 281 dns_db_detach(&xfr->db); 282 } 283 284 CHECK(axfr_makedb(xfr, &xfr->db)); 285 dns_rdatacallbacks_init(&xfr->axfr); 286 CHECK(dns_db_beginload(xfr->db, &xfr->axfr)); 287 result = ISC_R_SUCCESS; 288failure: 289 return (result); 290} 291 292static isc_result_t 293axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) { 294 isc_result_t result; 295 296 result = dns_db_create(xfr->mctx, /* XXX */ 297 "rbt", /* XXX guess */ 298 &xfr->name, dns_dbtype_zone, xfr->rdclass, 0, 299 NULL, /* XXX guess */ 300 dbp); 301 if (result == ISC_R_SUCCESS) { 302 dns_zone_rpz_enable_db(xfr->zone, *dbp); 303 dns_zone_catz_enable_db(xfr->zone, *dbp); 304 } 305 return (result); 306} 307 308static isc_result_t 309axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, 310 dns_ttl_t ttl, dns_rdata_t *rdata) { 311 isc_result_t result; 312 313 dns_difftuple_t *tuple = NULL; 314 315 if (rdata->rdclass != xfr->rdclass) { 316 return (DNS_R_BADCLASS); 317 } 318 319 CHECK(dns_zone_checknames(xfr->zone, name, rdata)); 320 CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata, 321 &tuple)); 322 dns_diff_append(&xfr->diff, &tuple); 323 if (++xfr->difflen > 100) { 324 CHECK(axfr_apply(xfr)); 325 } 326 result = ISC_R_SUCCESS; 327failure: 328 return (result); 329} 330 331/* 332 * Store a set of AXFR RRs in the database. 333 */ 334static isc_result_t 335axfr_apply(dns_xfrin_ctx_t *xfr) { 336 isc_result_t result; 337 uint64_t records; 338 339 CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private)); 340 xfr->difflen = 0; 341 dns_diff_clear(&xfr->diff); 342 if (xfr->maxrecords != 0U) { 343 result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); 344 if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { 345 result = DNS_R_TOOMANYRECORDS; 346 goto failure; 347 } 348 } 349 result = ISC_R_SUCCESS; 350failure: 351 return (result); 352} 353 354static isc_result_t 355axfr_commit(dns_xfrin_ctx_t *xfr) { 356 isc_result_t result; 357 358 CHECK(axfr_apply(xfr)); 359 CHECK(dns_db_endload(xfr->db, &xfr->axfr)); 360 CHECK(dns_zone_verifydb(xfr->zone, xfr->db, NULL)); 361 362 result = ISC_R_SUCCESS; 363failure: 364 return (result); 365} 366 367static isc_result_t 368axfr_finalize(dns_xfrin_ctx_t *xfr) { 369 isc_result_t result; 370 371 CHECK(dns_zone_replacedb(xfr->zone, xfr->db, true)); 372 373 result = ISC_R_SUCCESS; 374failure: 375 return (result); 376} 377 378/**************************************************************************/ 379/* 380 * IXFR handling 381 */ 382 383static isc_result_t 384ixfr_init(dns_xfrin_ctx_t *xfr) { 385 isc_result_t result; 386 char *journalfile; 387 388 if (xfr->reqtype != dns_rdatatype_ixfr) { 389 xfrin_log(xfr, ISC_LOG_ERROR, 390 "got incremental response to AXFR request"); 391 return (DNS_R_FORMERR); 392 } 393 394 xfr->is_ixfr = true; 395 INSIST(xfr->db != NULL); 396 xfr->difflen = 0; 397 398 journalfile = dns_zone_getjournal(xfr->zone); 399 if (journalfile != NULL) { 400 CHECK(dns_journal_open(xfr->mctx, journalfile, 401 DNS_JOURNAL_CREATE, &xfr->ixfr.journal)); 402 } 403 404 result = ISC_R_SUCCESS; 405failure: 406 return (result); 407} 408 409static isc_result_t 410ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name, 411 dns_ttl_t ttl, dns_rdata_t *rdata) { 412 isc_result_t result; 413 dns_difftuple_t *tuple = NULL; 414 415 if (rdata->rdclass != xfr->rdclass) { 416 return (DNS_R_BADCLASS); 417 } 418 419 if (op == DNS_DIFFOP_ADD) { 420 CHECK(dns_zone_checknames(xfr->zone, name, rdata)); 421 } 422 CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata, 423 &tuple)); 424 dns_diff_append(&xfr->diff, &tuple); 425 if (++xfr->difflen > 100) { 426 CHECK(ixfr_apply(xfr)); 427 } 428 result = ISC_R_SUCCESS; 429failure: 430 return (result); 431} 432 433/* 434 * Apply a set of IXFR changes to the database. 435 */ 436static isc_result_t 437ixfr_apply(dns_xfrin_ctx_t *xfr) { 438 isc_result_t result; 439 uint64_t records; 440 441 if (xfr->ver == NULL) { 442 CHECK(dns_db_newversion(xfr->db, &xfr->ver)); 443 if (xfr->ixfr.journal != NULL) { 444 CHECK(dns_journal_begin_transaction(xfr->ixfr.journal)); 445 } 446 } 447 CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver)); 448 if (xfr->maxrecords != 0U) { 449 result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); 450 if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { 451 result = DNS_R_TOOMANYRECORDS; 452 goto failure; 453 } 454 } 455 if (xfr->ixfr.journal != NULL) { 456 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff); 457 if (result != ISC_R_SUCCESS) { 458 goto failure; 459 } 460 } 461 dns_diff_clear(&xfr->diff); 462 xfr->difflen = 0; 463 result = ISC_R_SUCCESS; 464failure: 465 return (result); 466} 467 468static isc_result_t 469ixfr_commit(dns_xfrin_ctx_t *xfr) { 470 isc_result_t result; 471 472 CHECK(ixfr_apply(xfr)); 473 if (xfr->ver != NULL) { 474 CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver)); 475 /* XXX enter ready-to-commit state here */ 476 if (xfr->ixfr.journal != NULL) { 477 CHECK(dns_journal_commit(xfr->ixfr.journal)); 478 } 479 dns_db_closeversion(xfr->db, &xfr->ver, true); 480 dns_zone_markdirty(xfr->zone); 481 } 482 result = ISC_R_SUCCESS; 483failure: 484 return (result); 485} 486 487/**************************************************************************/ 488/* 489 * Common AXFR/IXFR protocol code 490 */ 491 492/* 493 * Handle a single incoming resource record according to the current 494 * state. 495 */ 496static isc_result_t 497xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl, 498 dns_rdata_t *rdata) { 499 isc_result_t result; 500 501 xfr->nrecs++; 502 503 if (rdata->type == dns_rdatatype_none || 504 dns_rdatatype_ismeta(rdata->type)) 505 { 506 FAIL(DNS_R_FORMERR); 507 } 508 509 /* 510 * Immediately reject the entire transfer if the RR that is currently 511 * being processed is an SOA record that is not placed at the zone 512 * apex. 513 */ 514 if (rdata->type == dns_rdatatype_soa && 515 !dns_name_equal(&xfr->name, name)) 516 { 517 char namebuf[DNS_NAME_FORMATSIZE]; 518 dns_name_format(name, namebuf, sizeof(namebuf)); 519 xfrin_log(xfr, ISC_LOG_DEBUG(3), "SOA name mismatch: '%s'", 520 namebuf); 521 FAIL(DNS_R_NOTZONETOP); 522 } 523 524redo: 525 switch (xfr->state) { 526 case XFRST_SOAQUERY: 527 if (rdata->type != dns_rdatatype_soa) { 528 xfrin_log(xfr, ISC_LOG_ERROR, 529 "non-SOA response to SOA query"); 530 FAIL(DNS_R_FORMERR); 531 } 532 xfr->end_serial = dns_soa_getserial(rdata); 533 if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) && 534 !dns_zone_isforced(xfr->zone)) 535 { 536 xfrin_log(xfr, ISC_LOG_DEBUG(3), 537 "requested serial %u, " 538 "master has %u, not updating", 539 xfr->ixfr.request_serial, xfr->end_serial); 540 FAIL(DNS_R_UPTODATE); 541 } 542 xfr->state = XFRST_GOTSOA; 543 break; 544 545 case XFRST_GOTSOA: 546 /* 547 * Skip other records in the answer section. 548 */ 549 break; 550 551 case XFRST_INITIALSOA: 552 if (rdata->type != dns_rdatatype_soa) { 553 xfrin_log(xfr, ISC_LOG_ERROR, 554 "first RR in zone transfer must be SOA"); 555 FAIL(DNS_R_FORMERR); 556 } 557 /* 558 * Remember the serial number in the initial SOA. 559 * We need it to recognize the end of an IXFR. 560 */ 561 xfr->end_serial = dns_soa_getserial(rdata); 562 if (xfr->reqtype == dns_rdatatype_ixfr && 563 !DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) && 564 !dns_zone_isforced(xfr->zone)) 565 { 566 /* 567 * This must be the single SOA record that is 568 * sent when the current version on the master 569 * is not newer than the version in the request. 570 */ 571 xfrin_log(xfr, ISC_LOG_DEBUG(3), 572 "requested serial %u, " 573 "master has %u, not updating", 574 xfr->ixfr.request_serial, xfr->end_serial); 575 FAIL(DNS_R_UPTODATE); 576 } 577 if (xfr->reqtype == dns_rdatatype_axfr) { 578 xfr->checkid = false; 579 } 580 xfr->firstsoa = *rdata; 581 if (xfr->firstsoa_data != NULL) { 582 isc_mem_free(xfr->mctx, xfr->firstsoa_data); 583 } 584 xfr->firstsoa_data = isc_mem_allocate(xfr->mctx, rdata->length); 585 memcpy(xfr->firstsoa_data, rdata->data, rdata->length); 586 xfr->firstsoa.data = xfr->firstsoa_data; 587 xfr->state = XFRST_FIRSTDATA; 588 break; 589 590 case XFRST_FIRSTDATA: 591 /* 592 * If the transfer begins with one SOA record, it is an AXFR, 593 * if it begins with two SOAs, it is an IXFR. 594 */ 595 if (xfr->reqtype == dns_rdatatype_ixfr && 596 rdata->type == dns_rdatatype_soa && 597 xfr->ixfr.request_serial == dns_soa_getserial(rdata)) 598 { 599 xfrin_log(xfr, ISC_LOG_DEBUG(3), 600 "got incremental response"); 601 CHECK(ixfr_init(xfr)); 602 xfr->state = XFRST_IXFR_DELSOA; 603 } else { 604 xfrin_log(xfr, ISC_LOG_DEBUG(3), 605 "got nonincremental response"); 606 CHECK(axfr_init(xfr)); 607 xfr->state = XFRST_AXFR; 608 } 609 goto redo; 610 611 case XFRST_IXFR_DELSOA: 612 INSIST(rdata->type == dns_rdatatype_soa); 613 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); 614 xfr->state = XFRST_IXFR_DEL; 615 break; 616 617 case XFRST_IXFR_DEL: 618 if (rdata->type == dns_rdatatype_soa) { 619 uint32_t soa_serial = dns_soa_getserial(rdata); 620 xfr->state = XFRST_IXFR_ADDSOA; 621 xfr->ixfr.current_serial = soa_serial; 622 goto redo; 623 } 624 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); 625 break; 626 627 case XFRST_IXFR_ADDSOA: 628 INSIST(rdata->type == dns_rdatatype_soa); 629 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 630 xfr->state = XFRST_IXFR_ADD; 631 break; 632 633 case XFRST_IXFR_ADD: 634 if (rdata->type == dns_rdatatype_soa) { 635 uint32_t soa_serial = dns_soa_getserial(rdata); 636 if (soa_serial == xfr->end_serial) { 637 CHECK(ixfr_commit(xfr)); 638 xfr->state = XFRST_IXFR_END; 639 break; 640 } else if (soa_serial != xfr->ixfr.current_serial) { 641 xfrin_log(xfr, ISC_LOG_ERROR, 642 "IXFR out of sync: " 643 "expected serial %u, got %u", 644 xfr->ixfr.current_serial, soa_serial); 645 FAIL(DNS_R_FORMERR); 646 } else { 647 CHECK(ixfr_commit(xfr)); 648 xfr->state = XFRST_IXFR_DELSOA; 649 goto redo; 650 } 651 } 652 if (rdata->type == dns_rdatatype_ns && 653 dns_name_iswildcard(name)) 654 { 655 FAIL(DNS_R_INVALIDNS); 656 } 657 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 658 break; 659 660 case XFRST_AXFR: 661 /* 662 * Old BINDs sent cross class A records for non IN classes. 663 */ 664 if (rdata->type == dns_rdatatype_a && 665 rdata->rdclass != xfr->rdclass && 666 xfr->rdclass != dns_rdataclass_in) 667 { 668 break; 669 } 670 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 671 if (rdata->type == dns_rdatatype_soa) { 672 /* 673 * Use dns_rdata_compare instead of memcmp to 674 * allow for case differences. 675 */ 676 if (dns_rdata_compare(rdata, &xfr->firstsoa) != 0) { 677 xfrin_log(xfr, ISC_LOG_ERROR, 678 "start and ending SOA records " 679 "mismatch"); 680 FAIL(DNS_R_FORMERR); 681 } 682 CHECK(axfr_commit(xfr)); 683 xfr->state = XFRST_AXFR_END; 684 break; 685 } 686 break; 687 case XFRST_AXFR_END: 688 case XFRST_IXFR_END: 689 FAIL(DNS_R_EXTRADATA); 690 FALLTHROUGH; 691 default: 692 UNREACHABLE(); 693 } 694 result = ISC_R_SUCCESS; 695failure: 696 return (result); 697} 698 699isc_result_t 700dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype, 701 const isc_sockaddr_t *masteraddr, 702 const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp, 703 dns_tsigkey_t *tsigkey, isc_mem_t *mctx, 704 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, 705 isc_task_t *task, dns_xfrindone_t done, 706 dns_xfrin_ctx_t **xfrp) { 707 dns_name_t *zonename = dns_zone_getorigin(zone); 708 dns_xfrin_ctx_t *xfr = NULL; 709 isc_result_t result; 710 dns_db_t *db = NULL; 711 712 REQUIRE(xfrp != NULL && *xfrp == NULL); 713 714 (void)dns_zone_getdb(zone, &db); 715 716 if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr) { 717 REQUIRE(db != NULL); 718 } 719 720 CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename, 721 dns_zone_getclass(zone), xfrtype, masteraddr, 722 sourceaddr, dscp, tsigkey, &xfr)); 723 724 if (db != NULL) { 725 xfr->zone_had_db = true; 726 } 727 728 CHECK(xfrin_start(xfr)); 729 730 xfr->done = done; 731 if (xfr->done != NULL) { 732 xfr->refcount++; 733 } 734 *xfrp = xfr; 735 736failure: 737 if (db != NULL) { 738 dns_db_detach(&db); 739 } 740 if (result != ISC_R_SUCCESS) { 741 char zonetext[DNS_NAME_MAXTEXT + 32]; 742 dns_zone_name(zone, zonetext, sizeof(zonetext)); 743 xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr, 744 "zone transfer setup failed"); 745 } 746 return (result); 747} 748 749void 750dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) { 751 if (!xfr->shuttingdown) { 752 xfrin_fail(xfr, ISC_R_CANCELED, "shut down"); 753 } 754} 755 756void 757dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) { 758 REQUIRE(target != NULL && *target == NULL); 759 source->refcount++; 760 *target = source; 761} 762 763void 764dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) { 765 dns_xfrin_ctx_t *xfr = *xfrp; 766 *xfrp = NULL; 767 INSIST(xfr->refcount > 0); 768 xfr->refcount--; 769 maybe_free(xfr); 770} 771 772static void 773xfrin_cancelio(dns_xfrin_ctx_t *xfr) { 774 if (xfr->connects > 0) { 775 isc_socket_cancel(xfr->socket, xfr->task, 776 ISC_SOCKCANCEL_CONNECT); 777 } else if (xfr->recvs > 0) { 778 dns_tcpmsg_cancelread(&xfr->tcpmsg); 779 } else if (xfr->sends > 0) { 780 isc_socket_cancel(xfr->socket, xfr->task, ISC_SOCKCANCEL_SEND); 781 } 782} 783 784static void 785xfrin_reset(dns_xfrin_ctx_t *xfr) { 786 REQUIRE(VALID_XFRIN(xfr)); 787 788 xfrin_log(xfr, ISC_LOG_INFO, "resetting"); 789 790 xfrin_cancelio(xfr); 791 792 if (xfr->socket != NULL) { 793 isc_socket_detach(&xfr->socket); 794 } 795 796 if (xfr->lasttsig != NULL) { 797 isc_buffer_free(&xfr->lasttsig); 798 } 799 800 dns_diff_clear(&xfr->diff); 801 xfr->difflen = 0; 802 803 if (xfr->ixfr.journal != NULL) { 804 dns_journal_destroy(&xfr->ixfr.journal); 805 } 806 807 if (xfr->axfr.add_private != NULL) { 808 (void)dns_db_endload(xfr->db, &xfr->axfr); 809 } 810 811 if (xfr->tcpmsg_valid) { 812 dns_tcpmsg_invalidate(&xfr->tcpmsg); 813 xfr->tcpmsg_valid = false; 814 } 815 816 if (xfr->ver != NULL) { 817 dns_db_closeversion(xfr->db, &xfr->ver, false); 818 } 819} 820 821static void 822xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) { 823 if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) { 824 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg, 825 isc_result_totext(result)); 826 if (xfr->is_ixfr) { 827 /* Pass special result code to force AXFR retry */ 828 result = DNS_R_BADIXFR; 829 } 830 } 831 xfrin_cancelio(xfr); 832 /* 833 * Close the journal. 834 */ 835 if (xfr->ixfr.journal != NULL) { 836 dns_journal_destroy(&xfr->ixfr.journal); 837 } 838 if (xfr->done != NULL) { 839 (xfr->done)(xfr->zone, result); 840 xfr->done = NULL; 841 } 842 xfr->shuttingdown = true; 843 xfr->shutdown_result = result; 844 maybe_free(xfr); 845} 846 847static isc_result_t 848xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task, 849 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr, 850 dns_name_t *zonename, dns_rdataclass_t rdclass, 851 dns_rdatatype_t reqtype, const isc_sockaddr_t *masteraddr, 852 const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp, 853 dns_tsigkey_t *tsigkey, dns_xfrin_ctx_t **xfrp) { 854 dns_xfrin_ctx_t *xfr = NULL; 855 isc_result_t result; 856 857 xfr = isc_mem_get(mctx, sizeof(*xfr)); 858 xfr->mctx = NULL; 859 isc_mem_attach(mctx, &xfr->mctx); 860 xfr->refcount = 0; 861 xfr->zone = NULL; 862 dns_zone_iattach(zone, &xfr->zone); 863 xfr->task = NULL; 864 isc_task_attach(task, &xfr->task); 865 xfr->timer = NULL; 866 xfr->socketmgr = socketmgr; 867 xfr->done = NULL; 868 869 xfr->connects = 0; 870 xfr->sends = 0; 871 xfr->recvs = 0; 872 xfr->shuttingdown = false; 873 xfr->shutdown_result = ISC_R_UNSET; 874 875 dns_name_init(&xfr->name, NULL); 876 xfr->rdclass = rdclass; 877 xfr->checkid = true; 878 xfr->logit = true; 879 xfr->id = (dns_messageid_t)isc_random16(); 880 xfr->reqtype = reqtype; 881 xfr->dscp = dscp; 882 883 /* sockaddr */ 884 xfr->socket = NULL; 885 /* qbuffer */ 886 /* qbuffer_data */ 887 /* tcpmsg */ 888 xfr->tcpmsg_valid = false; 889 890 xfr->zone_had_db = false; 891 xfr->db = NULL; 892 if (db != NULL) { 893 dns_db_attach(db, &xfr->db); 894 } 895 xfr->ver = NULL; 896 dns_diff_init(xfr->mctx, &xfr->diff); 897 xfr->difflen = 0; 898 899 if (reqtype == dns_rdatatype_soa) { 900 xfr->state = XFRST_SOAQUERY; 901 } else { 902 xfr->state = XFRST_INITIALSOA; 903 } 904 /* end_serial */ 905 906 xfr->nmsg = 0; 907 xfr->nrecs = 0; 908 xfr->nbytes = 0; 909 xfr->maxrecords = dns_zone_getmaxrecords(zone); 910 isc_time_now(&xfr->start); 911 912 xfr->tsigkey = NULL; 913 if (tsigkey != NULL) { 914 dns_tsigkey_attach(tsigkey, &xfr->tsigkey); 915 } 916 xfr->lasttsig = NULL; 917 xfr->tsigctx = NULL; 918 xfr->sincetsig = 0; 919 xfr->is_ixfr = false; 920 921 /* ixfr.request_serial */ 922 /* ixfr.current_serial */ 923 xfr->ixfr.journal = NULL; 924 925 xfr->axfr.add = NULL; 926 xfr->axfr.add_private = NULL; 927 dns_rdata_init(&xfr->firstsoa); 928 xfr->firstsoa_data = NULL; 929 930 dns_name_dup(zonename, mctx, &xfr->name); 931 932 CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL, 933 task, xfrin_timeout, xfr, &xfr->timer)); 934 CHECK(dns_timer_setidle(xfr->timer, dns_zone_getmaxxfrin(xfr->zone), 935 dns_zone_getidlein(xfr->zone), false)); 936 937 xfr->masteraddr = *masteraddr; 938 939 INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr)); 940 xfr->sourceaddr = *sourceaddr; 941 isc_sockaddr_setport(&xfr->sourceaddr, 0); 942 943 /* 944 * Reserve 2 bytes for TCP length at the beginning of the buffer. 945 */ 946 isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2], 947 sizeof(xfr->qbuffer_data) - 2); 948 949 xfr->magic = XFRIN_MAGIC; 950 *xfrp = xfr; 951 return (ISC_R_SUCCESS); 952 953failure: 954 if (xfr->timer != NULL) { 955 isc_timer_destroy(&xfr->timer); 956 } 957 if (dns_name_dynamic(&xfr->name)) { 958 dns_name_free(&xfr->name, xfr->mctx); 959 } 960 if (xfr->tsigkey != NULL) { 961 dns_tsigkey_detach(&xfr->tsigkey); 962 } 963 if (xfr->db != NULL) { 964 dns_db_detach(&xfr->db); 965 } 966 isc_task_detach(&xfr->task); 967 dns_zone_idetach(&xfr->zone); 968 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr)); 969 970 return (result); 971} 972 973static isc_result_t 974xfrin_start(dns_xfrin_ctx_t *xfr) { 975 isc_result_t result; 976 CHECK(isc_socket_create(xfr->socketmgr, 977 isc_sockaddr_pf(&xfr->sourceaddr), 978 isc_sockettype_tcp, &xfr->socket)); 979 isc_socket_setname(xfr->socket, "xfrin", NULL); 980#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT 981 CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr, 982 ISC_SOCKET_REUSEADDRESS)); 983#endif /* ifndef BROKEN_TCP_BIND_BEFORE_CONNECT */ 984 isc_socket_dscp(xfr->socket, xfr->dscp); 985 CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task, 986 xfrin_connect_done, xfr)); 987 xfr->connects++; 988 return (ISC_R_SUCCESS); 989failure: 990 xfrin_fail(xfr, result, "failed setting up socket"); 991 return (result); 992} 993 994/* XXX the resolver could use this, too */ 995 996static isc_result_t 997render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) { 998 dns_compress_t cctx; 999 bool cleanup_cctx = false; 1000 isc_result_t result; 1001 1002 CHECK(dns_compress_init(&cctx, -1, mctx)); 1003 cleanup_cctx = true; 1004 CHECK(dns_message_renderbegin(msg, &cctx, buf)); 1005 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); 1006 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); 1007 CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0)); 1008 CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0)); 1009 CHECK(dns_message_renderend(msg)); 1010 result = ISC_R_SUCCESS; 1011failure: 1012 if (cleanup_cctx) { 1013 dns_compress_invalidate(&cctx); 1014 } 1015 return (result); 1016} 1017 1018/* 1019 * A connection has been established. 1020 */ 1021static void 1022xfrin_connect_done(isc_task_t *task, isc_event_t *event) { 1023 isc_socket_connev_t *cev = (isc_socket_connev_t *)event; 1024 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg; 1025 isc_result_t result = cev->result; 1026 char sourcetext[ISC_SOCKADDR_FORMATSIZE]; 1027 char signerbuf[DNS_NAME_FORMATSIZE]; 1028 const char *signer = "", *sep = ""; 1029 isc_sockaddr_t sockaddr; 1030 dns_zonemgr_t *zmgr; 1031 isc_time_t now; 1032 1033 REQUIRE(VALID_XFRIN(xfr)); 1034 1035 UNUSED(task); 1036 1037 INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT); 1038 isc_event_free(&event); 1039 1040 xfr->connects--; 1041 if (xfr->shuttingdown) { 1042 maybe_free(xfr); 1043 return; 1044 } 1045 1046 zmgr = dns_zone_getmgr(xfr->zone); 1047 if (zmgr != NULL) { 1048 if (result != ISC_R_SUCCESS) { 1049 TIME_NOW(&now); 1050 dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr, 1051 &xfr->sourceaddr, &now); 1052 goto failure; 1053 } else { 1054 dns_zonemgr_unreachabledel(zmgr, &xfr->masteraddr, 1055 &xfr->sourceaddr); 1056 } 1057 } 1058 1059 result = isc_socket_getsockname(xfr->socket, &sockaddr); 1060 if (result == ISC_R_SUCCESS) { 1061 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext)); 1062 } else { 1063 strlcpy(sourcetext, "<UNKNOWN>", sizeof(sourcetext)); 1064 } 1065 1066 if (xfr->tsigkey != NULL && xfr->tsigkey->key != NULL) { 1067 dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf, 1068 sizeof(signerbuf)); 1069 sep = " TSIG "; 1070 signer = signerbuf; 1071 } 1072 1073 xfrin_log(xfr, ISC_LOG_INFO, "connected using %s%s%s", sourcetext, sep, 1074 signer); 1075 1076 dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg); 1077 xfr->tcpmsg_valid = true; 1078 1079 CHECK(xfrin_send_request(xfr)); 1080failure: 1081 if (result != ISC_R_SUCCESS) { 1082 xfrin_fail(xfr, result, "failed to connect"); 1083 } 1084} 1085 1086/* 1087 * Convert a tuple into a dns_name_t suitable for inserting 1088 * into the given dns_message_t. 1089 */ 1090static isc_result_t 1091tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target) { 1092 isc_result_t result; 1093 dns_rdata_t *rdata = NULL; 1094 dns_rdatalist_t *rdl = NULL; 1095 dns_rdataset_t *rds = NULL; 1096 dns_name_t *name = NULL; 1097 1098 REQUIRE(target != NULL && *target == NULL); 1099 1100 CHECK(dns_message_gettemprdata(msg, &rdata)); 1101 dns_rdata_init(rdata); 1102 dns_rdata_clone(&tuple->rdata, rdata); 1103 1104 CHECK(dns_message_gettemprdatalist(msg, &rdl)); 1105 dns_rdatalist_init(rdl); 1106 rdl->type = tuple->rdata.type; 1107 rdl->rdclass = tuple->rdata.rdclass; 1108 rdl->ttl = tuple->ttl; 1109 ISC_LIST_APPEND(rdl->rdata, rdata, link); 1110 1111 CHECK(dns_message_gettemprdataset(msg, &rds)); 1112 CHECK(dns_rdatalist_tordataset(rdl, rds)); 1113 1114 CHECK(dns_message_gettempname(msg, &name)); 1115 dns_name_clone(&tuple->name, name); 1116 ISC_LIST_APPEND(name->list, rds, link); 1117 1118 *target = name; 1119 return (ISC_R_SUCCESS); 1120 1121failure: 1122 1123 if (rds != NULL) { 1124 dns_rdataset_disassociate(rds); 1125 dns_message_puttemprdataset(msg, &rds); 1126 } 1127 if (rdl != NULL) { 1128 ISC_LIST_UNLINK(rdl->rdata, rdata, link); 1129 dns_message_puttemprdatalist(msg, &rdl); 1130 } 1131 if (rdata != NULL) { 1132 dns_message_puttemprdata(msg, &rdata); 1133 } 1134 1135 return (result); 1136} 1137 1138/* 1139 * Build an *XFR request and send its length prefix. 1140 */ 1141static isc_result_t 1142xfrin_send_request(dns_xfrin_ctx_t *xfr) { 1143 isc_result_t result; 1144 isc_region_t region; 1145 dns_rdataset_t *qrdataset = NULL; 1146 dns_message_t *msg = NULL; 1147 dns_difftuple_t *soatuple = NULL; 1148 dns_name_t *qname = NULL; 1149 dns_dbversion_t *ver = NULL; 1150 dns_name_t *msgsoaname = NULL; 1151 1152 /* Create the request message */ 1153 dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg); 1154 CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); 1155 1156 /* Create a name for the question section. */ 1157 CHECK(dns_message_gettempname(msg, &qname)); 1158 dns_name_clone(&xfr->name, qname); 1159 1160 /* Formulate the question and attach it to the question name. */ 1161 CHECK(dns_message_gettemprdataset(msg, &qrdataset)); 1162 dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype); 1163 ISC_LIST_APPEND(qname->list, qrdataset, link); 1164 qrdataset = NULL; 1165 1166 dns_message_addname(msg, qname, DNS_SECTION_QUESTION); 1167 qname = NULL; 1168 1169 if (xfr->reqtype == dns_rdatatype_ixfr) { 1170 /* Get the SOA and add it to the authority section. */ 1171 /* XXX is using the current version the right thing? */ 1172 dns_db_currentversion(xfr->db, &ver); 1173 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx, 1174 DNS_DIFFOP_EXISTS, &soatuple)); 1175 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata); 1176 xfr->ixfr.current_serial = xfr->ixfr.request_serial; 1177 xfrin_log(xfr, ISC_LOG_DEBUG(3), 1178 "requesting IXFR for serial %u", 1179 xfr->ixfr.request_serial); 1180 1181 CHECK(tuple2msgname(soatuple, msg, &msgsoaname)); 1182 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY); 1183 } else if (xfr->reqtype == dns_rdatatype_soa) { 1184 CHECK(dns_db_getsoaserial(xfr->db, NULL, 1185 &xfr->ixfr.request_serial)); 1186 } 1187 1188 xfr->checkid = true; 1189 xfr->logit = true; 1190 xfr->id++; 1191 xfr->nmsg = 0; 1192 xfr->nrecs = 0; 1193 xfr->nbytes = 0; 1194 isc_time_now(&xfr->start); 1195 msg->id = xfr->id; 1196 if (xfr->tsigctx != NULL) { 1197 dst_context_destroy(&xfr->tsigctx); 1198 } 1199 1200 CHECK(render(msg, xfr->mctx, &xfr->qbuffer)); 1201 1202 /* 1203 * Free the last tsig, if there is one. 1204 */ 1205 if (xfr->lasttsig != NULL) { 1206 isc_buffer_free(&xfr->lasttsig); 1207 } 1208 1209 /* 1210 * Save the query TSIG and don't let message_destroy free it. 1211 */ 1212 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); 1213 1214 isc_buffer_usedregion(&xfr->qbuffer, ®ion); 1215 INSIST(region.length <= 65535); 1216 1217 /* 1218 * Record message length and adjust region to include TCP 1219 * length field. 1220 */ 1221 xfr->qbuffer_data[0] = (region.length >> 8) & 0xff; 1222 xfr->qbuffer_data[1] = region.length & 0xff; 1223 region.base -= 2; 1224 region.length += 2; 1225 CHECK(isc_socket_send(xfr->socket, ®ion, xfr->task, xfrin_send_done, 1226 xfr)); 1227 xfr->sends++; 1228 1229failure: 1230 if (qname != NULL) { 1231 dns_message_puttempname(msg, &qname); 1232 } 1233 if (qrdataset != NULL) { 1234 dns_message_puttemprdataset(msg, &qrdataset); 1235 } 1236 if (msg != NULL) { 1237 dns_message_detach(&msg); 1238 } 1239 if (soatuple != NULL) { 1240 dns_difftuple_free(&soatuple); 1241 } 1242 if (ver != NULL) { 1243 dns_db_closeversion(xfr->db, &ver, false); 1244 } 1245 return (result); 1246} 1247 1248static void 1249xfrin_send_done(isc_task_t *task, isc_event_t *event) { 1250 isc_socketevent_t *sev = (isc_socketevent_t *)event; 1251 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg; 1252 isc_result_t result; 1253 1254 REQUIRE(VALID_XFRIN(xfr)); 1255 1256 UNUSED(task); 1257 1258 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE); 1259 1260 xfr->sends--; 1261 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data"); 1262 CHECK(sev->result); 1263 1264 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task, xfrin_recv_done, 1265 xfr)); 1266 xfr->recvs++; 1267failure: 1268 isc_event_free(&event); 1269 if (result != ISC_R_SUCCESS) { 1270 xfrin_fail(xfr, result, "failed sending request data"); 1271 } 1272} 1273 1274static void 1275xfrin_recv_done(isc_task_t *task, isc_event_t *ev) { 1276 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)ev->ev_arg; 1277 isc_result_t result; 1278 dns_message_t *msg = NULL; 1279 dns_name_t *name; 1280 dns_tcpmsg_t *tcpmsg; 1281 const dns_name_t *tsigowner = NULL; 1282 1283 REQUIRE(VALID_XFRIN(xfr)); 1284 1285 UNUSED(task); 1286 1287 INSIST(ev->ev_type == DNS_EVENT_TCPMSG); 1288 tcpmsg = ev->ev_sender; 1289 isc_event_free(&ev); 1290 1291 xfr->recvs--; 1292 if (xfr->shuttingdown) { 1293 maybe_free(xfr); 1294 return; 1295 } 1296 1297 CHECK(tcpmsg->result); 1298 1299 xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes", 1300 tcpmsg->buffer.used); 1301 1302 CHECK(isc_timer_touch(xfr->timer)); 1303 1304 dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg); 1305 1306 CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); 1307 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); 1308 1309 msg->tsigctx = xfr->tsigctx; 1310 xfr->tsigctx = NULL; 1311 1312 dns_message_setclass(msg, xfr->rdclass); 1313 1314 if (xfr->nmsg > 0) { 1315 msg->tcp_continuation = 1; 1316 } 1317 1318 result = dns_message_parse(msg, &tcpmsg->buffer, 1319 DNS_MESSAGEPARSE_PRESERVEORDER); 1320 1321 if (result == ISC_R_SUCCESS) { 1322 dns_message_logpacket(msg, "received message from", 1323 &tcpmsg->address, DNS_LOGCATEGORY_XFER_IN, 1324 DNS_LOGMODULE_XFER_IN, ISC_LOG_DEBUG(10), 1325 xfr->mctx); 1326 } else { 1327 xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s", 1328 dns_result_totext(result)); 1329 } 1330 1331 if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror || 1332 msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass || 1333 (xfr->checkid && msg->id != xfr->id)) 1334 { 1335 if (result == ISC_R_SUCCESS && msg->rcode != dns_rcode_noerror) 1336 { 1337 result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/ 1338 } else if (result == ISC_R_SUCCESS && 1339 msg->opcode != dns_opcode_query) 1340 { 1341 result = DNS_R_UNEXPECTEDOPCODE; 1342 } else if (result == ISC_R_SUCCESS && 1343 msg->rdclass != xfr->rdclass) 1344 { 1345 result = DNS_R_BADCLASS; 1346 } else if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR) { 1347 result = DNS_R_UNEXPECTEDID; 1348 } 1349 if (xfr->reqtype == dns_rdatatype_axfr || 1350 xfr->reqtype == dns_rdatatype_soa) 1351 { 1352 goto failure; 1353 } 1354 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR", 1355 isc_result_totext(result)); 1356 try_axfr: 1357 dns_message_detach(&msg); 1358 xfrin_reset(xfr); 1359 xfr->reqtype = dns_rdatatype_soa; 1360 xfr->state = XFRST_SOAQUERY; 1361 (void)xfrin_start(xfr); 1362 return; 1363 } else if (!xfr->checkid && msg->id != xfr->id && xfr->logit) { 1364 xfrin_log(xfr, ISC_LOG_WARNING, 1365 "detected message ID mismatch on incoming AXFR " 1366 "stream, transfer will fail in BIND 9.17.2 and " 1367 "later if AXFR source is not fixed"); 1368 xfr->logit = false; 1369 } 1370 1371 /* 1372 * Does the server know about IXFR? If it doesn't we will get 1373 * a message with a empty answer section or a potentially a CNAME / 1374 * DNAME, the later is handled by xfr_rr() which will return FORMERR 1375 * if the first RR in the answer section is not a SOA record. 1376 */ 1377 if (xfr->reqtype == dns_rdatatype_ixfr && 1378 xfr->state == XFRST_INITIALSOA && 1379 msg->counts[DNS_SECTION_ANSWER] == 0) 1380 { 1381 xfrin_log(xfr, ISC_LOG_DEBUG(3), 1382 "empty answer section, retrying with AXFR"); 1383 goto try_axfr; 1384 } 1385 1386 if (xfr->reqtype == dns_rdatatype_soa && 1387 (msg->flags & DNS_MESSAGEFLAG_AA) == 0) 1388 { 1389 FAIL(DNS_R_NOTAUTHORITATIVE); 1390 } 1391 1392 result = dns_message_checksig(msg, dns_zone_getview(xfr->zone)); 1393 if (result != ISC_R_SUCCESS) { 1394 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s", 1395 isc_result_totext(result)); 1396 goto failure; 1397 } 1398 1399 for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 1400 result == ISC_R_SUCCESS; 1401 result = dns_message_nextname(msg, DNS_SECTION_ANSWER)) 1402 { 1403 dns_rdataset_t *rds; 1404 1405 name = NULL; 1406 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 1407 for (rds = ISC_LIST_HEAD(name->list); rds != NULL; 1408 rds = ISC_LIST_NEXT(rds, link)) 1409 { 1410 for (result = dns_rdataset_first(rds); 1411 result == ISC_R_SUCCESS; 1412 result = dns_rdataset_next(rds)) 1413 { 1414 dns_rdata_t rdata = DNS_RDATA_INIT; 1415 dns_rdataset_current(rds, &rdata); 1416 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata)); 1417 } 1418 } 1419 } 1420 if (result != ISC_R_NOMORE) { 1421 goto failure; 1422 } 1423 1424 if (dns_message_gettsig(msg, &tsigowner) != NULL) { 1425 /* 1426 * Reset the counter. 1427 */ 1428 xfr->sincetsig = 0; 1429 1430 /* 1431 * Free the last tsig, if there is one. 1432 */ 1433 if (xfr->lasttsig != NULL) { 1434 isc_buffer_free(&xfr->lasttsig); 1435 } 1436 1437 /* 1438 * Update the last tsig pointer. 1439 */ 1440 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); 1441 } else if (dns_message_gettsigkey(msg) != NULL) { 1442 xfr->sincetsig++; 1443 if (xfr->sincetsig > 100 || xfr->nmsg == 0 || 1444 xfr->state == XFRST_AXFR_END || 1445 xfr->state == XFRST_IXFR_END) 1446 { 1447 result = DNS_R_EXPECTEDTSIG; 1448 goto failure; 1449 } 1450 } 1451 1452 /* 1453 * Update the number of messages received. 1454 */ 1455 xfr->nmsg++; 1456 1457 /* 1458 * Update the number of bytes received. 1459 */ 1460 xfr->nbytes += tcpmsg->buffer.used; 1461 1462 /* 1463 * Take the context back. 1464 */ 1465 INSIST(xfr->tsigctx == NULL); 1466 xfr->tsigctx = msg->tsigctx; 1467 msg->tsigctx = NULL; 1468 1469 dns_message_detach(&msg); 1470 1471 switch (xfr->state) { 1472 case XFRST_GOTSOA: 1473 xfr->reqtype = dns_rdatatype_axfr; 1474 xfr->state = XFRST_INITIALSOA; 1475 CHECK(xfrin_send_request(xfr)); 1476 break; 1477 case XFRST_AXFR_END: 1478 CHECK(axfr_finalize(xfr)); 1479 FALLTHROUGH; 1480 case XFRST_IXFR_END: 1481 /* 1482 * Close the journal. 1483 */ 1484 if (xfr->ixfr.journal != NULL) { 1485 dns_journal_destroy(&xfr->ixfr.journal); 1486 } 1487 1488 /* 1489 * Inform the caller we succeeded. 1490 */ 1491 if (xfr->done != NULL) { 1492 (xfr->done)(xfr->zone, ISC_R_SUCCESS); 1493 xfr->done = NULL; 1494 } 1495 /* 1496 * We should have no outstanding events at this 1497 * point, thus maybe_free() should succeed. 1498 */ 1499 xfr->shuttingdown = true; 1500 xfr->shutdown_result = ISC_R_SUCCESS; 1501 maybe_free(xfr); 1502 break; 1503 default: 1504 /* 1505 * Read the next message. 1506 */ 1507 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task, 1508 xfrin_recv_done, xfr)); 1509 xfr->recvs++; 1510 } 1511 return; 1512 1513failure: 1514 if (msg != NULL) { 1515 dns_message_detach(&msg); 1516 } 1517 if (result != ISC_R_SUCCESS) { 1518 xfrin_fail(xfr, result, "failed while receiving responses"); 1519 } 1520} 1521 1522static void 1523xfrin_timeout(isc_task_t *task, isc_event_t *event) { 1524 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg; 1525 1526 REQUIRE(VALID_XFRIN(xfr)); 1527 1528 UNUSED(task); 1529 1530 isc_event_free(&event); 1531 /* 1532 * This will log "giving up: timeout". 1533 */ 1534 xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up"); 1535} 1536 1537static void 1538maybe_free(dns_xfrin_ctx_t *xfr) { 1539 uint64_t msecs; 1540 uint64_t persec; 1541 const char *result_str; 1542 1543 REQUIRE(VALID_XFRIN(xfr)); 1544 1545 if (!xfr->shuttingdown || xfr->refcount != 0 || xfr->connects != 0 || 1546 xfr->sends != 0 || xfr->recvs != 0) 1547 { 1548 return; 1549 } 1550 1551 INSIST(!xfr->shuttingdown || xfr->shutdown_result != ISC_R_UNSET); 1552 1553 /* If we're called through dns_xfrin_detach() and are not 1554 * shutting down, we can't know what the transfer status is as 1555 * we are only called when the last reference is lost. 1556 */ 1557 result_str = (xfr->shuttingdown 1558 ? isc_result_totext(xfr->shutdown_result) 1559 : "unknown"); 1560 xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", result_str); 1561 1562 /* 1563 * Calculate the length of time the transfer took, 1564 * and print a log message with the bytes and rate. 1565 */ 1566 isc_time_now(&xfr->end); 1567 msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000; 1568 if (msecs == 0) { 1569 msecs = 1; 1570 } 1571 persec = (xfr->nbytes * 1000) / msecs; 1572 xfrin_log(xfr, ISC_LOG_INFO, 1573 "Transfer completed: %d messages, %d records, " 1574 "%" PRIu64 " bytes, " 1575 "%u.%03u secs (%u bytes/sec) (serial %u)", 1576 xfr->nmsg, xfr->nrecs, xfr->nbytes, 1577 (unsigned int)(msecs / 1000), (unsigned int)(msecs % 1000), 1578 (unsigned int)persec, xfr->end_serial); 1579 1580 if (xfr->socket != NULL) { 1581 isc_socket_detach(&xfr->socket); 1582 } 1583 1584 if (xfr->timer != NULL) { 1585 isc_timer_destroy(&xfr->timer); 1586 } 1587 1588 if (xfr->task != NULL) { 1589 isc_task_detach(&xfr->task); 1590 } 1591 1592 if (xfr->tsigkey != NULL) { 1593 dns_tsigkey_detach(&xfr->tsigkey); 1594 } 1595 1596 if (xfr->lasttsig != NULL) { 1597 isc_buffer_free(&xfr->lasttsig); 1598 } 1599 1600 dns_diff_clear(&xfr->diff); 1601 1602 if (xfr->ixfr.journal != NULL) { 1603 dns_journal_destroy(&xfr->ixfr.journal); 1604 } 1605 1606 if (xfr->axfr.add_private != NULL) { 1607 (void)dns_db_endload(xfr->db, &xfr->axfr); 1608 } 1609 1610 if (xfr->tcpmsg_valid) { 1611 dns_tcpmsg_invalidate(&xfr->tcpmsg); 1612 } 1613 1614 if (xfr->tsigctx != NULL) { 1615 dst_context_destroy(&xfr->tsigctx); 1616 } 1617 1618 if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0) { 1619 dns_name_free(&xfr->name, xfr->mctx); 1620 } 1621 1622 if (xfr->ver != NULL) { 1623 dns_db_closeversion(xfr->db, &xfr->ver, false); 1624 } 1625 1626 if (xfr->db != NULL) { 1627 dns_db_detach(&xfr->db); 1628 } 1629 1630 if (xfr->zone != NULL) { 1631 if (!xfr->zone_had_db && xfr->shuttingdown && 1632 xfr->shutdown_result == ISC_R_SUCCESS && 1633 dns_zone_gettype(xfr->zone) == dns_zone_mirror) 1634 { 1635 dns_zone_log(xfr->zone, ISC_LOG_INFO, 1636 "mirror zone is now in use"); 1637 } 1638 xfrin_log(xfr, ISC_LOG_DEBUG(99), "freeing transfer context"); 1639 /* 1640 * xfr->zone must not be detached before xfrin_log() is called. 1641 */ 1642 dns_zone_idetach(&xfr->zone); 1643 } 1644 1645 if (xfr->firstsoa_data != NULL) { 1646 isc_mem_free(xfr->mctx, xfr->firstsoa_data); 1647 } 1648 1649 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr)); 1650} 1651 1652/* 1653 * Log incoming zone transfer messages in a format like 1654 * transfer of <zone> from <address>: <message> 1655 */ 1656static void 1657xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *masteraddr, 1658 const char *fmt, va_list ap) { 1659 char mastertext[ISC_SOCKADDR_FORMATSIZE]; 1660 char msgtext[2048]; 1661 1662 isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext)); 1663 vsnprintf(msgtext, sizeof(msgtext), fmt, ap); 1664 1665 isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN, 1666 level, "transfer of '%s' from %s: %s", zonetext, 1667 mastertext, msgtext); 1668} 1669 1670/* 1671 * Logging function for use when a xfrin_ctx_t has not yet been created. 1672 */ 1673 1674static void 1675xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *masteraddr, 1676 const char *fmt, ...) { 1677 va_list ap; 1678 1679 if (!isc_log_wouldlog(dns_lctx, level)) { 1680 return; 1681 } 1682 1683 va_start(ap, fmt); 1684 xfrin_logv(level, zonetext, masteraddr, fmt, ap); 1685 va_end(ap); 1686} 1687 1688/* 1689 * Logging function for use when there is a xfrin_ctx_t. 1690 */ 1691 1692static void 1693xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) { 1694 va_list ap; 1695 char zonetext[DNS_NAME_MAXTEXT + 32]; 1696 1697 if (!isc_log_wouldlog(dns_lctx, level)) { 1698 return; 1699 } 1700 1701 dns_zone_name(xfr->zone, zonetext, sizeof(zonetext)); 1702 1703 va_start(ap, fmt); 1704 xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap); 1705 va_end(ap); 1706} 1707