2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 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.5 2004/03/09 06:11:11 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.
89 * Incoming zone transfer context.
92 struct dns_xfrin_ctx
{
101 isc_socketmgr_t
*socketmgr
;
103 int connects
; /* Connect in progress */
104 int sends
; /* Send in progress */
105 int recvs
; /* Receive in progress */
106 isc_boolean_t shuttingdown
;
108 dns_name_t name
; /* Name of zone to transfer */
109 dns_rdataclass_t rdclass
;
111 isc_boolean_t checkid
;
115 * Requested transfer type (dns_rdatatype_axfr or
116 * dns_rdatatype_ixfr). The actual transfer type
117 * may differ due to IXFR->AXFR fallback.
119 dns_rdatatype_t reqtype
;
121 isc_sockaddr_t masteraddr
;
122 isc_sockaddr_t sourceaddr
;
123 isc_socket_t
*socket
;
125 /* Buffer for IXFR/AXFR request message */
126 isc_buffer_t qbuffer
;
127 unsigned char qbuffer_data
[512];
129 /* Incoming reply TCP message */
131 isc_boolean_t tcpmsg_valid
;
134 dns_dbversion_t
*ver
;
135 dns_diff_t diff
; /* Pending database changes */
136 int difflen
; /* Number of pending tuples */
139 isc_uint32_t end_serial
;
140 isc_boolean_t is_ixfr
;
142 unsigned int nmsg
; /* Number of messages recvd */
144 dns_tsigkey_t
*tsigkey
; /* Key used to create TSIG */
145 isc_buffer_t
*lasttsig
; /* The last TSIG */
146 dst_context_t
*tsigctx
; /* TSIG verification context */
147 unsigned int sincetsig
; /* recvd since the last TSIG */
148 dns_xfrindone_t done
;
151 * AXFR- and IXFR-specific data. Only one is used at a time
152 * according to the is_ixfr flag, so this could be a union,
153 * but keeping them separate makes it a bit simpler to clean
154 * things up when destroying the context.
157 dns_addrdatasetfunc_t add_func
;
158 dns_dbload_t
*add_private
;
162 isc_uint32_t request_serial
;
163 isc_uint32_t end_serial
;
164 dns_journal_t
*journal
;
169 #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
170 #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
172 /**************************************************************************/
174 * Forward declarations.
178 xfrin_create(isc_mem_t
*mctx
,
182 isc_timermgr_t
*timermgr
,
183 isc_socketmgr_t
*socketmgr
,
184 dns_name_t
*zonename
,
185 dns_rdataclass_t rdclass
,
186 dns_rdatatype_t reqtype
,
187 isc_sockaddr_t
*masteraddr
,
188 dns_tsigkey_t
*tsigkey
,
189 dns_xfrin_ctx_t
**xfrp
);
191 static isc_result_t
axfr_init(dns_xfrin_ctx_t
*xfr
);
192 static isc_result_t
axfr_makedb(dns_xfrin_ctx_t
*xfr
, dns_db_t
**dbp
);
193 static isc_result_t
axfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
194 dns_name_t
*name
, dns_ttl_t ttl
,
196 static isc_result_t
axfr_apply(dns_xfrin_ctx_t
*xfr
);
197 static isc_result_t
axfr_commit(dns_xfrin_ctx_t
*xfr
);
199 static isc_result_t
ixfr_init(dns_xfrin_ctx_t
*xfr
);
200 static isc_result_t
ixfr_apply(dns_xfrin_ctx_t
*xfr
);
201 static isc_result_t
ixfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
202 dns_name_t
*name
, dns_ttl_t ttl
,
204 static isc_result_t
ixfr_commit(dns_xfrin_ctx_t
*xfr
);
206 static isc_result_t
xfr_rr(dns_xfrin_ctx_t
*xfr
, dns_name_t
*name
,
207 isc_uint32_t ttl
, dns_rdata_t
*rdata
);
209 static isc_result_t
xfrin_start(dns_xfrin_ctx_t
*xfr
);
211 static void xfrin_connect_done(isc_task_t
*task
, isc_event_t
*event
);
212 static isc_result_t
xfrin_send_request(dns_xfrin_ctx_t
*xfr
);
213 static void xfrin_send_done(isc_task_t
*task
, isc_event_t
*event
);
214 static void xfrin_sendlen_done(isc_task_t
*task
, isc_event_t
*event
);
215 static void xfrin_recv_done(isc_task_t
*task
, isc_event_t
*event
);
216 static void xfrin_timeout(isc_task_t
*task
, isc_event_t
*event
);
218 static void maybe_free(dns_xfrin_ctx_t
*xfr
);
221 xfrin_fail(dns_xfrin_ctx_t
*xfr
, isc_result_t result
, const char *msg
);
223 render(dns_message_t
*msg
, isc_mem_t
*mctx
, isc_buffer_t
*buf
);
226 xfrin_logv(int level
, dns_name_t
*zonename
, dns_rdataclass_t rdclass
,
227 isc_sockaddr_t
*masteraddr
, const char *fmt
, va_list ap
)
228 ISC_FORMAT_PRINTF(5, 0);
231 xfrin_log1(int level
, dns_name_t
*zonename
, dns_rdataclass_t rdclass
,
232 isc_sockaddr_t
*masteraddr
, const char *fmt
, ...)
233 ISC_FORMAT_PRINTF(5, 6);
236 xfrin_log(dns_xfrin_ctx_t
*xfr
, unsigned int level
, const char *fmt
, ...)
237 ISC_FORMAT_PRINTF(3, 4);
239 /**************************************************************************/
245 axfr_init(dns_xfrin_ctx_t
*xfr
) {
248 xfr
->is_ixfr
= ISC_FALSE
;
251 dns_db_detach(&xfr
->db
);
253 CHECK(axfr_makedb(xfr
, &xfr
->db
));
254 CHECK(dns_db_beginload(xfr
->db
, &xfr
->axfr
.add_func
,
255 &xfr
->axfr
.add_private
));
256 result
= ISC_R_SUCCESS
;
262 axfr_makedb(dns_xfrin_ctx_t
*xfr
, dns_db_t
**dbp
) {
263 return (dns_db_create(xfr
->mctx
, /* XXX */
264 "rbt", /* XXX guess */
268 0, NULL
, /* XXX guess */
273 axfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
274 dns_name_t
*name
, dns_ttl_t ttl
, dns_rdata_t
*rdata
)
278 dns_difftuple_t
*tuple
= NULL
;
279 CHECK(dns_difftuple_create(xfr
->diff
.mctx
, op
,
280 name
, ttl
, rdata
, &tuple
));
281 dns_diff_append(&xfr
->diff
, &tuple
);
282 if (++xfr
->difflen
> 100)
283 CHECK(axfr_apply(xfr
));
284 result
= ISC_R_SUCCESS
;
290 * Store a set of AXFR RRs in the database.
293 axfr_apply(dns_xfrin_ctx_t
*xfr
) {
296 CHECK(dns_diff_load(&xfr
->diff
,
297 xfr
->axfr
.add_func
, xfr
->axfr
.add_private
));
299 dns_diff_clear(&xfr
->diff
);
300 result
= ISC_R_SUCCESS
;
306 axfr_commit(dns_xfrin_ctx_t
*xfr
) {
309 CHECK(axfr_apply(xfr
));
310 CHECK(dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
));
311 CHECK(dns_zone_replacedb(xfr
->zone
, xfr
->db
, ISC_TRUE
));
313 result
= ISC_R_SUCCESS
;
318 /**************************************************************************/
324 ixfr_init(dns_xfrin_ctx_t
*xfr
) {
328 if (xfr
->reqtype
!= dns_rdatatype_ixfr
) {
329 xfrin_log(xfr
, ISC_LOG_ERROR
,
330 "got incremental response to AXFR request");
331 return (DNS_R_FORMERR
);
334 xfr
->is_ixfr
= ISC_TRUE
;
335 INSIST(xfr
->db
!= NULL
);
338 journalfile
= dns_zone_getjournal(xfr
->zone
);
339 if (journalfile
!= NULL
)
340 CHECK(dns_journal_open(xfr
->mctx
, journalfile
,
341 ISC_TRUE
, &xfr
->ixfr
.journal
));
343 result
= ISC_R_SUCCESS
;
349 ixfr_putdata(dns_xfrin_ctx_t
*xfr
, dns_diffop_t op
,
350 dns_name_t
*name
, dns_ttl_t ttl
, dns_rdata_t
*rdata
)
354 dns_difftuple_t
*tuple
= NULL
;
355 CHECK(dns_difftuple_create(xfr
->diff
.mctx
, op
,
356 name
, ttl
, rdata
, &tuple
));
357 dns_diff_append(&xfr
->diff
, &tuple
);
358 if (++xfr
->difflen
> 100)
359 CHECK(ixfr_apply(xfr
));
360 result
= ISC_R_SUCCESS
;
366 * Apply a set of IXFR changes to the database.
369 ixfr_apply(dns_xfrin_ctx_t
*xfr
) {
372 if (xfr
->ver
== NULL
) {
373 CHECK(dns_db_newversion(xfr
->db
, &xfr
->ver
));
374 if (xfr
->ixfr
.journal
!= NULL
)
375 CHECK(dns_journal_begin_transaction(xfr
->ixfr
.journal
));
377 CHECK(dns_diff_apply(&xfr
->diff
, xfr
->db
, xfr
->ver
));
378 if (xfr
->ixfr
.journal
!= NULL
)
379 dns_journal_writediff(xfr
->ixfr
.journal
, &xfr
->diff
);
380 dns_diff_clear(&xfr
->diff
);
382 result
= ISC_R_SUCCESS
;
388 ixfr_commit(dns_xfrin_ctx_t
*xfr
) {
391 CHECK(ixfr_apply(xfr
));
392 if (xfr
->ver
!= NULL
) {
393 /* XXX enter ready-to-commit state here */
394 if (xfr
->ixfr
.journal
!= NULL
)
395 CHECK(dns_journal_commit(xfr
->ixfr
.journal
));
396 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_TRUE
);
397 dns_zone_markdirty(xfr
->zone
);
399 result
= ISC_R_SUCCESS
;
404 /**************************************************************************/
406 * Common AXFR/IXFR protocol code
410 * Handle a single incoming resource record according to the current
414 xfr_rr(dns_xfrin_ctx_t
*xfr
, dns_name_t
*name
, isc_uint32_t ttl
,
420 switch (xfr
->state
) {
422 if (rdata
->type
!= dns_rdatatype_soa
) {
423 xfrin_log(xfr
, ISC_LOG_ERROR
,
424 "non-SOA response to SOA query");
427 xfr
->end_serial
= dns_soa_getserial(rdata
);
428 if (!DNS_SERIAL_GT(xfr
->end_serial
,
429 xfr
->ixfr
.request_serial
) &&
430 !dns_zone_isforced(xfr
->zone
)) {
431 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
432 "requested serial %u, "
433 "master has %u, not updating",
434 xfr
->ixfr
.request_serial
, xfr
->end_serial
);
435 FAIL(DNS_R_UPTODATE
);
437 xfr
->state
= XFRST_GOTSOA
;
442 * Skip other records in the answer section.
446 case XFRST_INITIALSOA
:
447 if (rdata
->type
!= dns_rdatatype_soa
) {
448 xfrin_log(xfr
, ISC_LOG_ERROR
,
449 "first RR in zone transfer must be SOA");
453 * Remember the serial number in the intial SOA.
454 * We need it to recognize the end of an IXFR.
456 xfr
->end_serial
= dns_soa_getserial(rdata
);
457 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
458 ! DNS_SERIAL_GT(xfr
->end_serial
, xfr
->ixfr
.request_serial
)
459 && !dns_zone_isforced(xfr
->zone
))
462 * This must be the single SOA record that is
463 * sent when the current version on the master
464 * is not newer than the version in the request.
466 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
467 "requested serial %u, "
468 "master has %u, not updating",
469 xfr
->ixfr
.request_serial
, xfr
->end_serial
);
470 FAIL(DNS_R_UPTODATE
);
472 if (xfr
->reqtype
== dns_rdatatype_axfr
)
473 xfr
->checkid
= ISC_FALSE
;
474 xfr
->state
= XFRST_FIRSTDATA
;
477 case XFRST_FIRSTDATA
:
479 * If the transfer begins with one SOA record, it is an AXFR,
480 * if it begins with two SOAs, it is an IXFR.
482 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
483 rdata
->type
== dns_rdatatype_soa
&&
484 xfr
->ixfr
.request_serial
== dns_soa_getserial(rdata
)) {
485 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
486 "got incremental response");
487 CHECK(ixfr_init(xfr
));
488 xfr
->state
= XFRST_IXFR_DELSOA
;
490 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
491 "got nonincremental response");
492 CHECK(axfr_init(xfr
));
493 xfr
->state
= XFRST_AXFR
;
497 case XFRST_IXFR_DELSOA
:
498 INSIST(rdata
->type
== dns_rdatatype_soa
);
499 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_DEL
, name
, ttl
, rdata
));
500 xfr
->state
= XFRST_IXFR_DEL
;
504 if (rdata
->type
== dns_rdatatype_soa
) {
505 isc_uint32_t soa_serial
= dns_soa_getserial(rdata
);
506 xfr
->state
= XFRST_IXFR_ADDSOA
;
507 xfr
->ixfr
.end_serial
= soa_serial
;
510 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_DEL
, name
, ttl
, rdata
));
513 case XFRST_IXFR_ADDSOA
:
514 INSIST(rdata
->type
== dns_rdatatype_soa
);
515 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
516 xfr
->state
= XFRST_IXFR_ADD
;
520 if (rdata
->type
== dns_rdatatype_soa
) {
521 isc_uint32_t soa_serial
= dns_soa_getserial(rdata
);
522 CHECK(ixfr_commit(xfr
));
523 if (soa_serial
== xfr
->end_serial
) {
524 xfr
->state
= XFRST_END
;
527 xfr
->state
= XFRST_IXFR_DELSOA
;
531 CHECK(ixfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
536 * Old BINDs sent cross class A records for non IN classes.
538 if (rdata
->type
== dns_rdatatype_a
&&
539 rdata
->rdclass
!= xfr
->rdclass
&&
540 xfr
->rdclass
!= dns_rdataclass_in
)
542 CHECK(axfr_putdata(xfr
, DNS_DIFFOP_ADD
, name
, ttl
, rdata
));
543 if (rdata
->type
== dns_rdatatype_soa
) {
544 CHECK(axfr_commit(xfr
));
545 xfr
->state
= XFRST_END
;
550 FAIL(DNS_R_EXTRADATA
);
555 result
= ISC_R_SUCCESS
;
561 dns_xfrin_create(dns_zone_t
*zone
, dns_rdatatype_t xfrtype
,
562 isc_sockaddr_t
*masteraddr
, dns_tsigkey_t
*tsigkey
,
563 isc_mem_t
*mctx
, isc_timermgr_t
*timermgr
,
564 isc_socketmgr_t
*socketmgr
, isc_task_t
*task
,
565 dns_xfrindone_t done
, dns_xfrin_ctx_t
**xfrp
)
567 dns_name_t
*zonename
= dns_zone_getorigin(zone
);
568 dns_xfrin_ctx_t
*xfr
;
572 REQUIRE(xfrp
!= NULL
&& *xfrp
== NULL
);
574 (void)dns_zone_getdb(zone
, &db
);
576 CHECK(xfrin_create(mctx
, zone
, db
, task
, timermgr
, socketmgr
, zonename
,
577 dns_zone_getclass(zone
), xfrtype
, masteraddr
,
580 CHECK(xfrin_start(xfr
));
589 if (result
!= ISC_R_SUCCESS
)
590 xfrin_log1(ISC_LOG_ERROR
, zonename
, dns_zone_getclass(zone
),
591 masteraddr
, "zone transfer setup failed");
596 dns_xfrin_shutdown(dns_xfrin_ctx_t
*xfr
) {
597 if (! xfr
->shuttingdown
)
598 xfrin_fail(xfr
, ISC_R_CANCELED
, "shut down");
602 dns_xfrin_attach(dns_xfrin_ctx_t
*source
, dns_xfrin_ctx_t
**target
) {
603 REQUIRE(target
!= NULL
&& *target
== NULL
);
609 dns_xfrin_detach(dns_xfrin_ctx_t
**xfrp
) {
610 dns_xfrin_ctx_t
*xfr
= *xfrp
;
611 INSIST(xfr
->refcount
> 0);
618 xfrin_cancelio(dns_xfrin_ctx_t
*xfr
) {
619 if (xfr
->connects
> 0) {
620 isc_socket_cancel(xfr
->socket
, xfr
->task
,
621 ISC_SOCKCANCEL_CONNECT
);
622 } else if (xfr
->recvs
> 0) {
623 dns_tcpmsg_cancelread(&xfr
->tcpmsg
);
624 } else if (xfr
->sends
> 0) {
625 isc_socket_cancel(xfr
->socket
, xfr
->task
,
626 ISC_SOCKCANCEL_SEND
);
631 xfrin_reset(dns_xfrin_ctx_t
*xfr
) {
632 REQUIRE(VALID_XFRIN(xfr
));
634 xfrin_log(xfr
, ISC_LOG_INFO
, "resetting");
638 if (xfr
->socket
!= NULL
)
639 isc_socket_detach(&xfr
->socket
);
641 if (xfr
->lasttsig
!= NULL
)
642 isc_buffer_free(&xfr
->lasttsig
);
644 dns_diff_clear(&xfr
->diff
);
647 if (xfr
->ixfr
.journal
!= NULL
)
648 dns_journal_destroy(&xfr
->ixfr
.journal
);
650 if (xfr
->axfr
.add_private
!= NULL
) {
651 (void)dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
);
652 xfr
->axfr
.add_func
= NULL
;
655 if (xfr
->tcpmsg_valid
) {
656 dns_tcpmsg_invalidate(&xfr
->tcpmsg
);
657 xfr
->tcpmsg_valid
= ISC_FALSE
;
660 if (xfr
->ver
!= NULL
)
661 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_FALSE
);
666 xfrin_fail(dns_xfrin_ctx_t
*xfr
, isc_result_t result
, const char *msg
) {
667 if (result
!= DNS_R_UPTODATE
) {
668 xfrin_log(xfr
, ISC_LOG_ERROR
, "%s: %s",
669 msg
, isc_result_totext(result
));
671 /* Pass special result code to force AXFR retry */
672 result
= DNS_R_BADIXFR
;
675 if (xfr
->done
!= NULL
) {
676 (xfr
->done
)(xfr
->zone
, result
);
679 xfr
->shuttingdown
= ISC_TRUE
;
684 xfrin_create(isc_mem_t
*mctx
,
688 isc_timermgr_t
*timermgr
,
689 isc_socketmgr_t
*socketmgr
,
690 dns_name_t
*zonename
,
691 dns_rdataclass_t rdclass
,
692 dns_rdatatype_t reqtype
,
693 isc_sockaddr_t
*masteraddr
,
694 dns_tsigkey_t
*tsigkey
,
695 dns_xfrin_ctx_t
**xfrp
)
697 dns_xfrin_ctx_t
*xfr
= NULL
;
701 xfr
= isc_mem_get(mctx
, sizeof(*xfr
));
703 return (ISC_R_NOMEMORY
);
707 dns_zone_iattach(zone
, &xfr
->zone
);
709 isc_task_attach(task
, &xfr
->task
);
711 xfr
->socketmgr
= socketmgr
;
717 xfr
->shuttingdown
= ISC_FALSE
;
719 dns_name_init(&xfr
->name
, NULL
);
720 xfr
->rdclass
= rdclass
;
721 isc_random_get(&tmp
);
722 xfr
->checkid
= ISC_TRUE
;
723 xfr
->id
= (isc_uint16_t
)(tmp
& 0xffff);
724 xfr
->reqtype
= reqtype
;
731 xfr
->tcpmsg_valid
= ISC_FALSE
;
735 dns_db_attach(db
, &xfr
->db
);
737 dns_diff_init(xfr
->mctx
, &xfr
->diff
);
740 xfr
->state
= XFRST_INITIALSOA
;
747 dns_tsigkey_attach(tsigkey
, &xfr
->tsigkey
);
748 xfr
->lasttsig
= NULL
;
751 xfr
->is_ixfr
= ISC_FALSE
;
753 /* ixfr.request_serial */
754 /* ixfr.end_serial */
755 xfr
->ixfr
.journal
= NULL
;
757 xfr
->axfr
.add_func
= NULL
;
758 xfr
->axfr
.add_private
= NULL
;
760 CHECK(dns_name_dup(zonename
, mctx
, &xfr
->name
));
762 CHECK(isc_timer_create(timermgr
, isc_timertype_inactive
, NULL
, NULL
,
763 task
, xfrin_timeout
, xfr
, &xfr
->timer
));
764 CHECK(dns_timer_setidle(xfr
->timer
,
765 dns_zone_getmaxxfrin(xfr
->zone
),
766 dns_zone_getidlein(xfr
->zone
),
769 xfr
->masteraddr
= *masteraddr
;
771 switch (isc_sockaddr_pf(masteraddr
)) {
773 xfr
->sourceaddr
= *dns_zone_getxfrsource4(zone
);
776 xfr
->sourceaddr
= *dns_zone_getxfrsource6(zone
);
781 isc_sockaddr_setport(&xfr
->sourceaddr
, 0);
783 isc_buffer_init(&xfr
->qbuffer
, xfr
->qbuffer_data
,
784 sizeof(xfr
->qbuffer_data
));
786 xfr
->magic
= XFRIN_MAGIC
;
788 return (ISC_R_SUCCESS
);
791 xfrin_fail(xfr
, result
, "failed creating transfer context");
796 xfrin_start(dns_xfrin_ctx_t
*xfr
) {
798 CHECK(isc_socket_create(xfr
->socketmgr
,
799 isc_sockaddr_pf(&xfr
->sourceaddr
),
802 CHECK(isc_socket_bind(xfr
->socket
, &xfr
->sourceaddr
));
803 CHECK(isc_socket_connect(xfr
->socket
, &xfr
->masteraddr
, xfr
->task
,
804 xfrin_connect_done
, xfr
));
806 return (ISC_R_SUCCESS
);
808 xfrin_fail(xfr
, result
, "failed setting up socket");
812 /* XXX the resolver could use this, too */
815 render(dns_message_t
*msg
, isc_mem_t
*mctx
, isc_buffer_t
*buf
) {
817 isc_boolean_t cleanup_cctx
= ISC_FALSE
;
820 CHECK(dns_compress_init(&cctx
, -1, mctx
));
821 cleanup_cctx
= ISC_TRUE
;
822 CHECK(dns_message_renderbegin(msg
, &cctx
, buf
));
823 CHECK(dns_message_rendersection(msg
, DNS_SECTION_QUESTION
, 0));
824 CHECK(dns_message_rendersection(msg
, DNS_SECTION_ANSWER
, 0));
825 CHECK(dns_message_rendersection(msg
, DNS_SECTION_AUTHORITY
, 0));
826 CHECK(dns_message_rendersection(msg
, DNS_SECTION_ADDITIONAL
, 0));
827 CHECK(dns_message_renderend(msg
));
828 result
= ISC_R_SUCCESS
;
831 dns_compress_invalidate(&cctx
);
836 * A connection has been established.
839 xfrin_connect_done(isc_task_t
*task
, isc_event_t
*event
) {
840 isc_socket_connev_t
*cev
= (isc_socket_connev_t
*) event
;
841 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
842 isc_result_t evresult
= cev
->result
;
845 REQUIRE(VALID_XFRIN(xfr
));
849 INSIST(event
->ev_type
== ISC_SOCKEVENT_CONNECT
);
850 isc_event_free(&event
);
853 if (xfr
->shuttingdown
) {
859 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "connected");
861 dns_tcpmsg_init(xfr
->mctx
, xfr
->socket
, &xfr
->tcpmsg
);
862 xfr
->tcpmsg_valid
= ISC_TRUE
;
864 CHECK(xfrin_send_request(xfr
));
866 if (result
!= ISC_R_SUCCESS
)
867 xfrin_fail(xfr
, result
, "failed to connect");
871 * Convert a tuple into a dns_name_t suitable for inserting
872 * into the given dns_message_t.
875 tuple2msgname(dns_difftuple_t
*tuple
, dns_message_t
*msg
, dns_name_t
**target
)
878 dns_rdata_t
*rdata
= NULL
;
879 dns_rdatalist_t
*rdl
= NULL
;
880 dns_rdataset_t
*rds
= NULL
;
881 dns_name_t
*name
= NULL
;
883 REQUIRE(target
!= NULL
&& *target
== NULL
);
885 CHECK(dns_message_gettemprdata(msg
, &rdata
));
886 dns_rdata_init(rdata
);
887 dns_rdata_clone(&tuple
->rdata
, rdata
);
889 CHECK(dns_message_gettemprdatalist(msg
, &rdl
));
890 dns_rdatalist_init(rdl
);
891 rdl
->type
= tuple
->rdata
.type
;
892 rdl
->rdclass
= tuple
->rdata
.rdclass
;
893 rdl
->ttl
= tuple
->ttl
;
894 ISC_LIST_APPEND(rdl
->rdata
, rdata
, link
);
896 CHECK(dns_message_gettemprdataset(msg
, &rds
));
897 dns_rdataset_init(rds
);
898 CHECK(dns_rdatalist_tordataset(rdl
, rds
));
900 CHECK(dns_message_gettempname(msg
, &name
));
901 dns_name_init(name
, NULL
);
902 dns_name_clone(&tuple
->name
, name
);
903 ISC_LIST_APPEND(name
->list
, rds
, link
);
906 return (ISC_R_SUCCESS
);
911 dns_rdataset_disassociate(rds
);
912 dns_message_puttemprdataset(msg
, &rds
);
914 ISC_LIST_UNLINK(rdl
->rdata
, rdata
, link
);
915 dns_message_puttemprdatalist(msg
, &rdl
);
918 dns_message_puttemprdata(msg
, &rdata
);
925 * Build an *XFR request and send its length prefix.
928 xfrin_send_request(dns_xfrin_ctx_t
*xfr
) {
931 isc_region_t lregion
;
932 dns_rdataset_t
*qrdataset
= NULL
;
933 dns_message_t
*msg
= NULL
;
934 unsigned char length
[2];
935 dns_difftuple_t
*soatuple
= NULL
;
936 dns_name_t
*qname
= NULL
;
937 dns_dbversion_t
*ver
= NULL
;
938 dns_name_t
*msgsoaname
= NULL
;
940 /* Create the request message */
941 CHECK(dns_message_create(xfr
->mctx
, DNS_MESSAGE_INTENTRENDER
, &msg
));
942 CHECK(dns_message_settsigkey(msg
, xfr
->tsigkey
));
944 /* Create a name for the question section. */
945 CHECK(dns_message_gettempname(msg
, &qname
));
946 dns_name_init(qname
, NULL
);
947 dns_name_clone(&xfr
->name
, qname
);
949 /* Formulate the question and attach it to the question name. */
950 CHECK(dns_message_gettemprdataset(msg
, &qrdataset
));
951 dns_rdataset_init(qrdataset
);
952 dns_rdataset_makequestion(qrdataset
, xfr
->rdclass
, xfr
->reqtype
);
953 ISC_LIST_APPEND(qname
->list
, qrdataset
, link
);
956 dns_message_addname(msg
, qname
, DNS_SECTION_QUESTION
);
959 if (xfr
->reqtype
== dns_rdatatype_ixfr
) {
960 /* Get the SOA and add it to the authority section. */
961 /* XXX is using the current version the right thing? */
962 dns_db_currentversion(xfr
->db
, &ver
);
963 CHECK(dns_db_createsoatuple(xfr
->db
, ver
, xfr
->mctx
,
964 DNS_DIFFOP_EXISTS
, &soatuple
));
965 xfr
->ixfr
.request_serial
= dns_soa_getserial(&soatuple
->rdata
);
966 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
967 "requesting IXFR for serial %u",
968 xfr
->ixfr
.request_serial
);
970 CHECK(tuple2msgname(soatuple
, msg
, &msgsoaname
));
971 dns_message_addname(msg
, msgsoaname
, DNS_SECTION_AUTHORITY
);
974 xfr
->checkid
= ISC_TRUE
;
978 CHECK(render(msg
, xfr
->mctx
, &xfr
->qbuffer
));
981 * Free the last tsig, if there is one.
983 if (xfr
->lasttsig
!= NULL
)
984 isc_buffer_free(&xfr
->lasttsig
);
987 * Save the query TSIG and don't let message_destroy free it.
989 CHECK(dns_message_getquerytsig(msg
, xfr
->mctx
, &xfr
->lasttsig
));
991 isc_buffer_usedregion(&xfr
->qbuffer
, ®ion
);
992 INSIST(region
.length
<= 65535);
994 length
[0] = region
.length
>> 8;
995 length
[1] = region
.length
& 0xFF;
996 lregion
.base
= length
;
998 CHECK(isc_socket_send(xfr
->socket
, &lregion
, xfr
->task
,
999 xfrin_sendlen_done
, xfr
));
1004 dns_message_puttempname(msg
, &qname
);
1005 if (qrdataset
!= NULL
)
1006 dns_message_puttemprdataset(msg
, &qrdataset
);
1008 dns_message_destroy(&msg
);
1009 if (soatuple
!= NULL
)
1010 dns_difftuple_free(&soatuple
);
1012 dns_db_closeversion(xfr
->db
, &ver
, ISC_FALSE
);
1016 /* XXX there should be library support for sending DNS TCP messages */
1019 xfrin_sendlen_done(isc_task_t
*task
, isc_event_t
*event
) {
1020 isc_socketevent_t
*sev
= (isc_socketevent_t
*) event
;
1021 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1022 isc_result_t evresult
= sev
->result
;
1023 isc_result_t result
;
1024 isc_region_t region
;
1026 REQUIRE(VALID_XFRIN(xfr
));
1030 INSIST(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1031 isc_event_free(&event
);
1034 if (xfr
->shuttingdown
) {
1039 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "sent request length prefix");
1042 isc_buffer_usedregion(&xfr
->qbuffer
, ®ion
);
1043 CHECK(isc_socket_send(xfr
->socket
, ®ion
, xfr
->task
,
1044 xfrin_send_done
, xfr
));
1047 if (result
!= ISC_R_SUCCESS
)
1048 xfrin_fail(xfr
, result
, "failed sending request length prefix");
1053 xfrin_send_done(isc_task_t
*task
, isc_event_t
*event
) {
1054 isc_socketevent_t
*sev
= (isc_socketevent_t
*) event
;
1055 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1056 isc_result_t result
;
1058 REQUIRE(VALID_XFRIN(xfr
));
1062 INSIST(event
->ev_type
== ISC_SOCKEVENT_SENDDONE
);
1065 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "sent request data");
1068 CHECK(dns_tcpmsg_readmessage(&xfr
->tcpmsg
, xfr
->task
,
1069 xfrin_recv_done
, xfr
));
1072 isc_event_free(&event
);
1073 if (result
!= ISC_R_SUCCESS
)
1074 xfrin_fail(xfr
, result
, "failed sending request data");
1079 xfrin_recv_done(isc_task_t
*task
, isc_event_t
*ev
) {
1080 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) ev
->ev_arg
;
1081 isc_result_t result
;
1082 dns_message_t
*msg
= NULL
;
1084 dns_tcpmsg_t
*tcpmsg
;
1085 dns_name_t
*tsigowner
= NULL
;
1087 REQUIRE(VALID_XFRIN(xfr
));
1091 INSIST(ev
->ev_type
== DNS_EVENT_TCPMSG
);
1092 tcpmsg
= ev
->ev_sender
;
1093 isc_event_free(&ev
);
1096 if (xfr
->shuttingdown
) {
1101 CHECK(tcpmsg
->result
);
1103 xfrin_log(xfr
, ISC_LOG_DEBUG(7), "received %u bytes",
1104 tcpmsg
->buffer
.used
);
1106 CHECK(isc_timer_touch(xfr
->timer
));
1108 CHECK(dns_message_create(xfr
->mctx
, DNS_MESSAGE_INTENTPARSE
, &msg
));
1110 dns_message_settsigkey(msg
, xfr
->tsigkey
);
1111 dns_message_setquerytsig(msg
, xfr
->lasttsig
);
1112 msg
->tsigctx
= xfr
->tsigctx
;
1114 msg
->tcp_continuation
= 1;
1116 result
= dns_message_parse(msg
, &tcpmsg
->buffer
,
1117 DNS_MESSAGEPARSE_PRESERVEORDER
);
1119 if (result
!= ISC_R_SUCCESS
|| msg
->rcode
!= dns_rcode_noerror
||
1120 (xfr
->checkid
&& msg
->id
!= xfr
->id
)) {
1121 if (result
== ISC_R_SUCCESS
)
1122 result
= ISC_RESULTCLASS_DNSRCODE
+ msg
->rcode
; /*XXX*/
1123 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_NOERROR
)
1124 result
= DNS_R_UNEXPECTEDID
;
1125 if (xfr
->reqtype
== dns_rdatatype_axfr
||
1126 xfr
->reqtype
== dns_rdatatype_soa
)
1128 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1129 isc_result_totext(result
));
1131 dns_message_destroy(&msg
);
1133 xfr
->reqtype
= dns_rdatatype_soa
;
1134 xfr
->state
= XFRST_SOAQUERY
;
1140 * Does the server know about IXFR? If it doesn't we will get
1141 * a message with a empty answer section or a potentially a CNAME /
1142 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1143 * if the first RR in the answer section is not a SOA record.
1145 if (xfr
->reqtype
== dns_rdatatype_ixfr
&&
1146 xfr
->state
== XFRST_INITIALSOA
&&
1147 msg
->counts
[DNS_SECTION_ANSWER
] == 0) {
1148 xfrin_log(xfr
, ISC_LOG_DEBUG(3),
1149 "empty answer section, retrying with AXFR");
1154 result
= dns_message_checksig(msg
, dns_zone_getview(xfr
->zone
));
1155 if (result
!= ISC_R_SUCCESS
) {
1156 xfrin_log(xfr
, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1157 isc_result_totext(result
));
1161 for (result
= dns_message_firstname(msg
, DNS_SECTION_ANSWER
);
1162 result
== ISC_R_SUCCESS
;
1163 result
= dns_message_nextname(msg
, DNS_SECTION_ANSWER
))
1165 dns_rdataset_t
*rds
;
1168 dns_message_currentname(msg
, DNS_SECTION_ANSWER
, &name
);
1169 for (rds
= ISC_LIST_HEAD(name
->list
);
1171 rds
= ISC_LIST_NEXT(rds
, link
))
1173 for (result
= dns_rdataset_first(rds
);
1174 result
== ISC_R_SUCCESS
;
1175 result
= dns_rdataset_next(rds
))
1177 dns_rdata_t rdata
= DNS_RDATA_INIT
;
1178 dns_rdataset_current(rds
, &rdata
);
1179 CHECK(xfr_rr(xfr
, name
, rds
->ttl
, &rdata
));
1183 if (result
!= ISC_R_NOMORE
)
1186 if (dns_message_gettsig(msg
, &tsigowner
) != NULL
) {
1188 * Reset the counter.
1193 * Free the last tsig, if there is one.
1195 if (xfr
->lasttsig
!= NULL
)
1196 isc_buffer_free(&xfr
->lasttsig
);
1199 * Update the last tsig pointer.
1201 CHECK(dns_message_getquerytsig(msg
, xfr
->mctx
,
1204 } else if (dns_message_gettsigkey(msg
) != NULL
) {
1206 if (xfr
->sincetsig
> 100 ||
1207 xfr
->nmsg
== 0 || xfr
->state
== XFRST_END
)
1209 result
= DNS_R_EXPECTEDTSIG
;
1215 * Update the number of messages received.
1220 * Copy the context back.
1222 xfr
->tsigctx
= msg
->tsigctx
;
1224 dns_message_destroy(&msg
);
1226 if (xfr
->state
== XFRST_GOTSOA
) {
1227 xfr
->reqtype
= dns_rdatatype_axfr
;
1228 xfr
->state
= XFRST_INITIALSOA
;
1229 CHECK(xfrin_send_request(xfr
));
1230 } else if (xfr
->state
== XFRST_END
) {
1232 * Inform the caller we succeeded.
1234 if (xfr
->done
!= NULL
) {
1235 (xfr
->done
)(xfr
->zone
, ISC_R_SUCCESS
);
1239 * We should have no outstanding events at this
1240 * point, thus maybe_free() should succeed.
1242 xfr
->shuttingdown
= ISC_TRUE
;
1246 * Read the next message.
1248 CHECK(dns_tcpmsg_readmessage(&xfr
->tcpmsg
, xfr
->task
,
1249 xfrin_recv_done
, xfr
));
1256 dns_message_destroy(&msg
);
1257 if (result
!= ISC_R_SUCCESS
)
1258 xfrin_fail(xfr
, result
, "failed while receiving responses");
1262 xfrin_timeout(isc_task_t
*task
, isc_event_t
*event
) {
1263 dns_xfrin_ctx_t
*xfr
= (dns_xfrin_ctx_t
*) event
->ev_arg
;
1265 REQUIRE(VALID_XFRIN(xfr
));
1269 isc_event_free(&event
);
1271 * This will log "giving up: timeout".
1273 xfrin_fail(xfr
, ISC_R_TIMEDOUT
, "giving up");
1277 maybe_free(dns_xfrin_ctx_t
*xfr
) {
1278 REQUIRE(VALID_XFRIN(xfr
));
1280 if (! xfr
->shuttingdown
|| xfr
->refcount
!= 0 ||
1281 xfr
->connects
!= 0 || xfr
->sends
!= 0 ||
1285 xfrin_log(xfr
, ISC_LOG_INFO
, "end of transfer");
1287 if (xfr
->socket
!= NULL
)
1288 isc_socket_detach(&xfr
->socket
);
1290 if (xfr
->timer
!= NULL
)
1291 isc_timer_detach(&xfr
->timer
);
1293 if (xfr
->task
!= NULL
)
1294 isc_task_detach(&xfr
->task
);
1296 if (xfr
->tsigkey
!= NULL
)
1297 dns_tsigkey_detach(&xfr
->tsigkey
);
1299 if (xfr
->lasttsig
!= NULL
)
1300 isc_buffer_free(&xfr
->lasttsig
);
1302 dns_diff_clear(&xfr
->diff
);
1304 if (xfr
->ixfr
.journal
!= NULL
)
1305 dns_journal_destroy(&xfr
->ixfr
.journal
);
1307 if (xfr
->axfr
.add_private
!= NULL
)
1308 (void)dns_db_endload(xfr
->db
, &xfr
->axfr
.add_private
);
1310 if (xfr
->tcpmsg_valid
)
1311 dns_tcpmsg_invalidate(&xfr
->tcpmsg
);
1313 if ((xfr
->name
.attributes
& DNS_NAMEATTR_DYNAMIC
) != 0)
1314 dns_name_free(&xfr
->name
, xfr
->mctx
);
1316 if (xfr
->ver
!= NULL
)
1317 dns_db_closeversion(xfr
->db
, &xfr
->ver
, ISC_FALSE
);
1319 if (xfr
->db
!= NULL
)
1320 dns_db_detach(&xfr
->db
);
1322 if (xfr
->zone
!= NULL
)
1323 dns_zone_idetach(&xfr
->zone
);
1325 isc_mem_put(xfr
->mctx
, xfr
, sizeof(*xfr
));
1329 * Log incoming zone transfer messages in a format like
1330 * transfer of <zone> from <address>: <message>
1333 xfrin_logv(int level
, dns_name_t
*zonename
, dns_rdataclass_t rdclass
,
1334 isc_sockaddr_t
*masteraddr
, const char *fmt
, va_list ap
)
1336 char zntext
[DNS_NAME_FORMATSIZE
];
1337 char mastertext
[ISC_SOCKADDR_FORMATSIZE
];
1338 char classtext
[DNS_RDATACLASS_FORMATSIZE
];
1341 dns_name_format(zonename
, zntext
, sizeof(zntext
));
1342 dns_rdataclass_format(rdclass
, classtext
, sizeof(classtext
));
1343 isc_sockaddr_format(masteraddr
, mastertext
, sizeof(mastertext
));
1344 vsnprintf(msgtext
, sizeof(msgtext
), fmt
, ap
);
1346 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_XFER_IN
,
1347 DNS_LOGMODULE_XFER_IN
, level
,
1348 "transfer of '%s/%s' from %s: %s",
1349 zntext
, classtext
, mastertext
, msgtext
);
1353 * Logging function for use when a xfrin_ctx_t has not yet been created.
1357 xfrin_log1(int level
, dns_name_t
*zonename
, dns_rdataclass_t rdclass
,
1358 isc_sockaddr_t
*masteraddr
, const char *fmt
, ...)
1362 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
1366 xfrin_logv(level
, zonename
, rdclass
, masteraddr
, fmt
, ap
);
1371 * Logging function for use when there is a xfrin_ctx_t.
1375 xfrin_log(dns_xfrin_ctx_t
*xfr
, unsigned int level
, const char *fmt
, ...)
1379 if (isc_log_wouldlog(dns_lctx
, level
) == ISC_FALSE
)
1383 xfrin_logv(level
, &xfr
->name
, xfr
->rdclass
, &xfr
->masteraddr
, fmt
, ap
);