2 * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.124.2.4.2.12 2005/11/03 23:08:41 marka Exp $ */
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/string.h> /* Required for HP/UX (and others?) */
27 #include <isc/timer.h>
32 #include <dns/events.h>
33 #include <dns/journal.h>
35 #include <dns/message.h>
36 #include <dns/rdataclass.h>
37 #include <dns/rdatalist.h>
38 #include <dns/rdataset.h>
39 #include <dns/result.h>
41 #include <dns/tcpmsg.h>
42 #include <dns/timer.h>
45 #include <dns/xfrin.h>
51 * Incoming AXFR and IXFR.
55 * It would be non-sensical (or at least obtuse) to use FAIL() with an
56 * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
57 * from complaining about "end-of-loop code not reached".
60 do { result = (code); \
61 if (result != ISC_R_SUCCESS) goto failure; \
66 if (result != ISC_R_SUCCESS) goto failure; \
70 * The states of the *XFR state machine. We handle both IXFR and AXFR
71 * with a single integrated state machine because they cannot be distinguished
72 * immediately - an AXFR response to an IXFR request can only be detected
73 * when the first two (2) response RRs have already been received.
87 * Incoming zone transfer context.
90 struct dns_xfrin_ctx {
99 isc_socketmgr_t *socketmgr;
101 int connects; /* Connect in progress */
102 int sends; /* Send in progress */
103 int recvs; /* Receive in progress */
104 isc_boolean_t shuttingdown;
106 dns_name_t name; /* Name of zone to transfer */
107 dns_rdataclass_t rdclass;
109 isc_boolean_t checkid;
113 * Requested transfer type (dns_rdatatype_axfr or
114 * dns_rdatatype_ixfr). The actual transfer type
115 * may differ due to IXFR->AXFR fallback.
117 dns_rdatatype_t reqtype;
119 isc_sockaddr_t masteraddr;
120 isc_sockaddr_t sourceaddr;
121 isc_socket_t *socket;
123 /* Buffer for IXFR/AXFR request message */
124 isc_buffer_t qbuffer;
125 unsigned char qbuffer_data[512];
127 /* Incoming reply TCP message */
129 isc_boolean_t tcpmsg_valid;
132 dns_dbversion_t *ver;
133 dns_diff_t diff; /* Pending database changes */
134 int difflen; /* Number of pending tuples */
137 isc_uint32_t end_serial;
138 isc_boolean_t is_ixfr;
140 unsigned int nmsg; /* Number of messages recvd */
142 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
143 isc_buffer_t *lasttsig; /* The last TSIG */
144 dst_context_t *tsigctx; /* TSIG verification context */
145 unsigned int sincetsig; /* recvd since the last TSIG */
146 dns_xfrindone_t done;
149 * AXFR- and IXFR-specific data. Only one is used at a time
150 * according to the is_ixfr flag, so this could be a union,
151 * but keeping them separate makes it a bit simpler to clean
152 * things up when destroying the context.
155 dns_addrdatasetfunc_t add_func;
156 dns_dbload_t *add_private;
160 isc_uint32_t request_serial;
161 isc_uint32_t current_serial;
162 dns_journal_t *journal;
167 #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
168 #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
170 /**************************************************************************/
172 * Forward declarations.
176 xfrin_create(isc_mem_t *mctx,
180 isc_timermgr_t *timermgr,
181 isc_socketmgr_t *socketmgr,
182 dns_name_t *zonename,
183 dns_rdataclass_t rdclass,
184 dns_rdatatype_t reqtype,
185 isc_sockaddr_t *masteraddr,
186 isc_sockaddr_t *sourceaddr,
187 dns_tsigkey_t *tsigkey,
188 dns_xfrin_ctx_t **xfrp);
190 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
191 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
192 static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
193 dns_name_t *name, dns_ttl_t ttl,
195 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
196 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
198 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
199 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
200 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
201 dns_name_t *name, dns_ttl_t ttl,
203 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
205 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
206 isc_uint32_t ttl, dns_rdata_t *rdata);
208 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
210 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
211 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
212 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
213 static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
214 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
215 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
217 static void maybe_free(dns_xfrin_ctx_t *xfr);
220 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
222 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
225 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
226 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
227 ISC_FORMAT_PRINTF(5, 0);
230 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
231 isc_sockaddr_t *masteraddr, const char *fmt, ...)
232 ISC_FORMAT_PRINTF(5, 6);
235 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
236 ISC_FORMAT_PRINTF(3, 4);
238 /**************************************************************************/
244 axfr_init(dns_xfrin_ctx_t *xfr) {
247 xfr->is_ixfr = ISC_FALSE;
250 dns_db_detach(&xfr->db);
252 CHECK(axfr_makedb(xfr, &xfr->db));
253 CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
254 &xfr->axfr.add_private));
255 result = ISC_R_SUCCESS;
261 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
262 return (dns_db_create(xfr->mctx, /* XXX */
263 "rbt", /* XXX guess */
267 0, NULL, /* XXX guess */
272 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
273 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
277 dns_difftuple_t *tuple = NULL;
279 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
280 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
281 name, ttl, rdata, &tuple));
282 dns_diff_append(&xfr->diff, &tuple);
283 if (++xfr->difflen > 100)
284 CHECK(axfr_apply(xfr));
285 result = ISC_R_SUCCESS;
291 * Store a set of AXFR RRs in the database.
294 axfr_apply(dns_xfrin_ctx_t *xfr) {
297 CHECK(dns_diff_load(&xfr->diff,
298 xfr->axfr.add_func, xfr->axfr.add_private));
300 dns_diff_clear(&xfr->diff);
301 result = ISC_R_SUCCESS;
307 axfr_commit(dns_xfrin_ctx_t *xfr) {
310 CHECK(axfr_apply(xfr));
311 CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
312 CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
314 result = ISC_R_SUCCESS;
319 /**************************************************************************/
325 ixfr_init(dns_xfrin_ctx_t *xfr) {
329 if (xfr->reqtype != dns_rdatatype_ixfr) {
330 xfrin_log(xfr, ISC_LOG_ERROR,
331 "got incremental response to AXFR request");
332 return (DNS_R_FORMERR);
335 xfr->is_ixfr = ISC_TRUE;
336 INSIST(xfr->db != NULL);
339 journalfile = dns_zone_getjournal(xfr->zone);
340 if (journalfile != NULL)
341 CHECK(dns_journal_open(xfr->mctx, journalfile,
342 ISC_TRUE, &xfr->ixfr.journal));
344 result = ISC_R_SUCCESS;
350 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
351 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
355 dns_difftuple_t *tuple = NULL;
356 if (op == DNS_DIFFOP_ADD)
357 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
358 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
359 name, ttl, rdata, &tuple));
360 dns_diff_append(&xfr->diff, &tuple);
361 if (++xfr->difflen > 100)
362 CHECK(ixfr_apply(xfr));
363 result = ISC_R_SUCCESS;
369 * Apply a set of IXFR changes to the database.
372 ixfr_apply(dns_xfrin_ctx_t *xfr) {
375 if (xfr->ver == NULL) {
376 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
377 if (xfr->ixfr.journal != NULL)
378 CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
380 CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
381 if (xfr->ixfr.journal != NULL) {
382 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
383 if (result != ISC_R_SUCCESS)
386 dns_diff_clear(&xfr->diff);
388 result = ISC_R_SUCCESS;
394 ixfr_commit(dns_xfrin_ctx_t *xfr) {
397 CHECK(ixfr_apply(xfr));
398 if (xfr->ver != NULL) {
399 /* XXX enter ready-to-commit state here */
400 if (xfr->ixfr.journal != NULL)
401 CHECK(dns_journal_commit(xfr->ixfr.journal));
402 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
403 dns_zone_markdirty(xfr->zone);
405 result = ISC_R_SUCCESS;
410 /**************************************************************************/
412 * Common AXFR/IXFR protocol code
416 * Handle a single incoming resource record according to the current
420 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
426 switch (xfr->state) {
427 case XFRST_INITIALSOA:
428 if (rdata->type != dns_rdatatype_soa) {
429 xfrin_log(xfr, ISC_LOG_ERROR,
430 "first RR in zone transfer must be SOA");
434 * Remember the serial number in the intial SOA.
435 * We need it to recognize the end of an IXFR.
437 xfr->end_serial = dns_soa_getserial(rdata);
438 if (xfr->reqtype == dns_rdatatype_ixfr &&
439 ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
440 && !dns_zone_isforced(xfr->zone))
443 * This must be the single SOA record that is
444 * sent when the current version on the master
445 * is not newer than the version in the request.
447 xfrin_log(xfr, ISC_LOG_DEBUG(3),
448 "requested serial %u, "
449 "master has %u, not updating",
450 xfr->ixfr.request_serial, xfr->end_serial);
451 FAIL(DNS_R_UPTODATE);
453 if (xfr->reqtype == dns_rdatatype_axfr)
454 xfr->checkid = ISC_FALSE;
455 xfr->state = XFRST_FIRSTDATA;
458 case XFRST_FIRSTDATA:
460 * If the transfer begins with one SOA record, it is an AXFR,
461 * if it begins with two SOAs, it is an IXFR.
463 if (xfr->reqtype == dns_rdatatype_ixfr &&
464 rdata->type == dns_rdatatype_soa &&
465 xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
466 xfrin_log(xfr, ISC_LOG_DEBUG(3),
467 "got incremental response");
468 CHECK(ixfr_init(xfr));
469 xfr->state = XFRST_IXFR_DELSOA;
471 xfrin_log(xfr, ISC_LOG_DEBUG(3),
472 "got nonincremental response");
473 CHECK(axfr_init(xfr));
474 xfr->state = XFRST_AXFR;
478 case XFRST_IXFR_DELSOA:
479 INSIST(rdata->type == dns_rdatatype_soa);
480 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
481 xfr->state = XFRST_IXFR_DEL;
485 if (rdata->type == dns_rdatatype_soa) {
486 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
487 xfr->state = XFRST_IXFR_ADDSOA;
488 xfr->ixfr.current_serial = soa_serial;
491 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
494 case XFRST_IXFR_ADDSOA:
495 INSIST(rdata->type == dns_rdatatype_soa);
496 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
497 xfr->state = XFRST_IXFR_ADD;
501 if (rdata->type == dns_rdatatype_soa) {
502 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
503 if (soa_serial == xfr->end_serial) {
504 CHECK(ixfr_commit(xfr));
505 xfr->state = XFRST_END;
507 } else if (soa_serial != xfr->ixfr.current_serial) {
508 xfrin_log(xfr, ISC_LOG_ERROR,
510 "expected serial %u, got %u",
511 xfr->ixfr.current_serial, soa_serial);
514 CHECK(ixfr_commit(xfr));
515 xfr->state = XFRST_IXFR_DELSOA;
519 if (rdata->type == dns_rdatatype_ns &&
520 dns_name_iswildcard(name))
521 FAIL(DNS_R_INVALIDNS);
522 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
527 * Old BINDs sent cross class A records for non IN classes.
529 if (rdata->type == dns_rdatatype_a &&
530 rdata->rdclass != xfr->rdclass &&
531 xfr->rdclass != dns_rdataclass_in)
533 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
534 if (rdata->type == dns_rdatatype_soa) {
535 CHECK(axfr_commit(xfr));
536 xfr->state = XFRST_END;
541 FAIL(DNS_R_EXTRADATA);
546 result = ISC_R_SUCCESS;
552 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
553 isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
554 isc_mem_t *mctx, isc_timermgr_t *timermgr,
555 isc_socketmgr_t *socketmgr, isc_task_t *task,
556 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
558 isc_sockaddr_t sourceaddr;
560 switch (isc_sockaddr_pf(masteraddr)) {
562 sourceaddr = *dns_zone_getxfrsource4(zone);
565 sourceaddr = *dns_zone_getxfrsource6(zone);
571 return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
572 tsigkey, mctx, timermgr, socketmgr,
577 dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
578 isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
579 dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
580 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
581 isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
583 dns_name_t *zonename = dns_zone_getorigin(zone);
584 dns_xfrin_ctx_t *xfr = NULL;
588 REQUIRE(xfrp != NULL && *xfrp == NULL);
590 (void)dns_zone_getdb(zone, &db);
592 CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
593 dns_zone_getclass(zone), xfrtype, masteraddr,
594 sourceaddr, tsigkey, &xfr));
596 CHECK(xfrin_start(xfr));
605 if (result != ISC_R_SUCCESS)
606 xfrin_log1(ISC_LOG_ERROR, zonename, dns_zone_getclass(zone),
607 masteraddr, "zone transfer setup failed");
612 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
613 if (! xfr->shuttingdown)
614 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
618 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
619 REQUIRE(target != NULL && *target == NULL);
625 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
626 dns_xfrin_ctx_t *xfr = *xfrp;
627 INSIST(xfr->refcount > 0);
634 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
635 if (xfr->connects > 0) {
636 isc_socket_cancel(xfr->socket, xfr->task,
637 ISC_SOCKCANCEL_CONNECT);
638 } else if (xfr->recvs > 0) {
639 dns_tcpmsg_cancelread(&xfr->tcpmsg);
640 } else if (xfr->sends > 0) {
641 isc_socket_cancel(xfr->socket, xfr->task,
642 ISC_SOCKCANCEL_SEND);
647 xfrin_reset(dns_xfrin_ctx_t *xfr) {
648 REQUIRE(VALID_XFRIN(xfr));
650 xfrin_log(xfr, ISC_LOG_INFO, "resetting");
654 if (xfr->socket != NULL)
655 isc_socket_detach(&xfr->socket);
657 if (xfr->lasttsig != NULL)
658 isc_buffer_free(&xfr->lasttsig);
660 dns_diff_clear(&xfr->diff);
663 if (xfr->ixfr.journal != NULL)
664 dns_journal_destroy(&xfr->ixfr.journal);
666 if (xfr->axfr.add_private != NULL) {
667 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
668 xfr->axfr.add_func = NULL;
671 if (xfr->tcpmsg_valid) {
672 dns_tcpmsg_invalidate(&xfr->tcpmsg);
673 xfr->tcpmsg_valid = ISC_FALSE;
676 if (xfr->ver != NULL)
677 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
682 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
683 if (result != DNS_R_UPTODATE) {
684 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
685 msg, isc_result_totext(result));
687 /* Pass special result code to force AXFR retry */
688 result = DNS_R_BADIXFR;
691 if (xfr->done != NULL) {
692 (xfr->done)(xfr->zone, result);
695 xfr->shuttingdown = ISC_TRUE;
700 xfrin_create(isc_mem_t *mctx,
704 isc_timermgr_t *timermgr,
705 isc_socketmgr_t *socketmgr,
706 dns_name_t *zonename,
707 dns_rdataclass_t rdclass,
708 dns_rdatatype_t reqtype,
709 isc_sockaddr_t *masteraddr,
710 isc_sockaddr_t *sourceaddr,
711 dns_tsigkey_t *tsigkey,
712 dns_xfrin_ctx_t **xfrp)
714 dns_xfrin_ctx_t *xfr = NULL;
718 xfr = isc_mem_get(mctx, sizeof(*xfr));
720 return (ISC_R_NOMEMORY);
724 dns_zone_iattach(zone, &xfr->zone);
726 isc_task_attach(task, &xfr->task);
728 xfr->socketmgr = socketmgr;
734 xfr->shuttingdown = ISC_FALSE;
736 dns_name_init(&xfr->name, NULL);
737 xfr->rdclass = rdclass;
738 isc_random_get(&tmp);
739 xfr->checkid = ISC_TRUE;
740 xfr->id = (isc_uint16_t)(tmp & 0xffff);
741 xfr->reqtype = reqtype;
748 xfr->tcpmsg_valid = ISC_FALSE;
752 dns_db_attach(db, &xfr->db);
754 dns_diff_init(xfr->mctx, &xfr->diff);
757 xfr->state = XFRST_INITIALSOA;
764 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
765 xfr->lasttsig = NULL;
768 xfr->is_ixfr = ISC_FALSE;
770 /* ixfr.request_serial */
771 /* ixfr.current_serial */
772 xfr->ixfr.journal = NULL;
774 xfr->axfr.add_func = NULL;
775 xfr->axfr.add_private = NULL;
777 CHECK(dns_name_dup(zonename, mctx, &xfr->name));
779 CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
780 task, xfrin_timeout, xfr, &xfr->timer));
781 CHECK(dns_timer_setidle(xfr->timer,
782 dns_zone_getmaxxfrin(xfr->zone),
783 dns_zone_getidlein(xfr->zone),
786 xfr->masteraddr = *masteraddr;
788 INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
789 xfr->sourceaddr = *sourceaddr;
790 isc_sockaddr_setport(&xfr->sourceaddr, 0);
792 isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
793 sizeof(xfr->qbuffer_data));
795 xfr->magic = XFRIN_MAGIC;
797 return (ISC_R_SUCCESS);
800 xfrin_fail(xfr, result, "failed creating transfer context");
805 xfrin_start(dns_xfrin_ctx_t *xfr) {
807 CHECK(isc_socket_create(xfr->socketmgr,
808 isc_sockaddr_pf(&xfr->sourceaddr),
811 CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr));
812 CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
813 xfrin_connect_done, xfr));
815 return (ISC_R_SUCCESS);
817 xfrin_fail(xfr, result, "failed setting up socket");
821 /* XXX the resolver could use this, too */
824 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
826 isc_boolean_t cleanup_cctx = ISC_FALSE;
829 CHECK(dns_compress_init(&cctx, -1, mctx));
830 cleanup_cctx = ISC_TRUE;
831 CHECK(dns_message_renderbegin(msg, &cctx, buf));
832 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
833 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
834 CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
835 CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
836 CHECK(dns_message_renderend(msg));
837 result = ISC_R_SUCCESS;
840 dns_compress_invalidate(&cctx);
845 * A connection has been established.
848 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
849 isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
850 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
851 isc_result_t evresult = cev->result;
853 char sourcetext[ISC_SOCKADDR_FORMATSIZE];
854 isc_sockaddr_t sockaddr;
856 REQUIRE(VALID_XFRIN(xfr));
860 INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
861 isc_event_free(&event);
864 if (xfr->shuttingdown) {
870 result = isc_socket_getsockname(xfr->socket, &sockaddr);
871 if (result == ISC_R_SUCCESS) {
872 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
874 strcpy(sourcetext, "<UNKNOWN>");
875 xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
877 dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
878 xfr->tcpmsg_valid = ISC_TRUE;
880 CHECK(xfrin_send_request(xfr));
882 if (result != ISC_R_SUCCESS)
883 xfrin_fail(xfr, result, "failed to connect");
887 * Convert a tuple into a dns_name_t suitable for inserting
888 * into the given dns_message_t.
891 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
894 dns_rdata_t *rdata = NULL;
895 dns_rdatalist_t *rdl = NULL;
896 dns_rdataset_t *rds = NULL;
897 dns_name_t *name = NULL;
899 REQUIRE(target != NULL && *target == NULL);
901 CHECK(dns_message_gettemprdata(msg, &rdata));
902 dns_rdata_init(rdata);
903 dns_rdata_clone(&tuple->rdata, rdata);
905 CHECK(dns_message_gettemprdatalist(msg, &rdl));
906 dns_rdatalist_init(rdl);
907 rdl->type = tuple->rdata.type;
908 rdl->rdclass = tuple->rdata.rdclass;
909 rdl->ttl = tuple->ttl;
910 ISC_LIST_APPEND(rdl->rdata, rdata, link);
912 CHECK(dns_message_gettemprdataset(msg, &rds));
913 dns_rdataset_init(rds);
914 CHECK(dns_rdatalist_tordataset(rdl, rds));
916 CHECK(dns_message_gettempname(msg, &name));
917 dns_name_init(name, NULL);
918 dns_name_clone(&tuple->name, name);
919 ISC_LIST_APPEND(name->list, rds, link);
922 return (ISC_R_SUCCESS);
927 dns_rdataset_disassociate(rds);
928 dns_message_puttemprdataset(msg, &rds);
931 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
932 dns_message_puttemprdatalist(msg, &rdl);
935 dns_message_puttemprdata(msg, &rdata);
942 * Build an *XFR request and send its length prefix.
945 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
948 isc_region_t lregion;
949 dns_rdataset_t *qrdataset = NULL;
950 dns_message_t *msg = NULL;
951 unsigned char length[2];
952 dns_difftuple_t *soatuple = NULL;
953 dns_name_t *qname = NULL;
954 dns_dbversion_t *ver = NULL;
955 dns_name_t *msgsoaname = NULL;
957 /* Create the request message */
958 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
959 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
961 /* Create a name for the question section. */
962 CHECK(dns_message_gettempname(msg, &qname));
963 dns_name_init(qname, NULL);
964 dns_name_clone(&xfr->name, qname);
966 /* Formulate the question and attach it to the question name. */
967 CHECK(dns_message_gettemprdataset(msg, &qrdataset));
968 dns_rdataset_init(qrdataset);
969 dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
970 ISC_LIST_APPEND(qname->list, qrdataset, link);
973 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
976 if (xfr->reqtype == dns_rdatatype_ixfr) {
977 /* Get the SOA and add it to the authority section. */
978 /* XXX is using the current version the right thing? */
979 dns_db_currentversion(xfr->db, &ver);
980 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
981 DNS_DIFFOP_EXISTS, &soatuple));
982 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
983 xfr->ixfr.current_serial = xfr->ixfr.request_serial;
984 xfrin_log(xfr, ISC_LOG_DEBUG(3),
985 "requesting IXFR for serial %u",
986 xfr->ixfr.request_serial);
988 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
989 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
992 xfr->checkid = ISC_TRUE;
996 CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
999 * Free the last tsig, if there is one.
1001 if (xfr->lasttsig != NULL)
1002 isc_buffer_free(&xfr->lasttsig);
1005 * Save the query TSIG and don't let message_destroy free it.
1007 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1009 isc_buffer_usedregion(&xfr->qbuffer, ®ion);
1010 INSIST(region.length <= 65535);
1012 length[0] = region.length >> 8;
1013 length[1] = region.length & 0xFF;
1014 lregion.base = length;
1016 CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
1017 xfrin_sendlen_done, xfr));
1022 dns_message_puttempname(msg, &qname);
1023 if (qrdataset != NULL)
1024 dns_message_puttemprdataset(msg, &qrdataset);
1026 dns_message_destroy(&msg);
1027 if (soatuple != NULL)
1028 dns_difftuple_free(&soatuple);
1030 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
1034 /* XXX there should be library support for sending DNS TCP messages */
1037 xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
1038 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1039 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1040 isc_result_t evresult = sev->result;
1041 isc_result_t result;
1042 isc_region_t region;
1044 REQUIRE(VALID_XFRIN(xfr));
1048 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1049 isc_event_free(&event);
1052 if (xfr->shuttingdown) {
1057 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1060 isc_buffer_usedregion(&xfr->qbuffer, ®ion);
1061 CHECK(isc_socket_send(xfr->socket, ®ion, xfr->task,
1062 xfrin_send_done, xfr));
1065 if (result != ISC_R_SUCCESS)
1066 xfrin_fail(xfr, result, "failed sending request length prefix");
1071 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
1072 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1073 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1074 isc_result_t result;
1076 REQUIRE(VALID_XFRIN(xfr));
1080 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1083 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1086 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1087 xfrin_recv_done, xfr));
1090 isc_event_free(&event);
1091 if (result != ISC_R_SUCCESS)
1092 xfrin_fail(xfr, result, "failed sending request data");
1097 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
1098 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
1099 isc_result_t result;
1100 dns_message_t *msg = NULL;
1102 dns_tcpmsg_t *tcpmsg;
1103 dns_name_t *tsigowner = NULL;
1105 REQUIRE(VALID_XFRIN(xfr));
1109 INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1110 tcpmsg = ev->ev_sender;
1111 isc_event_free(&ev);
1114 if (xfr->shuttingdown) {
1119 CHECK(tcpmsg->result);
1121 xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1122 tcpmsg->buffer.used);
1124 CHECK(isc_timer_touch(xfr->timer));
1126 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1128 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1129 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1130 msg->tsigctx = xfr->tsigctx;
1132 msg->tcp_continuation = 1;
1134 result = dns_message_parse(msg, &tcpmsg->buffer,
1135 DNS_MESSAGEPARSE_PRESERVEORDER);
1137 if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
1138 (xfr->checkid && msg->id != xfr->id)) {
1139 if (result == ISC_R_SUCCESS)
1140 result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
1141 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
1142 result = DNS_R_UNEXPECTEDID;
1143 if (xfr->reqtype == dns_rdatatype_axfr ||
1144 xfr->reqtype == dns_rdatatype_soa)
1146 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1147 isc_result_totext(result));
1149 dns_message_destroy(&msg);
1151 xfr->reqtype = dns_rdatatype_axfr;
1152 xfr->state = XFRST_INITIALSOA;
1153 (void)xfrin_start(xfr);
1158 * Does the server know about IXFR? If it doesn't we will get
1159 * a message with a empty answer section or a potentially a CNAME /
1160 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1161 * if the first RR in the answer section is not a SOA record.
1163 if (xfr->reqtype == dns_rdatatype_ixfr &&
1164 xfr->state == XFRST_INITIALSOA &&
1165 msg->counts[DNS_SECTION_ANSWER] == 0) {
1166 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1167 "empty answer section, retrying with AXFR");
1171 if (xfr->reqtype == dns_rdatatype_soa &&
1172 (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
1173 FAIL(DNS_R_NOTAUTHORITATIVE);
1177 result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
1178 if (result != ISC_R_SUCCESS) {
1179 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1180 isc_result_totext(result));
1184 for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1185 result == ISC_R_SUCCESS;
1186 result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1188 dns_rdataset_t *rds;
1191 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
1192 for (rds = ISC_LIST_HEAD(name->list);
1194 rds = ISC_LIST_NEXT(rds, link))
1196 for (result = dns_rdataset_first(rds);
1197 result == ISC_R_SUCCESS;
1198 result = dns_rdataset_next(rds))
1200 dns_rdata_t rdata = DNS_RDATA_INIT;
1201 dns_rdataset_current(rds, &rdata);
1202 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1206 if (result != ISC_R_NOMORE)
1209 if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1211 * Reset the counter.
1216 * Free the last tsig, if there is one.
1218 if (xfr->lasttsig != NULL)
1219 isc_buffer_free(&xfr->lasttsig);
1222 * Update the last tsig pointer.
1224 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1227 } else if (dns_message_gettsigkey(msg) != NULL) {
1229 if (xfr->sincetsig > 100 ||
1230 xfr->nmsg == 0 || xfr->state == XFRST_END)
1232 result = DNS_R_EXPECTEDTSIG;
1238 * Update the number of messages received.
1243 * Copy the context back.
1245 xfr->tsigctx = msg->tsigctx;
1247 dns_message_destroy(&msg);
1249 if (xfr->state == XFRST_END) {
1251 * Inform the caller we succeeded.
1253 if (xfr->done != NULL) {
1254 (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1258 * We should have no outstanding events at this
1259 * point, thus maybe_free() should succeed.
1261 xfr->shuttingdown = ISC_TRUE;
1265 * Read the next message.
1267 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1268 xfrin_recv_done, xfr));
1275 dns_message_destroy(&msg);
1276 if (result != ISC_R_SUCCESS)
1277 xfrin_fail(xfr, result, "failed while receiving responses");
1281 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
1282 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1284 REQUIRE(VALID_XFRIN(xfr));
1288 isc_event_free(&event);
1290 * This will log "giving up: timeout".
1292 xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1296 maybe_free(dns_xfrin_ctx_t *xfr) {
1297 REQUIRE(VALID_XFRIN(xfr));
1299 if (! xfr->shuttingdown || xfr->refcount != 0 ||
1300 xfr->connects != 0 || xfr->sends != 0 ||
1304 xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
1306 if (xfr->socket != NULL)
1307 isc_socket_detach(&xfr->socket);
1309 if (xfr->timer != NULL)
1310 isc_timer_detach(&xfr->timer);
1312 if (xfr->task != NULL)
1313 isc_task_detach(&xfr->task);
1315 if (xfr->tsigkey != NULL)
1316 dns_tsigkey_detach(&xfr->tsigkey);
1318 if (xfr->lasttsig != NULL)
1319 isc_buffer_free(&xfr->lasttsig);
1321 dns_diff_clear(&xfr->diff);
1323 if (xfr->ixfr.journal != NULL)
1324 dns_journal_destroy(&xfr->ixfr.journal);
1326 if (xfr->axfr.add_private != NULL)
1327 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1329 if (xfr->tcpmsg_valid)
1330 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1332 if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1333 dns_name_free(&xfr->name, xfr->mctx);
1335 if (xfr->ver != NULL)
1336 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1338 if (xfr->db != NULL)
1339 dns_db_detach(&xfr->db);
1341 if (xfr->zone != NULL)
1342 dns_zone_idetach(&xfr->zone);
1344 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1348 * Log incoming zone transfer messages in a format like
1349 * transfer of <zone> from <address>: <message>
1352 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1353 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
1355 char zntext[DNS_NAME_FORMATSIZE];
1356 char mastertext[ISC_SOCKADDR_FORMATSIZE];
1357 char classtext[DNS_RDATACLASS_FORMATSIZE];
1360 dns_name_format(zonename, zntext, sizeof(zntext));
1361 dns_rdataclass_format(rdclass, classtext, sizeof(classtext));
1362 isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
1363 vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
1365 isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
1366 DNS_LOGMODULE_XFER_IN, level,
1367 "transfer of '%s/%s' from %s: %s",
1368 zntext, classtext, mastertext, msgtext);
1372 * Logging function for use when a xfrin_ctx_t has not yet been created.
1376 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1377 isc_sockaddr_t *masteraddr, const char *fmt, ...)
1381 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1385 xfrin_logv(level, zonename, rdclass, masteraddr, fmt, ap);
1390 * Logging function for use when there is a xfrin_ctx_t.
1394 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
1398 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1402 xfrin_logv(level, &xfr->name, xfr->rdclass, &xfr->masteraddr, fmt, ap);