4 * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: xfrin.c,v 1.166 2008/09/25 04:12:39 marka Exp */
27 #include <isc/print.h>
28 #include <isc/random.h>
29 #include <isc/string.h> /* Required for HP/UX (and others?) */
31 #include <isc/timer.h>
36 #include <dns/events.h>
37 #include <dns/journal.h>
39 #include <dns/message.h>
40 #include <dns/rdataclass.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/result.h>
45 #include <dns/tcpmsg.h>
46 #include <dns/timer.h>
49 #include <dns/xfrin.h>
55 * Incoming AXFR and IXFR.
59 * It would be non-sensical (or at least obtuse) to use FAIL() with an
60 * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
61 * from complaining about "end-of-loop code not reached".
64 do { result = (code); \
65 if (result != ISC_R_SUCCESS) goto failure; \
70 if (result != ISC_R_SUCCESS) goto failure; \
74 * The states of the *XFR state machine. We handle both IXFR and AXFR
75 * with a single integrated state machine because they cannot be distinguished
76 * immediately - an AXFR response to an IXFR request can only be detected
77 * when the first two (2) response RRs have already been received.
93 * Incoming zone transfer context.
96 struct dns_xfrin_ctx
{
105 isc_socketmgr_t
*socketmgr
;
107 int connects
; /*%< Connect in progress */
108 int sends
; /*%< Send in progress */
109 int recvs
; /*%< Receive in progress */
110 isc_boolean_t shuttingdown
;
112 dns_name_t name
; /*%< Name of zone to transfer */
113 dns_rdataclass_t rdclass
;
115 isc_boolean_t checkid
;
119 * Requested transfer type (dns_rdatatype_axfr or
120 * dns_rdatatype_ixfr). The actual transfer type
121 * may differ due to IXFR->AXFR fallback.
123 dns_rdatatype_t reqtype
;
125 isc_sockaddr_t masteraddr
;
126 isc_sockaddr_t sourceaddr
;
127 isc_socket_t
*socket
;
129 /*% Buffer for IXFR/AXFR request message */
130 isc_buffer_t qbuffer
;
131 unsigned char qbuffer_data
[512];
133 /*% Incoming reply TCP message */
135 isc_boolean_t tcpmsg_valid
;
138 dns_dbversion_t
*ver
;
139 dns_diff_t diff
; /*%< Pending database changes */
140 int difflen
; /*%< Number of pending tuples */
143 isc_uint32_t end_serial
;
144 isc_boolean_t is_ixfr
;
146 unsigned int nmsg
; /*%< Number of messages recvd */
147 unsigned int nrecs
; /*%< Number of records recvd */
148 isc_uint64_t nbytes
; /*%< Number of bytes received */
150 isc_time_t start
; /*%< Start time of the transfer */
151 isc_time_t end
; /*%< End time of the transfer */
153 dns_tsigkey_t
*tsigkey
; /*%< Key used to create TSIG */
154 isc_buffer_t
*lasttsig
; /*%< The last TSIG */
155 dst_context_t
*tsigctx
; /*%< TSIG verification context */
156 unsigned int sincetsig
; /*%< recvd since the last TSIG */
157 dns_xfrindone_t done
;
160 * AXFR- and IXFR-specific data. Only one is used at a time
161 * according to the is_ixfr flag, so this could be a union,
162 * but keeping them separate makes it a bit simpler to clean
163 * things up when destroying the context.
166 dns_addrdatasetfunc_t add_func
;
167 dns_dbload_t
*add_private
;
171 isc_uint32_t request_serial
;
172 isc_uint32_t current_serial
;
173 dns_journal_t
*journal
;
178 #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
179 #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
181 /**************************************************************************/
183 * Forward declarations.
187 xfrin_create(isc_mem_t
*mctx
,
191 isc_timermgr_t
*timermgr
,
192 isc_socketmgr_t
*socketmgr
,
193 dns_name_t
*zonename
,
194 dns_rdataclass_t rdclass
,
195 dns_rdatatype_t reqtype
,
196 isc_sockaddr_t
*masteraddr
,
197 isc_sockaddr_t
*sourceaddr
,
198 dns_tsigkey_t
*tsigkey
,
199 dns_xfrin_ctx_t
**xfrp
);
201 static isc_result_t
axfr_init(dns_xfrin_ctx_t
*xfr
);
202 static isc_result_t
axfr_makedb(dns_xfrin_ctx_t
*xfr
, dns_db_t
**dbp
);
203 static isc_result_t
axfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
204 dns_name_t
*name
, dns_ttl_t ttl
,
206 static isc_result_t
axfr_apply(dns_xfrin_ctx_t
*xfr
);
207 static isc_result_t
axfr_commit(dns_xfrin_ctx_t
*xfr
);
209 static isc_result_t
ixfr_init(dns_xfrin_ctx_t
*xfr
);
210 static isc_result_t
ixfr_apply(dns_xfrin_ctx_t
*xfr
);
211 static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
212 dns_name_t
*name
, dns_ttl_t ttl
,
214 static isc_result_t
ixfr_commit(dns_xfrin_ctx_t
*xfr
);
216 static isc_result_t
xfr_rr(dns_xfrin_ctx_t
*xfr
, dns_name_t
*name
,
217 isc_uint32_t ttl
, dns_rdata_t
*rdata
);
219 static isc_result_t
xfrin_start(dns_xfrin_ctx_t
*xfr
);
221 static void xfrin_connect_done(isc_task_t
*task
, isc_event_t
*event
);
222 static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t
*xfr
);
223 static void xfrin_send_done(isc_task_t
*task
, isc_event_t
*event
);
224 static void xfrin_sendlen_done(isc_task_t
*task
, isc_event_t
*event
);
225 static void xfrin_recv_done(isc_task_t
*task
, isc_event_t
*event
);
226 static void xfrin_timeout(isc_task_t
*task
, isc_event_t
*event
);
228 static void maybe_free(dns_xfrin_ctx_t
*xfr
);
231 xfrin_fail(dns_xfrin_ctx_t
*xfr
, isc_result_t result
, const char *msg
);
233 render(dns_message_t
*msg
, isc_mem_t
*mctx
, isc_buffer_t
*buf
);
236 xfrin_logv(int level
, const char *zonetext
, isc_sockaddr_t
*masteraddr
,
237 const char *fmt
, va_list ap
)
238 ISC_FORMAT_PRINTF(4, 0);
241 xfrin_log1(int level
, const char *zonetext
, isc_sockaddr_t
*masteraddr
,
242 const char *fmt
, ...)
243 ISC_FORMAT_PRINTF(4, 5);
246 xfrin_log(dns_xfrin_ctx_t
*xfr
, int level
, const char *fmt
, ...)
247 ISC_FORMAT_PRINTF(3, 4);
249 /**************************************************************************/
255 axfr_init(dns_xfrin_ctx_t
*xfr
) {
258 xfr
->is_ixfr
= ISC_FALSE
;
261 dns_db_detach(&xfr
->db
);
263 CHECK(axfr_makedb(xfr
, &xfr
->db
));
264 CHECK(dns_db_beginload(xfr
->db
, &xfr
->axfr
.add_func
,
265 &xfr
->axfr
.add_private
));
266 result
= ISC_R_SUCCESS
;
272 axfr_makedb(dns_xfrin_ctx_t
*xfr
, dns_db_t
**dbp
) {
273 return (dns_db_create(xfr
->mctx
, /* XXX */
274 "rbt", /* XXX guess */
278 0, NULL
, /* XXX guess */
283 axfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
284 dns_name_t
*name
, dns_ttl_t ttl
, dns_rdata_t
*rdata
)
288 dns_difftuple_t
*tuple
= NULL
;
290 CHECK(dns_zone_checknames(xfr
->zone
, name
, rdata
));
291 CHECK(dns_difftuple_create(xfr
->diff
.mctx
, op
,
292 name
, ttl
, rdata
, &tuple
));
293 dns_diff_append(&xfr
->diff
, &tuple
);
294 if (++xfr
->difflen
> 100)
295 CHECK(axfr_apply(xfr
));
296 result
= ISC_R_SUCCESS
;
302 * Store a set of AXFR RRs in the database.
305 axfr_apply(dns_xfrin_ctx_t
*xfr
) {
308 CHECK(dns_diff_load(&xfr
->diff
,
309 xfr
->axfr
.add_func
, xfr
->axfr
.add_private
));
311 dns_diff_clear(&xfr
->diff
);
312 result
= ISC_R_SUCCESS
;
318 axfr_commit(dns_xfrin_ctx_t
*xfr
) {
321 CHECK(axfr_apply(xfr
));
322 CHECK(dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
));
323 CHECK(dns_zone_replacedb(xfr
->zone
, xfr
->db
, ISC_TRUE
));
325 result
= ISC_R_SUCCESS
;
330 /**************************************************************************/
336 ixfr_init(dns_xfrin_ctx_t
*xfr
) {
340 if (xfr
->reqtype
!= dns_rdatatype_ixfr
) {
341 xfrin_log(xfr
, ISC_LOG_ERROR
,
342 "got incremental response to AXFR request");
343 return (DNS_R_FORMERR
);
346 xfr
->is_ixfr
= ISC_TRUE
;
347 INSIST(xfr
->db
!= NULL
);
350 journalfile
= dns_zone_getjournal(xfr
->zone
);
351 if (journalfile
!= NULL
)
352 CHECK(dns_journal_open(xfr
->mctx
, journalfile
,
353 ISC_TRUE
, &xfr
->ixfr
.journal
));
355 result
= ISC_R_SUCCESS
;
361 ixfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
362 dns_name_t
*name
, dns_ttl_t ttl
, dns_rdata_t
*rdata
)
366 dns_difftuple_t
*tuple
= NULL
;
367 if (op
== DNS_DIFFOP_ADD
)
368 CHECK(dns_zone_checknames(xfr
->zone
, name
, rdata
));
369 CHECK(dns_difftuple_create(xfr
->diff
.mctx
, op
,
370 name
, ttl
, rdata
, &tuple
));
371 dns_diff_append(&xfr
->diff
, &tuple
);
372 if (++xfr
->difflen
> 100)
373 CHECK(ixfr_apply(xfr
));
374 result
= ISC_R_SUCCESS
;
380 * Apply a set of IXFR changes to the database.
383 ixfr_apply(dns_xfrin_ctx_t
*xfr
) {
386 if (xfr
->ver
== NULL
) {
387 CHECK(dns_db_newversion(xfr
->db
, &xfr
->ver
));
388 if (xfr
->ixfr
.journal
!= NULL
)
389 CHECK(dns_journal_begin_transaction(xfr
->ixfr
.journal
));
391 CHECK(dns_diff_apply(&xfr
->diff
, xfr
->db
, xfr
->ver
));
392 if (xfr
->ixfr
.journal
!= NULL
) {
393 result
= dns_journal_writediff(xfr
->ixfr
.journal
, &xfr
->diff
);
394 if (result
!= ISC_R_SUCCESS
)
397 dns_diff_clear(&xfr
->diff
);
399 result
= ISC_R_SUCCESS
;
405 ixfr_commit(dns_xfrin_ctx_t
*xfr
) {
408 CHECK(ixfr_apply(xfr
));
409 if (xfr
->ver
!= NULL
) {
410 /* XXX enter ready-to-commit state here */
411 if (xfr
->ixfr
.journal
!= NULL
)
412 CHECK(dns_journal_commit(xfr
->ixfr
.journal
));
413 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_TRUE
);
414 dns_zone_markdirty(xfr
->zone
);
416 result
= ISC_R_SUCCESS
;
421 /**************************************************************************/
423 * Common AXFR/IXFR protocol code
427 * Handle a single incoming resource record according to the current
431 xfr_rr(dns_xfrin_ctx_t
*xfr
, dns_name_t
*name
, isc_uint32_t ttl
,
438 if (rdata
->type
== dns_rdatatype_none
||
439 dns_rdatatype_ismeta(rdata
->type
))
443 switch (xfr
->state
) {
445 if (rdata
->type
!= dns_rdatatype_soa
) {
446 xfrin_log(xfr
, ISC_LOG_ERROR
,
447 "non-SOA response to SOA query");
450 xfr
->end_serial
= dns_soa_getserial(rdata
);
451 if (!DNS_SERIAL_GT(xfr
->end_serial
, xfr
->ixfr
.request_serial
) &&
452 !dns_zone_isforced(xfr
->zone
)) {
453 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
454 "requested serial %u, "
455 "master has %u, not updating",
456 xfr
->ixfr
.request_serial
, xfr
->end_serial
);
457 FAIL(DNS_R_UPTODATE
);
459 xfr
->state
= XFRST_GOTSOA
;
464 * Skip other records in the answer section.
468 case XFRST_INITIALSOA
:
469 if (rdata
->type
!= dns_rdatatype_soa
) {
470 xfrin_log(xfr
, ISC_LOG_ERROR
,
471 "first RR in zone transfer must be SOA");
475 * Remember the serial number in the initial SOA.
476 * We need it to recognize the end of an IXFR.
478 xfr
->end_serial
= dns_soa_getserial(rdata
);
479 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
480 ! DNS_SERIAL_GT(xfr
->end_serial
, xfr
->ixfr
.request_serial
)
481 && !dns_zone_isforced(xfr
->zone
))
484 * This must be the single SOA record that is
485 * sent when the current version on the master
486 * is not newer than the version in the request.
488 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
489 "requested serial %u, "
490 "master has %u, not updating",
491 xfr
->ixfr
.request_serial
, xfr
->end_serial
);
492 FAIL(DNS_R_UPTODATE
);
494 if (xfr
->reqtype
== dns_rdatatype_axfr
)
495 xfr
->checkid
= ISC_FALSE
;
496 xfr
->state
= XFRST_FIRSTDATA
;
499 case XFRST_FIRSTDATA
:
501 * If the transfer begins with one SOA record, it is an AXFR,
502 * if it begins with two SOAs, it is an IXFR.
504 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
505 rdata
->type
== dns_rdatatype_soa
&&
506 xfr
->ixfr
.request_serial
== dns_soa_getserial(rdata
)) {
507 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
508 "got incremental response");
509 CHECK(ixfr_init(xfr
));
510 xfr
->state
= XFRST_IXFR_DELSOA
;
512 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
513 "got nonincremental response");
514 CHECK(axfr_init(xfr
));
515 xfr
->state
= XFRST_AXFR
;
519 case XFRST_IXFR_DELSOA
:
520 INSIST(rdata
->type
== dns_rdatatype_soa
);
521 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_DEL
, name
, ttl
, rdata
));
522 xfr
->state
= XFRST_IXFR_DEL
;
526 if (rdata
->type
== dns_rdatatype_soa
) {
527 isc_uint32_t soa_serial
= dns_soa_getserial(rdata
);
528 xfr
->state
= XFRST_IXFR_ADDSOA
;
529 xfr
->ixfr
.current_serial
= soa_serial
;
532 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_DEL
, name
, ttl
, rdata
));
535 case XFRST_IXFR_ADDSOA
:
536 INSIST(rdata
->type
== dns_rdatatype_soa
);
537 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
538 xfr
->state
= XFRST_IXFR_ADD
;
542 if (rdata
->type
== dns_rdatatype_soa
) {
543 isc_uint32_t soa_serial
= dns_soa_getserial(rdata
);
544 if (soa_serial
== xfr
->end_serial
) {
545 CHECK(ixfr_commit(xfr
));
546 xfr
->state
= XFRST_END
;
548 } else if (soa_serial
!= xfr
->ixfr
.current_serial
) {
549 xfrin_log(xfr
, ISC_LOG_ERROR
,
551 "expected serial %u, got %u",
552 xfr
->ixfr
.current_serial
, soa_serial
);
555 CHECK(ixfr_commit(xfr
));
556 xfr
->state
= XFRST_IXFR_DELSOA
;
560 if (rdata
->type
== dns_rdatatype_ns
&&
561 dns_name_iswildcard(name
))
562 FAIL(DNS_R_INVALIDNS
);
563 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
568 * Old BINDs sent cross class A records for non IN classes.
570 if (rdata
->type
== dns_rdatatype_a
&&
571 rdata
->rdclass
!= xfr
->rdclass
&&
572 xfr
->rdclass
!= dns_rdataclass_in
)
574 CHECK(axfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
575 if (rdata
->type
== dns_rdatatype_soa
) {
576 CHECK(axfr_commit(xfr
));
577 xfr
->state
= XFRST_END
;
582 FAIL(DNS_R_EXTRADATA
);
587 result
= ISC_R_SUCCESS
;
593 dns_xfrin_create(dns_zone_t
*zone
, dns_rdatatype_t xfrtype
,
594 isc_sockaddr_t
*masteraddr
, dns_tsigkey_t
*tsigkey
,
595 isc_mem_t
*mctx
, isc_timermgr_t
*timermgr
,
596 isc_socketmgr_t
*socketmgr
, isc_task_t
*task
,
597 dns_xfrindone_t done
, dns_xfrin_ctx_t
**xfrp
)
599 isc_sockaddr_t sourceaddr
;
601 switch (isc_sockaddr_pf(masteraddr
)) {
603 sourceaddr
= *dns_zone_getxfrsource4(zone
);
606 sourceaddr
= *dns_zone_getxfrsource6(zone
);
612 return(dns_xfrin_create2(zone
, xfrtype
, masteraddr
, &sourceaddr
,
613 tsigkey
, mctx
, timermgr
, socketmgr
,
618 dns_xfrin_create2(dns_zone_t
*zone
, dns_rdatatype_t xfrtype
,
619 isc_sockaddr_t
*masteraddr
, isc_sockaddr_t
*sourceaddr
,
620 dns_tsigkey_t
*tsigkey
, isc_mem_t
*mctx
,
621 isc_timermgr_t
*timermgr
, isc_socketmgr_t
*socketmgr
,
622 isc_task_t
*task
, dns_xfrindone_t done
, dns_xfrin_ctx_t
**xfrp
)
624 dns_name_t
*zonename
= dns_zone_getorigin(zone
);
625 dns_xfrin_ctx_t
*xfr
= NULL
;
629 REQUIRE(xfrp
!= NULL
&& *xfrp
== NULL
);
631 (void)dns_zone_getdb(zone
, &db
);
633 if (xfrtype
== dns_rdatatype_soa
|| xfrtype
== dns_rdatatype_ixfr
)
636 CHECK(xfrin_create(mctx
, zone
, db
, task
, timermgr
, socketmgr
, zonename
,
637 dns_zone_getclass(zone
), xfrtype
, masteraddr
,
638 sourceaddr
, tsigkey
, &xfr
));
640 CHECK(xfrin_start(xfr
));
649 if (result
!= ISC_R_SUCCESS
) {
650 char zonetext
[DNS_NAME_MAXTEXT
+32];
651 dns_zone_name(zone
, zonetext
, sizeof(zonetext
));
652 xfrin_log1(ISC_LOG_ERROR
, zonetext
, masteraddr
,
653 "zone transfer setup failed");
659 dns_xfrin_shutdown(dns_xfrin_ctx_t
*xfr
) {
660 if (! xfr
->shuttingdown
)
661 xfrin_fail(xfr
, ISC_R_CANCELED
, "shut down");
665 dns_xfrin_attach(dns_xfrin_ctx_t
*source
, dns_xfrin_ctx_t
**target
) {
666 REQUIRE(target
!= NULL
&& *target
== NULL
);
672 dns_xfrin_detach(dns_xfrin_ctx_t
**xfrp
) {
673 dns_xfrin_ctx_t
*xfr
= *xfrp
;
674 INSIST(xfr
->refcount
> 0);
681 xfrin_cancelio(dns_xfrin_ctx_t
*xfr
) {
682 if (xfr
->connects
> 0) {
683 isc_socket_cancel(xfr
->socket
, xfr
->task
,
684 ISC_SOCKCANCEL_CONNECT
);
685 } else if (xfr
->recvs
> 0) {
686 dns_tcpmsg_cancelread(&xfr
->tcpmsg
);
687 } else if (xfr
->sends
> 0) {
688 isc_socket_cancel(xfr
->socket
, xfr
->task
,
689 ISC_SOCKCANCEL_SEND
);
694 xfrin_reset(dns_xfrin_ctx_t
*xfr
) {
695 REQUIRE(VALID_XFRIN(xfr
));
697 xfrin_log(xfr
, ISC_LOG_INFO
, "resetting");
701 if (xfr
->socket
!= NULL
)
702 isc_socket_detach(&xfr
->socket
);
704 if (xfr
->lasttsig
!= NULL
)
705 isc_buffer_free(&xfr
->lasttsig
);
707 dns_diff_clear(&xfr
->diff
);
710 if (xfr
->ixfr
.journal
!= NULL
)
711 dns_journal_destroy(&xfr
->ixfr
.journal
);
713 if (xfr
->axfr
.add_private
!= NULL
) {
714 (void)dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
);
715 xfr
->axfr
.add_func
= NULL
;
718 if (xfr
->tcpmsg_valid
) {
719 dns_tcpmsg_invalidate(&xfr
->tcpmsg
);
720 xfr
->tcpmsg_valid
= ISC_FALSE
;
723 if (xfr
->ver
!= NULL
)
724 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_FALSE
);
729 xfrin_fail(dns_xfrin_ctx_t
*xfr
, isc_result_t result
, const char *msg
) {
730 if (result
!= DNS_R_UPTODATE
) {
731 xfrin_log(xfr
, ISC_LOG_ERROR
, "%s: %s",
732 msg
, isc_result_totext(result
));
734 /* Pass special result code to force AXFR retry */
735 result
= DNS_R_BADIXFR
;
741 if (xfr
->ixfr
.journal
!= NULL
)
742 dns_journal_destroy(&xfr
->ixfr
.journal
);
743 if (xfr
->done
!= NULL
) {
744 (xfr
->done
)(xfr
->zone
, result
);
747 xfr
->shuttingdown
= ISC_TRUE
;
752 xfrin_create(isc_mem_t
*mctx
,
756 isc_timermgr_t
*timermgr
,
757 isc_socketmgr_t
*socketmgr
,
758 dns_name_t
*zonename
,
759 dns_rdataclass_t rdclass
,
760 dns_rdatatype_t reqtype
,
761 isc_sockaddr_t
*masteraddr
,
762 isc_sockaddr_t
*sourceaddr
,
763 dns_tsigkey_t
*tsigkey
,
764 dns_xfrin_ctx_t
**xfrp
)
766 dns_xfrin_ctx_t
*xfr
= NULL
;
770 xfr
= isc_mem_get(mctx
, sizeof(*xfr
));
772 return (ISC_R_NOMEMORY
);
776 dns_zone_iattach(zone
, &xfr
->zone
);
778 isc_task_attach(task
, &xfr
->task
);
780 xfr
->socketmgr
= socketmgr
;
786 xfr
->shuttingdown
= ISC_FALSE
;
788 dns_name_init(&xfr
->name
, NULL
);
789 xfr
->rdclass
= rdclass
;
790 isc_random_get(&tmp
);
791 xfr
->checkid
= ISC_TRUE
;
792 xfr
->id
= (isc_uint16_t
)(tmp
& 0xffff);
793 xfr
->reqtype
= reqtype
;
800 xfr
->tcpmsg_valid
= ISC_FALSE
;
804 dns_db_attach(db
, &xfr
->db
);
806 dns_diff_init(xfr
->mctx
, &xfr
->diff
);
809 if (reqtype
== dns_rdatatype_soa
)
810 xfr
->state
= XFRST_SOAQUERY
;
812 xfr
->state
= XFRST_INITIALSOA
;
818 isc_time_now(&xfr
->start
);
822 dns_tsigkey_attach(tsigkey
, &xfr
->tsigkey
);
823 xfr
->lasttsig
= NULL
;
826 xfr
->is_ixfr
= ISC_FALSE
;
828 /* ixfr.request_serial */
829 /* ixfr.current_serial */
830 xfr
->ixfr
.journal
= NULL
;
832 xfr
->axfr
.add_func
= NULL
;
833 xfr
->axfr
.add_private
= NULL
;
835 CHECK(dns_name_dup(zonename
, mctx
, &xfr
->name
));
837 CHECK(isc_timer_create(timermgr
, isc_timertype_inactive
, NULL
, NULL
,
838 task
, xfrin_timeout
, xfr
, &xfr
->timer
));
839 CHECK(dns_timer_setidle(xfr
->timer
,
840 dns_zone_getmaxxfrin(xfr
->zone
),
841 dns_zone_getidlein(xfr
->zone
),
844 xfr
->masteraddr
= *masteraddr
;
846 INSIST(isc_sockaddr_pf(masteraddr
) == isc_sockaddr_pf(sourceaddr
));
847 xfr
->sourceaddr
= *sourceaddr
;
848 isc_sockaddr_setport(&xfr
->sourceaddr
, 0);
850 isc_buffer_init(&xfr
->qbuffer
, xfr
->qbuffer_data
,
851 sizeof(xfr
->qbuffer_data
));
853 xfr
->magic
= XFRIN_MAGIC
;
855 return (ISC_R_SUCCESS
);
858 if (xfr
->timer
!= NULL
)
859 isc_timer_detach(&xfr
->timer
);
860 if (dns_name_dynamic(&xfr
->name
))
861 dns_name_free(&xfr
->name
, xfr
->mctx
);
862 if (xfr
->tsigkey
!= NULL
)
863 dns_tsigkey_detach(&xfr
->tsigkey
);
865 dns_db_detach(&xfr
->db
);
866 isc_task_detach(&xfr
->task
);
867 dns_zone_idetach(&xfr
->zone
);
868 isc_mem_put(mctx
, xfr
, sizeof(*xfr
));
874 xfrin_start(dns_xfrin_ctx_t
*xfr
) {
876 CHECK(isc_socket_create(xfr
->socketmgr
,
877 isc_sockaddr_pf(&xfr
->sourceaddr
),
880 isc_socket_setname(xfr
->socket
, "xfrin", NULL
);
881 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
882 CHECK(isc_socket_bind(xfr
->socket
, &xfr
->sourceaddr
,
883 ISC_SOCKET_REUSEADDRESS
));
885 CHECK(isc_socket_connect(xfr
->socket
, &xfr
->masteraddr
, xfr
->task
,
886 xfrin_connect_done
, xfr
));
888 return (ISC_R_SUCCESS
);
890 xfrin_fail(xfr
, result
, "failed setting up socket");
894 /* XXX the resolver could use this, too */
897 render(dns_message_t
*msg
, isc_mem_t
*mctx
, isc_buffer_t
*buf
) {
899 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
902 CHECK(dns_compress_init(&cctx
, -1, mctx
));
903 cleanup_cctx
= ISC_TRUE
;
904 CHECK(dns_message_renderbegin(msg
, &cctx
, buf
));
905 CHECK(dns_message_rendersection(msg
, DNS_SECTION_QUESTION
, 0));
906 CHECK(dns_message_rendersection(msg
, DNS_SECTION_ANSWER
, 0));
907 CHECK(dns_message_rendersection(msg
, DNS_SECTION_AUTHORITY
, 0));
908 CHECK(dns_message_rendersection(msg
, DNS_SECTION_ADDITIONAL
, 0));
909 CHECK(dns_message_renderend(msg
));
910 result
= ISC_R_SUCCESS
;
913 dns_compress_invalidate(&cctx
);
918 * A connection has been established.
921 xfrin_connect_done(isc_task_t
*task
, isc_event_t
*event
) {
922 isc_socket_connev_t
*cev
= (isc_socket_connev_t
*) event
;
923 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
924 isc_result_t result
= cev
->result
;
925 char sourcetext
[ISC_SOCKADDR_FORMATSIZE
];
926 isc_sockaddr_t sockaddr
;
928 REQUIRE(VALID_XFRIN(xfr
));
932 INSIST(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
933 isc_event_free(&event
);
936 if (xfr
->shuttingdown
) {
941 if (result
!= ISC_R_SUCCESS
) {
942 dns_zonemgr_t
* zmgr
= dns_zone_getmgr(xfr
->zone
);
947 dns_zonemgr_unreachableadd(zmgr
, &xfr
->masteraddr
,
948 &xfr
->sourceaddr
, &now
);
953 result
= isc_socket_getsockname(xfr
->socket
, &sockaddr
);
954 if (result
== ISC_R_SUCCESS
) {
955 isc_sockaddr_format(&sockaddr
, sourcetext
, sizeof(sourcetext
));
957 strcpy(sourcetext
, "<UNKNOWN>");
958 xfrin_log(xfr
, ISC_LOG_INFO
, "connected using %s", sourcetext
);
960 dns_tcpmsg_init(xfr
->mctx
, xfr
->socket
, &xfr
->tcpmsg
);
961 xfr
->tcpmsg_valid
= ISC_TRUE
;
963 CHECK(xfrin_send_request(xfr
));
965 if (result
!= ISC_R_SUCCESS
)
966 xfrin_fail(xfr
, result
, "failed to connect");
970 * Convert a tuple into a dns_name_t suitable for inserting
971 * into the given dns_message_t.
974 tuple2msgname(dns_difftuple_t
*tuple
, dns_message_t
*msg
, dns_name_t
**target
)
977 dns_rdata_t
*rdata
= NULL
;
978 dns_rdatalist_t
*rdl
= NULL
;
979 dns_rdataset_t
*rds
= NULL
;
980 dns_name_t
*name
= NULL
;
982 REQUIRE(target
!= NULL
&& *target
== NULL
);
984 CHECK(dns_message_gettemprdata(msg
, &rdata
));
985 dns_rdata_init(rdata
);
986 dns_rdata_clone(&tuple
->rdata
, rdata
);
988 CHECK(dns_message_gettemprdatalist(msg
, &rdl
));
989 dns_rdatalist_init(rdl
);
990 rdl
->type
= tuple
->rdata
.type
;
991 rdl
->rdclass
= tuple
->rdata
.rdclass
;
992 rdl
->ttl
= tuple
->ttl
;
993 ISC_LIST_APPEND(rdl
->rdata
, rdata
, link
);
995 CHECK(dns_message_gettemprdataset(msg
, &rds
));
996 dns_rdataset_init(rds
);
997 CHECK(dns_rdatalist_tordataset(rdl
, rds
));
999 CHECK(dns_message_gettempname(msg
, &name
));
1000 dns_name_init(name
, NULL
);
1001 dns_name_clone(&tuple
->name
, name
);
1002 ISC_LIST_APPEND(name
->list
, rds
, link
);
1005 return (ISC_R_SUCCESS
);
1010 dns_rdataset_disassociate(rds
);
1011 dns_message_puttemprdataset(msg
, &rds
);
1014 ISC_LIST_UNLINK(rdl
->rdata
, rdata
, link
);
1015 dns_message_puttemprdatalist(msg
, &rdl
);
1018 dns_message_puttemprdata(msg
, &rdata
);
1025 * Build an *XFR request and send its length prefix.
1028 xfrin_send_request(dns_xfrin_ctx_t
*xfr
) {
1029 isc_result_t result
;
1030 isc_region_t region
;
1031 isc_region_t lregion
;
1032 dns_rdataset_t
*qrdataset
= NULL
;
1033 dns_message_t
*msg
= NULL
;
1034 unsigned char length
[2];
1035 dns_difftuple_t
*soatuple
= NULL
;
1036 dns_name_t
*qname
= NULL
;
1037 dns_dbversion_t
*ver
= NULL
;
1038 dns_name_t
*msgsoaname
= NULL
;
1040 /* Create the request message */
1041 CHECK(dns_message_create(xfr
->mctx
, DNS_MESSAGE_INTENTRENDER
, &msg
));
1042 CHECK(dns_message_settsigkey(msg
, xfr
->tsigkey
));
1044 /* Create a name for the question section. */
1045 CHECK(dns_message_gettempname(msg
, &qname
));
1046 dns_name_init(qname
, NULL
);
1047 dns_name_clone(&xfr
->name
, qname
);
1049 /* Formulate the question and attach it to the question name. */
1050 CHECK(dns_message_gettemprdataset(msg
, &qrdataset
));
1051 dns_rdataset_init(qrdataset
);
1052 dns_rdataset_makequestion(qrdataset
, xfr
->rdclass
, xfr
->reqtype
);
1053 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
1056 dns_message_addname(msg
, qname
, DNS_SECTION_QUESTION
);
1059 if (xfr
->reqtype
== dns_rdatatype_ixfr
) {
1060 /* Get the SOA and add it to the authority section. */
1061 /* XXX is using the current version the right thing? */
1062 dns_db_currentversion(xfr
->db
, &ver
);
1063 CHECK(dns_db_createsoatuple(xfr
->db
, ver
, xfr
->mctx
,
1064 DNS_DIFFOP_EXISTS
, &soatuple
));
1065 xfr
->ixfr
.request_serial
= dns_soa_getserial(&soatuple
->rdata
);
1066 xfr
->ixfr
.current_serial
= xfr
->ixfr
.request_serial
;
1067 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
1068 "requesting IXFR for serial %u",
1069 xfr
->ixfr
.request_serial
);
1071 CHECK(tuple2msgname(soatuple
, msg
, &msgsoaname
));
1072 dns_message_addname(msg
, msgsoaname
, DNS_SECTION_AUTHORITY
);
1073 } else if (xfr
->reqtype
== dns_rdatatype_soa
)
1074 CHECK(dns_db_getsoaserial(xfr
->db
, NULL
,
1075 &xfr
->ixfr
.request_serial
));
1077 xfr
->checkid
= ISC_TRUE
;
1082 isc_time_now(&xfr
->start
);
1084 if (xfr
->tsigctx
!= NULL
)
1085 dst_context_destroy(&xfr
->tsigctx
);
1087 CHECK(render(msg
, xfr
->mctx
, &xfr
->qbuffer
));
1090 * Free the last tsig, if there is one.
1092 if (xfr
->lasttsig
!= NULL
)
1093 isc_buffer_free(&xfr
->lasttsig
);
1096 * Save the query TSIG and don't let message_destroy free it.
1098 CHECK(dns_message_getquerytsig(msg
, xfr
->mctx
, &xfr
->lasttsig
));
1100 isc_buffer_usedregion(&xfr
->qbuffer
, ®ion
);
1101 INSIST(region
.length
<= 65535);
1103 length
[0] = region
.length
>> 8;
1104 length
[1] = region
.length
& 0xFF;
1105 lregion
.base
= length
;
1107 CHECK(isc_socket_send(xfr
->socket
, &lregion
, xfr
->task
,
1108 xfrin_sendlen_done
, xfr
));
1113 dns_message_puttempname(msg
, &qname
);
1114 if (qrdataset
!= NULL
)
1115 dns_message_puttemprdataset(msg
, &qrdataset
);
1117 dns_message_destroy(&msg
);
1118 if (soatuple
!= NULL
)
1119 dns_difftuple_free(&soatuple
);
1121 dns_db_closeversion(xfr
->db
, &ver
, ISC_FALSE
);
1125 /* XXX there should be library support for sending DNS TCP messages */
1128 xfrin_sendlen_done(isc_task_t
*task
, isc_event_t
*event
) {
1129 isc_socketevent_t
*sev
= (isc_socketevent_t
*) event
;
1130 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1131 isc_result_t evresult
= sev
->result
;
1132 isc_result_t result
;
1133 isc_region_t region
;
1135 REQUIRE(VALID_XFRIN(xfr
));
1139 INSIST(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1140 isc_event_free(&event
);
1143 if (xfr
->shuttingdown
) {
1148 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "sent request length prefix");
1151 isc_buffer_usedregion(&xfr
->qbuffer
, ®ion
);
1152 CHECK(isc_socket_send(xfr
->socket
, ®ion
, xfr
->task
,
1153 xfrin_send_done
, xfr
));
1156 if (result
!= ISC_R_SUCCESS
)
1157 xfrin_fail(xfr
, result
, "failed sending request length prefix");
1162 xfrin_send_done(isc_task_t
*task
, isc_event_t
*event
) {
1163 isc_socketevent_t
*sev
= (isc_socketevent_t
*) event
;
1164 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1165 isc_result_t result
;
1167 REQUIRE(VALID_XFRIN(xfr
));
1171 INSIST(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1174 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "sent request data");
1177 CHECK(dns_tcpmsg_readmessage(&xfr
->tcpmsg
, xfr
->task
,
1178 xfrin_recv_done
, xfr
));
1181 isc_event_free(&event
);
1182 if (result
!= ISC_R_SUCCESS
)
1183 xfrin_fail(xfr
, result
, "failed sending request data");
1188 xfrin_recv_done(isc_task_t
*task
, isc_event_t
*ev
) {
1189 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) ev
->ev_arg
;
1190 isc_result_t result
;
1191 dns_message_t
*msg
= NULL
;
1193 dns_tcpmsg_t
*tcpmsg
;
1194 dns_name_t
*tsigowner
= NULL
;
1196 REQUIRE(VALID_XFRIN(xfr
));
1200 INSIST(ev
->ev_type
== DNS_EVENT_TCPMSG
);
1201 tcpmsg
= ev
->ev_sender
;
1202 isc_event_free(&ev
);
1205 if (xfr
->shuttingdown
) {
1210 CHECK(tcpmsg
->result
);
1212 xfrin_log(xfr
, ISC_LOG_DEBUG(7), "received %u bytes",
1213 tcpmsg
->buffer
.used
);
1215 CHECK(isc_timer_touch(xfr
->timer
));
1217 CHECK(dns_message_create(xfr
->mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
));
1219 CHECK(dns_message_settsigkey(msg
, xfr
->tsigkey
));
1220 CHECK(dns_message_setquerytsig(msg
, xfr
->lasttsig
));
1222 msg
->tsigctx
= xfr
->tsigctx
;
1223 xfr
->tsigctx
= NULL
;
1226 msg
->tcp_continuation
= 1;
1228 result
= dns_message_parse(msg
, &tcpmsg
->buffer
,
1229 DNS_MESSAGEPARSE_PRESERVEORDER
);
1231 if (result
!= ISC_R_SUCCESS
|| msg
->rcode
!= dns_rcode_noerror
||
1232 (xfr
->checkid
&& msg
->id
!= xfr
->id
)) {
1233 if (result
== ISC_R_SUCCESS
)
1234 result
= ISC_RESULTCLASS_DNSRCODE
+ msg
->rcode
; /*XXX*/
1235 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_NOERROR
)
1236 result
= DNS_R_UNEXPECTEDID
;
1237 if (xfr
->reqtype
== dns_rdatatype_axfr
||
1238 xfr
->reqtype
== dns_rdatatype_soa
)
1240 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1241 isc_result_totext(result
));
1243 dns_message_destroy(&msg
);
1245 xfr
->reqtype
= dns_rdatatype_soa
;
1246 xfr
->state
= XFRST_SOAQUERY
;
1247 (void)xfrin_start(xfr
);
1252 * Does the server know about IXFR? If it doesn't we will get
1253 * a message with a empty answer section or a potentially a CNAME /
1254 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1255 * if the first RR in the answer section is not a SOA record.
1257 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
1258 xfr
->state
== XFRST_INITIALSOA
&&
1259 msg
->counts
[DNS_SECTION_ANSWER
] == 0) {
1260 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
1261 "empty answer section, retrying with AXFR");
1265 if (xfr
->reqtype
== dns_rdatatype_soa
&&
1266 (msg
->flags
& DNS_MESSAGEFLAG_AA
) == 0) {
1267 FAIL(DNS_R_NOTAUTHORITATIVE
);
1271 result
= dns_message_checksig(msg
, dns_zone_getview(xfr
->zone
));
1272 if (result
!= ISC_R_SUCCESS
) {
1273 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1274 isc_result_totext(result
));
1278 for (result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
1279 result
== ISC_R_SUCCESS
;
1280 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
))
1282 dns_rdataset_t
*rds
;
1285 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
1286 for (rds
= ISC_LIST_HEAD(name
->list
);
1288 rds
= ISC_LIST_NEXT(rds
, link
))
1290 for (result
= dns_rdataset_first(rds
);
1291 result
== ISC_R_SUCCESS
;
1292 result
= dns_rdataset_next(rds
))
1294 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1295 dns_rdataset_current(rds
, &rdata
);
1296 CHECK(xfr_rr(xfr
, name
, rds
->ttl
, &rdata
));
1300 if (result
!= ISC_R_NOMORE
)
1303 if (dns_message_gettsig(msg
, &tsigowner
) != NULL
) {
1305 * Reset the counter.
1310 * Free the last tsig, if there is one.
1312 if (xfr
->lasttsig
!= NULL
)
1313 isc_buffer_free(&xfr
->lasttsig
);
1316 * Update the last tsig pointer.
1318 CHECK(dns_message_getquerytsig(msg
, xfr
->mctx
,
1321 } else if (dns_message_gettsigkey(msg
) != NULL
) {
1323 if (xfr
->sincetsig
> 100 ||
1324 xfr
->nmsg
== 0 || xfr
->state
== XFRST_END
)
1326 result
= DNS_R_EXPECTEDTSIG
;
1332 * Update the number of messages received.
1337 * Update the number of bytes received.
1339 xfr
->nbytes
+= tcpmsg
->buffer
.used
;
1342 * Take the context back.
1344 INSIST(xfr
->tsigctx
== NULL
);
1345 xfr
->tsigctx
= msg
->tsigctx
;
1346 msg
->tsigctx
= NULL
;
1348 dns_message_destroy(&msg
);
1350 if (xfr
->state
== XFRST_GOTSOA
) {
1351 xfr
->reqtype
= dns_rdatatype_axfr
;
1352 xfr
->state
= XFRST_INITIALSOA
;
1353 CHECK(xfrin_send_request(xfr
));
1354 } else if (xfr
->state
== XFRST_END
) {
1356 * Close the journal.
1358 if (xfr
->ixfr
.journal
!= NULL
)
1359 dns_journal_destroy(&xfr
->ixfr
.journal
);
1361 * Inform the caller we succeeded.
1363 if (xfr
->done
!= NULL
) {
1364 (xfr
->done
)(xfr
->zone
, ISC_R_SUCCESS
);
1368 * We should have no outstanding events at this
1369 * point, thus maybe_free() should succeed.
1371 xfr
->shuttingdown
= ISC_TRUE
;
1375 * Read the next message.
1377 CHECK(dns_tcpmsg_readmessage(&xfr
->tcpmsg
, xfr
->task
,
1378 xfrin_recv_done
, xfr
));
1385 dns_message_destroy(&msg
);
1386 if (result
!= ISC_R_SUCCESS
)
1387 xfrin_fail(xfr
, result
, "failed while receiving responses");
1391 xfrin_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1392 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1394 REQUIRE(VALID_XFRIN(xfr
));
1398 isc_event_free(&event
);
1400 * This will log "giving up: timeout".
1402 xfrin_fail(xfr
, ISC_R_TIMEDOUT
, "giving up");
1406 maybe_free(dns_xfrin_ctx_t
*xfr
) {
1408 isc_uint64_t persec
;
1410 REQUIRE(VALID_XFRIN(xfr
));
1412 if (! xfr
->shuttingdown
|| xfr
->refcount
!= 0 ||
1413 xfr
->connects
!= 0 || xfr
->sends
!= 0 ||
1418 * Calculate the length of time the transfer took,
1419 * and print a log message with the bytes and rate.
1421 isc_time_now(&xfr
->end
);
1422 msecs
= isc_time_microdiff(&xfr
->end
, &xfr
->start
) / 1000;
1425 persec
= (xfr
->nbytes
* 1000) / msecs
;
1426 xfrin_log(xfr
, ISC_LOG_INFO
,
1427 "Transfer completed: %d messages, %d records, "
1428 "%" ISC_PRINT_QUADFORMAT
"u bytes, "
1429 "%u.%03u secs (%u bytes/sec)",
1430 xfr
->nmsg
, xfr
->nrecs
, xfr
->nbytes
,
1431 (unsigned int) (msecs
/ 1000), (unsigned int) (msecs
% 1000),
1432 (unsigned int) persec
);
1434 if (xfr
->socket
!= NULL
)
1435 isc_socket_detach(&xfr
->socket
);
1437 if (xfr
->timer
!= NULL
)
1438 isc_timer_detach(&xfr
->timer
);
1440 if (xfr
->task
!= NULL
)
1441 isc_task_detach(&xfr
->task
);
1443 if (xfr
->tsigkey
!= NULL
)
1444 dns_tsigkey_detach(&xfr
->tsigkey
);
1446 if (xfr
->lasttsig
!= NULL
)
1447 isc_buffer_free(&xfr
->lasttsig
);
1449 dns_diff_clear(&xfr
->diff
);
1451 if (xfr
->ixfr
.journal
!= NULL
)
1452 dns_journal_destroy(&xfr
->ixfr
.journal
);
1454 if (xfr
->axfr
.add_private
!= NULL
)
1455 (void)dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
);
1457 if (xfr
->tcpmsg_valid
)
1458 dns_tcpmsg_invalidate(&xfr
->tcpmsg
);
1460 if (xfr
->tsigctx
!= NULL
)
1461 dst_context_destroy(&xfr
->tsigctx
);
1463 if ((xfr
->name
.attributes
& DNS_NAMEATTR_DYNAMIC
) != 0)
1464 dns_name_free(&xfr
->name
, xfr
->mctx
);
1466 if (xfr
->ver
!= NULL
)
1467 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_FALSE
);
1469 if (xfr
->db
!= NULL
)
1470 dns_db_detach(&xfr
->db
);
1472 if (xfr
->zone
!= NULL
)
1473 dns_zone_idetach(&xfr
->zone
);
1475 isc_mem_put(xfr
->mctx
, xfr
, sizeof(*xfr
));
1479 * Log incoming zone transfer messages in a format like
1480 * transfer of <zone> from <address>: <message>
1483 xfrin_logv(int level
, const char *zonetext
, isc_sockaddr_t
*masteraddr
,
1484 const char *fmt
, va_list ap
)
1486 char mastertext
[ISC_SOCKADDR_FORMATSIZE
];
1489 isc_sockaddr_format(masteraddr
, mastertext
, sizeof(mastertext
));
1490 vsnprintf(msgtext
, sizeof(msgtext
), fmt
, ap
);
1492 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_XFER_IN
,
1493 DNS_LOGMODULE_XFER_IN
, level
,
1494 "transfer of '%s' from %s: %s",
1495 zonetext
, mastertext
, msgtext
);
1499 * Logging function for use when a xfrin_ctx_t has not yet been created.
1503 xfrin_log1(int level
, const char *zonetext
, isc_sockaddr_t
*masteraddr
,
1504 const char *fmt
, ...)
1508 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
1512 xfrin_logv(level
, zonetext
, masteraddr
, fmt
, ap
);
1517 * Logging function for use when there is a xfrin_ctx_t.
1521 xfrin_log(dns_xfrin_ctx_t
*xfr
, int level
, const char *fmt
, ...)
1524 char zonetext
[DNS_NAME_MAXTEXT
+32];
1526 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
1529 dns_zone_name(xfr
->zone
, zonetext
, sizeof(zonetext
));
1532 xfrin_logv(level
, zonetext
, &xfr
->masteraddr
, fmt
, ap
);