2 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or 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.
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.
18 /* $Id: xfrin.c,v 1.135.18.23 2008/09/25 04:15:52 marka Exp $ */
25 #include <isc/print.h>
26 #include <isc/random.h>
27 #include <isc/string.h> /* Required for HP/UX (and others?) */
29 #include <isc/timer.h>
34 #include <dns/events.h>
35 #include <dns/journal.h>
37 #include <dns/message.h>
38 #include <dns/rdataclass.h>
39 #include <dns/rdatalist.h>
40 #include <dns/rdataset.h>
41 #include <dns/result.h>
43 #include <dns/tcpmsg.h>
44 #include <dns/timer.h>
47 #include <dns/xfrin.h>
53 * Incoming AXFR and IXFR.
57 * It would be non-sensical (or at least obtuse) to use FAIL() with an
58 * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
59 * from complaining about "end-of-loop code not reached".
62 do { result = (code); \
63 if (result != ISC_R_SUCCESS) goto failure; \
68 if (result != ISC_R_SUCCESS) goto failure; \
72 * The states of the *XFR state machine. We handle both IXFR and AXFR
73 * with a single integrated state machine because they cannot be distinguished
74 * immediately - an AXFR response to an IXFR request can only be detected
75 * when the first two (2) response RRs have already been received.
91 * Incoming zone transfer context.
94 struct dns_xfrin_ctx {
103 isc_socketmgr_t *socketmgr;
105 int connects; /*%< Connect in progress */
106 int sends; /*%< Send in progress */
107 int recvs; /*%< Receive in progress */
108 isc_boolean_t shuttingdown;
110 dns_name_t name; /*%< Name of zone to transfer */
111 dns_rdataclass_t rdclass;
113 isc_boolean_t checkid;
117 * Requested transfer type (dns_rdatatype_axfr or
118 * dns_rdatatype_ixfr). The actual transfer type
119 * may differ due to IXFR->AXFR fallback.
121 dns_rdatatype_t reqtype;
123 isc_sockaddr_t masteraddr;
124 isc_sockaddr_t sourceaddr;
125 isc_socket_t *socket;
127 /*% Buffer for IXFR/AXFR request message */
128 isc_buffer_t qbuffer;
129 unsigned char qbuffer_data[512];
131 /*% Incoming reply TCP message */
133 isc_boolean_t tcpmsg_valid;
136 dns_dbversion_t *ver;
137 dns_diff_t diff; /*%< Pending database changes */
138 int difflen; /*%< Number of pending tuples */
141 isc_uint32_t end_serial;
142 isc_boolean_t is_ixfr;
144 unsigned int nmsg; /*%< Number of messages recvd */
146 dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
147 isc_buffer_t *lasttsig; /*%< The last TSIG */
148 dst_context_t *tsigctx; /*%< TSIG verification context */
149 unsigned int sincetsig; /*%< recvd since the last TSIG */
150 dns_xfrindone_t done;
153 * AXFR- and IXFR-specific data. Only one is used at a time
154 * according to the is_ixfr flag, so this could be a union,
155 * but keeping them separate makes it a bit simpler to clean
156 * things up when destroying the context.
159 dns_addrdatasetfunc_t add_func;
160 dns_dbload_t *add_private;
164 isc_uint32_t request_serial;
165 isc_uint32_t current_serial;
166 dns_journal_t *journal;
171 #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
172 #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
174 /**************************************************************************/
176 * Forward declarations.
180 xfrin_create(isc_mem_t *mctx,
184 isc_timermgr_t *timermgr,
185 isc_socketmgr_t *socketmgr,
186 dns_name_t *zonename,
187 dns_rdataclass_t rdclass,
188 dns_rdatatype_t reqtype,
189 isc_sockaddr_t *masteraddr,
190 isc_sockaddr_t *sourceaddr,
191 dns_tsigkey_t *tsigkey,
192 dns_xfrin_ctx_t **xfrp);
194 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
195 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
196 static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
197 dns_name_t *name, dns_ttl_t ttl,
199 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
200 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
202 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
203 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
204 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
205 dns_name_t *name, dns_ttl_t ttl,
207 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
209 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
210 isc_uint32_t ttl, dns_rdata_t *rdata);
212 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
214 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
215 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
216 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
217 static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
218 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
219 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
221 static void maybe_free(dns_xfrin_ctx_t *xfr);
224 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
226 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
229 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
230 const char *fmt, va_list ap)
231 ISC_FORMAT_PRINTF(4, 0);
234 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
235 const char *fmt, ...)
236 ISC_FORMAT_PRINTF(4, 5);
239 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
240 ISC_FORMAT_PRINTF(3, 4);
242 /**************************************************************************/
248 axfr_init(dns_xfrin_ctx_t *xfr) {
251 xfr->is_ixfr = ISC_FALSE;
254 dns_db_detach(&xfr->db);
256 CHECK(axfr_makedb(xfr, &xfr->db));
257 CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
258 &xfr->axfr.add_private));
259 result = ISC_R_SUCCESS;
265 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
266 return (dns_db_create(xfr->mctx, /* XXX */
267 "rbt", /* XXX guess */
271 0, NULL, /* XXX guess */
276 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
277 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
281 dns_difftuple_t *tuple = NULL;
283 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
284 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
285 name, ttl, rdata, &tuple));
286 dns_diff_append(&xfr->diff, &tuple);
287 if (++xfr->difflen > 100)
288 CHECK(axfr_apply(xfr));
289 result = ISC_R_SUCCESS;
295 * Store a set of AXFR RRs in the database.
298 axfr_apply(dns_xfrin_ctx_t *xfr) {
301 CHECK(dns_diff_load(&xfr->diff,
302 xfr->axfr.add_func, xfr->axfr.add_private));
304 dns_diff_clear(&xfr->diff);
305 result = ISC_R_SUCCESS;
311 axfr_commit(dns_xfrin_ctx_t *xfr) {
314 CHECK(axfr_apply(xfr));
315 CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
316 CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
318 result = ISC_R_SUCCESS;
323 /**************************************************************************/
329 ixfr_init(dns_xfrin_ctx_t *xfr) {
333 if (xfr->reqtype != dns_rdatatype_ixfr) {
334 xfrin_log(xfr, ISC_LOG_ERROR,
335 "got incremental response to AXFR request");
336 return (DNS_R_FORMERR);
339 xfr->is_ixfr = ISC_TRUE;
340 INSIST(xfr->db != NULL);
343 journalfile = dns_zone_getjournal(xfr->zone);
344 if (journalfile != NULL)
345 CHECK(dns_journal_open(xfr->mctx, journalfile,
346 ISC_TRUE, &xfr->ixfr.journal));
348 result = ISC_R_SUCCESS;
354 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
355 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
359 dns_difftuple_t *tuple = NULL;
360 if (op == DNS_DIFFOP_ADD)
361 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
362 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
363 name, ttl, rdata, &tuple));
364 dns_diff_append(&xfr->diff, &tuple);
365 if (++xfr->difflen > 100)
366 CHECK(ixfr_apply(xfr));
367 result = ISC_R_SUCCESS;
373 * Apply a set of IXFR changes to the database.
376 ixfr_apply(dns_xfrin_ctx_t *xfr) {
379 if (xfr->ver == NULL) {
380 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
381 if (xfr->ixfr.journal != NULL)
382 CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
384 CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
385 if (xfr->ixfr.journal != NULL) {
386 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
387 if (result != ISC_R_SUCCESS)
390 dns_diff_clear(&xfr->diff);
392 result = ISC_R_SUCCESS;
398 ixfr_commit(dns_xfrin_ctx_t *xfr) {
401 CHECK(ixfr_apply(xfr));
402 if (xfr->ver != NULL) {
403 /* XXX enter ready-to-commit state here */
404 if (xfr->ixfr.journal != NULL)
405 CHECK(dns_journal_commit(xfr->ixfr.journal));
406 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
407 dns_zone_markdirty(xfr->zone);
409 result = ISC_R_SUCCESS;
414 /**************************************************************************/
416 * Common AXFR/IXFR protocol code
420 * Handle a single incoming resource record according to the current
424 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
429 if (rdata->type == dns_rdatatype_none ||
430 dns_rdatatype_ismeta(rdata->type))
434 switch (xfr->state) {
436 if (rdata->type != dns_rdatatype_soa) {
437 xfrin_log(xfr, ISC_LOG_ERROR,
438 "non-SOA response to SOA query");
441 xfr->end_serial = dns_soa_getserial(rdata);
442 if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
443 !dns_zone_isforced(xfr->zone)) {
444 xfrin_log(xfr, ISC_LOG_DEBUG(3),
445 "requested serial %u, "
446 "master has %u, not updating",
447 xfr->ixfr.request_serial, xfr->end_serial);
448 FAIL(DNS_R_UPTODATE);
450 xfr->state = XFRST_GOTSOA;
455 * Skip other records in the answer section.
459 case XFRST_INITIALSOA:
460 if (rdata->type != dns_rdatatype_soa) {
461 xfrin_log(xfr, ISC_LOG_ERROR,
462 "first RR in zone transfer must be SOA");
466 * Remember the serial number in the initial SOA.
467 * We need it to recognize the end of an IXFR.
469 xfr->end_serial = dns_soa_getserial(rdata);
470 if (xfr->reqtype == dns_rdatatype_ixfr &&
471 ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
472 && !dns_zone_isforced(xfr->zone))
475 * This must be the single SOA record that is
476 * sent when the current version on the master
477 * is not newer than the version in the request.
479 xfrin_log(xfr, ISC_LOG_DEBUG(3),
480 "requested serial %u, "
481 "master has %u, not updating",
482 xfr->ixfr.request_serial, xfr->end_serial);
483 FAIL(DNS_R_UPTODATE);
485 if (xfr->reqtype == dns_rdatatype_axfr)
486 xfr->checkid = ISC_FALSE;
487 xfr->state = XFRST_FIRSTDATA;
490 case XFRST_FIRSTDATA:
492 * If the transfer begins with one SOA record, it is an AXFR,
493 * if it begins with two SOAs, it is an IXFR.
495 if (xfr->reqtype == dns_rdatatype_ixfr &&
496 rdata->type == dns_rdatatype_soa &&
497 xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
498 xfrin_log(xfr, ISC_LOG_DEBUG(3),
499 "got incremental response");
500 CHECK(ixfr_init(xfr));
501 xfr->state = XFRST_IXFR_DELSOA;
503 xfrin_log(xfr, ISC_LOG_DEBUG(3),
504 "got nonincremental response");
505 CHECK(axfr_init(xfr));
506 xfr->state = XFRST_AXFR;
510 case XFRST_IXFR_DELSOA:
511 INSIST(rdata->type == dns_rdatatype_soa);
512 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
513 xfr->state = XFRST_IXFR_DEL;
517 if (rdata->type == dns_rdatatype_soa) {
518 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
519 xfr->state = XFRST_IXFR_ADDSOA;
520 xfr->ixfr.current_serial = soa_serial;
523 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
526 case XFRST_IXFR_ADDSOA:
527 INSIST(rdata->type == dns_rdatatype_soa);
528 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
529 xfr->state = XFRST_IXFR_ADD;
533 if (rdata->type == dns_rdatatype_soa) {
534 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
535 if (soa_serial == xfr->end_serial) {
536 CHECK(ixfr_commit(xfr));
537 xfr->state = XFRST_END;
539 } else if (soa_serial != xfr->ixfr.current_serial) {
540 xfrin_log(xfr, ISC_LOG_ERROR,
542 "expected serial %u, got %u",
543 xfr->ixfr.current_serial, soa_serial);
546 CHECK(ixfr_commit(xfr));
547 xfr->state = XFRST_IXFR_DELSOA;
551 if (rdata->type == dns_rdatatype_ns &&
552 dns_name_iswildcard(name))
553 FAIL(DNS_R_INVALIDNS);
554 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
559 * Old BINDs sent cross class A records for non IN classes.
561 if (rdata->type == dns_rdatatype_a &&
562 rdata->rdclass != xfr->rdclass &&
563 xfr->rdclass != dns_rdataclass_in)
565 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
566 if (rdata->type == dns_rdatatype_soa) {
567 CHECK(axfr_commit(xfr));
568 xfr->state = XFRST_END;
573 FAIL(DNS_R_EXTRADATA);
578 result = ISC_R_SUCCESS;
584 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
585 isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
586 isc_mem_t *mctx, isc_timermgr_t *timermgr,
587 isc_socketmgr_t *socketmgr, isc_task_t *task,
588 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
590 isc_sockaddr_t sourceaddr;
592 switch (isc_sockaddr_pf(masteraddr)) {
594 sourceaddr = *dns_zone_getxfrsource4(zone);
597 sourceaddr = *dns_zone_getxfrsource6(zone);
603 return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
604 tsigkey, mctx, timermgr, socketmgr,
609 dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
610 isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
611 dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
612 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
613 isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
615 dns_name_t *zonename = dns_zone_getorigin(zone);
616 dns_xfrin_ctx_t *xfr = NULL;
620 REQUIRE(xfrp != NULL && *xfrp == NULL);
622 (void)dns_zone_getdb(zone, &db);
624 if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
627 CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
628 dns_zone_getclass(zone), xfrtype, masteraddr,
629 sourceaddr, tsigkey, &xfr));
631 CHECK(xfrin_start(xfr));
640 if (result != ISC_R_SUCCESS) {
641 char zonetext[DNS_NAME_MAXTEXT+32];
642 dns_zone_name(zone, zonetext, sizeof(zonetext));
643 xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr,
644 "zone transfer setup failed");
650 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
651 if (! xfr->shuttingdown)
652 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
656 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
657 REQUIRE(target != NULL && *target == NULL);
663 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
664 dns_xfrin_ctx_t *xfr = *xfrp;
665 INSIST(xfr->refcount > 0);
672 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
673 if (xfr->connects > 0) {
674 isc_socket_cancel(xfr->socket, xfr->task,
675 ISC_SOCKCANCEL_CONNECT);
676 } else if (xfr->recvs > 0) {
677 dns_tcpmsg_cancelread(&xfr->tcpmsg);
678 } else if (xfr->sends > 0) {
679 isc_socket_cancel(xfr->socket, xfr->task,
680 ISC_SOCKCANCEL_SEND);
685 xfrin_reset(dns_xfrin_ctx_t *xfr) {
686 REQUIRE(VALID_XFRIN(xfr));
688 xfrin_log(xfr, ISC_LOG_INFO, "resetting");
692 if (xfr->socket != NULL)
693 isc_socket_detach(&xfr->socket);
695 if (xfr->lasttsig != NULL)
696 isc_buffer_free(&xfr->lasttsig);
698 dns_diff_clear(&xfr->diff);
701 if (xfr->ixfr.journal != NULL)
702 dns_journal_destroy(&xfr->ixfr.journal);
704 if (xfr->axfr.add_private != NULL) {
705 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
706 xfr->axfr.add_func = NULL;
709 if (xfr->tcpmsg_valid) {
710 dns_tcpmsg_invalidate(&xfr->tcpmsg);
711 xfr->tcpmsg_valid = ISC_FALSE;
714 if (xfr->ver != NULL)
715 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
720 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
721 if (result != DNS_R_UPTODATE) {
722 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
723 msg, isc_result_totext(result));
725 /* Pass special result code to force AXFR retry */
726 result = DNS_R_BADIXFR;
732 if (xfr->ixfr.journal != NULL)
733 dns_journal_destroy(&xfr->ixfr.journal);
734 if (xfr->done != NULL) {
735 (xfr->done)(xfr->zone, result);
738 xfr->shuttingdown = ISC_TRUE;
743 xfrin_create(isc_mem_t *mctx,
747 isc_timermgr_t *timermgr,
748 isc_socketmgr_t *socketmgr,
749 dns_name_t *zonename,
750 dns_rdataclass_t rdclass,
751 dns_rdatatype_t reqtype,
752 isc_sockaddr_t *masteraddr,
753 isc_sockaddr_t *sourceaddr,
754 dns_tsigkey_t *tsigkey,
755 dns_xfrin_ctx_t **xfrp)
757 dns_xfrin_ctx_t *xfr = NULL;
761 xfr = isc_mem_get(mctx, sizeof(*xfr));
763 return (ISC_R_NOMEMORY);
767 dns_zone_iattach(zone, &xfr->zone);
769 isc_task_attach(task, &xfr->task);
771 xfr->socketmgr = socketmgr;
777 xfr->shuttingdown = ISC_FALSE;
779 dns_name_init(&xfr->name, NULL);
780 xfr->rdclass = rdclass;
781 isc_random_get(&tmp);
782 xfr->checkid = ISC_TRUE;
783 xfr->id = (isc_uint16_t)(tmp & 0xffff);
784 xfr->reqtype = reqtype;
791 xfr->tcpmsg_valid = ISC_FALSE;
795 dns_db_attach(db, &xfr->db);
797 dns_diff_init(xfr->mctx, &xfr->diff);
800 if (reqtype == dns_rdatatype_soa)
801 xfr->state = XFRST_SOAQUERY;
803 xfr->state = XFRST_INITIALSOA;
810 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
811 xfr->lasttsig = NULL;
814 xfr->is_ixfr = ISC_FALSE;
816 /* ixfr.request_serial */
817 /* ixfr.current_serial */
818 xfr->ixfr.journal = NULL;
820 xfr->axfr.add_func = NULL;
821 xfr->axfr.add_private = NULL;
823 CHECK(dns_name_dup(zonename, mctx, &xfr->name));
825 CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
826 task, xfrin_timeout, xfr, &xfr->timer));
827 CHECK(dns_timer_setidle(xfr->timer,
828 dns_zone_getmaxxfrin(xfr->zone),
829 dns_zone_getidlein(xfr->zone),
832 xfr->masteraddr = *masteraddr;
834 INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
835 xfr->sourceaddr = *sourceaddr;
836 isc_sockaddr_setport(&xfr->sourceaddr, 0);
838 isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
839 sizeof(xfr->qbuffer_data));
841 xfr->magic = XFRIN_MAGIC;
843 return (ISC_R_SUCCESS);
846 if (xfr->timer != NULL)
847 isc_timer_detach(&xfr->timer);
848 if (dns_name_dynamic(&xfr->name))
849 dns_name_free(&xfr->name, xfr->mctx);
850 if (xfr->tsigkey != NULL)
851 dns_tsigkey_detach(&xfr->tsigkey);
853 dns_db_detach(&xfr->db);
854 isc_task_detach(&xfr->task);
855 dns_zone_idetach(&xfr->zone);
856 isc_mem_put(mctx, xfr, sizeof(*xfr));
862 xfrin_start(dns_xfrin_ctx_t *xfr) {
864 CHECK(isc_socket_create(xfr->socketmgr,
865 isc_sockaddr_pf(&xfr->sourceaddr),
868 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
869 CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
870 ISC_SOCKET_REUSEADDRESS));
872 CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
873 xfrin_connect_done, xfr));
875 return (ISC_R_SUCCESS);
877 xfrin_fail(xfr, result, "failed setting up socket");
881 /* XXX the resolver could use this, too */
884 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
886 isc_boolean_t cleanup_cctx = ISC_FALSE;
889 CHECK(dns_compress_init(&cctx, -1, mctx));
890 cleanup_cctx = ISC_TRUE;
891 CHECK(dns_message_renderbegin(msg, &cctx, buf));
892 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
893 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
894 CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
895 CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
896 CHECK(dns_message_renderend(msg));
897 result = ISC_R_SUCCESS;
900 dns_compress_invalidate(&cctx);
905 * A connection has been established.
908 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
909 isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
910 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
911 isc_result_t evresult = cev->result;
913 char sourcetext[ISC_SOCKADDR_FORMATSIZE];
914 isc_sockaddr_t sockaddr;
916 REQUIRE(VALID_XFRIN(xfr));
920 INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
921 isc_event_free(&event);
924 if (xfr->shuttingdown) {
930 result = isc_socket_getsockname(xfr->socket, &sockaddr);
931 if (result == ISC_R_SUCCESS) {
932 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
934 strcpy(sourcetext, "<UNKNOWN>");
935 xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
937 dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
938 xfr->tcpmsg_valid = ISC_TRUE;
940 CHECK(xfrin_send_request(xfr));
942 if (result != ISC_R_SUCCESS)
943 xfrin_fail(xfr, result, "failed to connect");
947 * Convert a tuple into a dns_name_t suitable for inserting
948 * into the given dns_message_t.
951 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
954 dns_rdata_t *rdata = NULL;
955 dns_rdatalist_t *rdl = NULL;
956 dns_rdataset_t *rds = NULL;
957 dns_name_t *name = NULL;
959 REQUIRE(target != NULL && *target == NULL);
961 CHECK(dns_message_gettemprdata(msg, &rdata));
962 dns_rdata_init(rdata);
963 dns_rdata_clone(&tuple->rdata, rdata);
965 CHECK(dns_message_gettemprdatalist(msg, &rdl));
966 dns_rdatalist_init(rdl);
967 rdl->type = tuple->rdata.type;
968 rdl->rdclass = tuple->rdata.rdclass;
969 rdl->ttl = tuple->ttl;
970 ISC_LIST_APPEND(rdl->rdata, rdata, link);
972 CHECK(dns_message_gettemprdataset(msg, &rds));
973 dns_rdataset_init(rds);
974 CHECK(dns_rdatalist_tordataset(rdl, rds));
976 CHECK(dns_message_gettempname(msg, &name));
977 dns_name_init(name, NULL);
978 dns_name_clone(&tuple->name, name);
979 ISC_LIST_APPEND(name->list, rds, link);
982 return (ISC_R_SUCCESS);
987 dns_rdataset_disassociate(rds);
988 dns_message_puttemprdataset(msg, &rds);
991 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
992 dns_message_puttemprdatalist(msg, &rdl);
995 dns_message_puttemprdata(msg, &rdata);
1002 * Build an *XFR request and send its length prefix.
1005 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
1006 isc_result_t result;
1007 isc_region_t region;
1008 isc_region_t lregion;
1009 dns_rdataset_t *qrdataset = NULL;
1010 dns_message_t *msg = NULL;
1011 unsigned char length[2];
1012 dns_difftuple_t *soatuple = NULL;
1013 dns_name_t *qname = NULL;
1014 dns_dbversion_t *ver = NULL;
1015 dns_name_t *msgsoaname = NULL;
1017 /* Create the request message */
1018 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
1019 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1021 /* Create a name for the question section. */
1022 CHECK(dns_message_gettempname(msg, &qname));
1023 dns_name_init(qname, NULL);
1024 dns_name_clone(&xfr->name, qname);
1026 /* Formulate the question and attach it to the question name. */
1027 CHECK(dns_message_gettemprdataset(msg, &qrdataset));
1028 dns_rdataset_init(qrdataset);
1029 dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
1030 ISC_LIST_APPEND(qname->list, qrdataset, link);
1033 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1036 if (xfr->reqtype == dns_rdatatype_ixfr) {
1037 /* Get the SOA and add it to the authority section. */
1038 /* XXX is using the current version the right thing? */
1039 dns_db_currentversion(xfr->db, &ver);
1040 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
1041 DNS_DIFFOP_EXISTS, &soatuple));
1042 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
1043 xfr->ixfr.current_serial = xfr->ixfr.request_serial;
1044 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1045 "requesting IXFR for serial %u",
1046 xfr->ixfr.request_serial);
1048 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
1049 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
1050 } else if (xfr->reqtype == dns_rdatatype_soa)
1051 CHECK(dns_db_getsoaserial(xfr->db, NULL,
1052 &xfr->ixfr.request_serial));
1054 xfr->checkid = ISC_TRUE;
1058 if (xfr->tsigctx != NULL)
1059 dst_context_destroy(&xfr->tsigctx);
1061 CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
1064 * Free the last tsig, if there is one.
1066 if (xfr->lasttsig != NULL)
1067 isc_buffer_free(&xfr->lasttsig);
1070 * Save the query TSIG and don't let message_destroy free it.
1072 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1074 isc_buffer_usedregion(&xfr->qbuffer, ®ion);
1075 INSIST(region.length <= 65535);
1077 length[0] = region.length >> 8;
1078 length[1] = region.length & 0xFF;
1079 lregion.base = length;
1081 CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
1082 xfrin_sendlen_done, xfr));
1087 dns_message_puttempname(msg, &qname);
1088 if (qrdataset != NULL)
1089 dns_message_puttemprdataset(msg, &qrdataset);
1091 dns_message_destroy(&msg);
1092 if (soatuple != NULL)
1093 dns_difftuple_free(&soatuple);
1095 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
1099 /* XXX there should be library support for sending DNS TCP messages */
1102 xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
1103 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1104 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1105 isc_result_t evresult = sev->result;
1106 isc_result_t result;
1107 isc_region_t region;
1109 REQUIRE(VALID_XFRIN(xfr));
1113 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1114 isc_event_free(&event);
1117 if (xfr->shuttingdown) {
1122 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1125 isc_buffer_usedregion(&xfr->qbuffer, ®ion);
1126 CHECK(isc_socket_send(xfr->socket, ®ion, xfr->task,
1127 xfrin_send_done, xfr));
1130 if (result != ISC_R_SUCCESS)
1131 xfrin_fail(xfr, result, "failed sending request length prefix");
1136 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
1137 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1138 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1139 isc_result_t result;
1141 REQUIRE(VALID_XFRIN(xfr));
1145 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1148 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1151 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1152 xfrin_recv_done, xfr));
1155 isc_event_free(&event);
1156 if (result != ISC_R_SUCCESS)
1157 xfrin_fail(xfr, result, "failed sending request data");
1162 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
1163 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
1164 isc_result_t result;
1165 dns_message_t *msg = NULL;
1167 dns_tcpmsg_t *tcpmsg;
1168 dns_name_t *tsigowner = NULL;
1170 REQUIRE(VALID_XFRIN(xfr));
1174 INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1175 tcpmsg = ev->ev_sender;
1176 isc_event_free(&ev);
1179 if (xfr->shuttingdown) {
1184 CHECK(tcpmsg->result);
1186 xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1187 tcpmsg->buffer.used);
1189 CHECK(isc_timer_touch(xfr->timer));
1191 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1193 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1194 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1196 msg->tsigctx = xfr->tsigctx;
1197 xfr->tsigctx = NULL;
1200 msg->tcp_continuation = 1;
1202 result = dns_message_parse(msg, &tcpmsg->buffer,
1203 DNS_MESSAGEPARSE_PRESERVEORDER);
1205 if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
1206 (xfr->checkid && msg->id != xfr->id)) {
1207 if (result == ISC_R_SUCCESS)
1208 result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
1209 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
1210 result = DNS_R_UNEXPECTEDID;
1211 if (xfr->reqtype == dns_rdatatype_axfr ||
1212 xfr->reqtype == dns_rdatatype_soa)
1214 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1215 isc_result_totext(result));
1217 dns_message_destroy(&msg);
1219 xfr->reqtype = dns_rdatatype_soa;
1220 xfr->state = XFRST_SOAQUERY;
1221 (void)xfrin_start(xfr);
1226 * Does the server know about IXFR? If it doesn't we will get
1227 * a message with a empty answer section or a potentially a CNAME /
1228 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1229 * if the first RR in the answer section is not a SOA record.
1231 if (xfr->reqtype == dns_rdatatype_ixfr &&
1232 xfr->state == XFRST_INITIALSOA &&
1233 msg->counts[DNS_SECTION_ANSWER] == 0) {
1234 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1235 "empty answer section, retrying with AXFR");
1239 if (xfr->reqtype == dns_rdatatype_soa &&
1240 (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
1241 FAIL(DNS_R_NOTAUTHORITATIVE);
1245 result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
1246 if (result != ISC_R_SUCCESS) {
1247 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1248 isc_result_totext(result));
1252 for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1253 result == ISC_R_SUCCESS;
1254 result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1256 dns_rdataset_t *rds;
1259 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
1260 for (rds = ISC_LIST_HEAD(name->list);
1262 rds = ISC_LIST_NEXT(rds, link))
1264 for (result = dns_rdataset_first(rds);
1265 result == ISC_R_SUCCESS;
1266 result = dns_rdataset_next(rds))
1268 dns_rdata_t rdata = DNS_RDATA_INIT;
1269 dns_rdataset_current(rds, &rdata);
1270 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1274 if (result != ISC_R_NOMORE)
1277 if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1279 * Reset the counter.
1284 * Free the last tsig, if there is one.
1286 if (xfr->lasttsig != NULL)
1287 isc_buffer_free(&xfr->lasttsig);
1290 * Update the last tsig pointer.
1292 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1295 } else if (dns_message_gettsigkey(msg) != NULL) {
1297 if (xfr->sincetsig > 100 ||
1298 xfr->nmsg == 0 || xfr->state == XFRST_END)
1300 result = DNS_R_EXPECTEDTSIG;
1306 * Update the number of messages received.
1311 * Take the context back.
1313 INSIST(xfr->tsigctx == NULL);
1314 xfr->tsigctx = msg->tsigctx;
1315 msg->tsigctx = NULL;
1317 dns_message_destroy(&msg);
1319 if (xfr->state == XFRST_GOTSOA) {
1320 xfr->reqtype = dns_rdatatype_axfr;
1321 xfr->state = XFRST_INITIALSOA;
1322 CHECK(xfrin_send_request(xfr));
1323 } else if (xfr->state == XFRST_END) {
1325 * Close the journal.
1327 if (xfr->ixfr.journal != NULL)
1328 dns_journal_destroy(&xfr->ixfr.journal);
1330 * Inform the caller we succeeded.
1332 if (xfr->done != NULL) {
1333 (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1337 * We should have no outstanding events at this
1338 * point, thus maybe_free() should succeed.
1340 xfr->shuttingdown = ISC_TRUE;
1344 * Read the next message.
1346 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1347 xfrin_recv_done, xfr));
1354 dns_message_destroy(&msg);
1355 if (result != ISC_R_SUCCESS)
1356 xfrin_fail(xfr, result, "failed while receiving responses");
1360 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
1361 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1363 REQUIRE(VALID_XFRIN(xfr));
1367 isc_event_free(&event);
1369 * This will log "giving up: timeout".
1371 xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1375 maybe_free(dns_xfrin_ctx_t *xfr) {
1376 REQUIRE(VALID_XFRIN(xfr));
1378 if (! xfr->shuttingdown || xfr->refcount != 0 ||
1379 xfr->connects != 0 || xfr->sends != 0 ||
1383 xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
1385 if (xfr->socket != NULL)
1386 isc_socket_detach(&xfr->socket);
1388 if (xfr->timer != NULL)
1389 isc_timer_detach(&xfr->timer);
1391 if (xfr->task != NULL)
1392 isc_task_detach(&xfr->task);
1394 if (xfr->tsigkey != NULL)
1395 dns_tsigkey_detach(&xfr->tsigkey);
1397 if (xfr->lasttsig != NULL)
1398 isc_buffer_free(&xfr->lasttsig);
1400 dns_diff_clear(&xfr->diff);
1402 if (xfr->ixfr.journal != NULL)
1403 dns_journal_destroy(&xfr->ixfr.journal);
1405 if (xfr->axfr.add_private != NULL)
1406 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1408 if (xfr->tcpmsg_valid)
1409 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1411 if (xfr->tsigctx != NULL)
1412 dst_context_destroy(&xfr->tsigctx);
1414 if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1415 dns_name_free(&xfr->name, xfr->mctx);
1417 if (xfr->ver != NULL)
1418 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1420 if (xfr->db != NULL)
1421 dns_db_detach(&xfr->db);
1423 if (xfr->zone != NULL)
1424 dns_zone_idetach(&xfr->zone);
1426 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1430 * Log incoming zone transfer messages in a format like
1431 * transfer of <zone> from <address>: <message>
1434 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
1435 const char *fmt, va_list ap)
1437 char mastertext[ISC_SOCKADDR_FORMATSIZE];
1440 isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
1441 vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
1443 isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
1444 DNS_LOGMODULE_XFER_IN, level,
1445 "transfer of '%s' from %s: %s",
1446 zonetext, mastertext, msgtext);
1450 * Logging function for use when a xfrin_ctx_t has not yet been created.
1454 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
1455 const char *fmt, ...)
1459 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1463 xfrin_logv(level, zonetext, masteraddr, fmt, ap);
1468 * Logging function for use when there is a xfrin_ctx_t.
1472 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
1475 char zonetext[DNS_NAME_MAXTEXT+32];
1477 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1480 dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
1483 xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap);