2 * Copyright (C) 2004-2006 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: xfrout.c,v 1.115.18.8 2006/03/05 23:58:51 marka Exp $ */
22 #include <isc/formatcheck.h>
24 #include <isc/timer.h>
25 #include <isc/print.h>
29 #include <dns/dbiterator.h>
33 #include <dns/fixedname.h>
34 #include <dns/journal.h>
35 #include <dns/message.h>
37 #include <dns/rdataclass.h>
38 #include <dns/rdatalist.h>
39 #include <dns/rdataset.h>
40 #include <dns/rdatasetiter.h>
41 #include <dns/result.h>
43 #include <dns/timer.h>
49 #include <named/client.h>
50 #include <named/log.h>
51 #include <named/server.h>
52 #include <named/xfrout.h>
56 * Outgoing AXFR and IXFR.
64 #define XFROUT_COMMON_LOGARGS \
65 ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
67 #define XFROUT_PROTOCOL_LOGARGS \
68 XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
70 #define XFROUT_DEBUG_LOGARGS(n) \
71 XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
73 #define XFROUT_RR_LOGARGS \
74 XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
76 #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
79 * Fail unconditionally and log as a client error.
80 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
81 * from complaining about "end-of-loop code not reached".
83 #define FAILC(code, msg) \
86 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
87 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
88 "bad zone transfer request: %s (%s)", \
89 msg, isc_result_totext(code)); \
90 if (result != ISC_R_SUCCESS) goto failure; \
93 #define FAILQ(code, msg, question, rdclass) \
95 char _buf1[DNS_NAME_FORMATSIZE]; \
96 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
98 dns_name_format(question, _buf1, sizeof(_buf1)); \
99 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
100 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
101 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
102 "bad zone transfer request: '%s/%s': %s (%s)", \
103 _buf1, _buf2, msg, isc_result_totext(code)); \
104 if (result != ISC_R_SUCCESS) goto failure; \
108 do { result = (op); \
109 if (result != ISC_R_SUCCESS) goto failure; \
112 /**************************************************************************/
114 * A db_rr_iterator_t is an iterator that iterates over an entire database,
115 * returning one RR at a time, in some arbitrary order.
118 typedef struct db_rr_iterator db_rr_iterator_t;
120 /*% db_rr_iterator structure */
121 struct db_rr_iterator {
124 dns_dbiterator_t *dbit;
125 dns_dbversion_t *ver;
128 dns_fixedname_t fixedname;
129 dns_rdatasetiter_t *rdatasetit;
130 dns_rdataset_t rdataset;
135 db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
139 db_rr_iterator_first(db_rr_iterator_t *it);
142 db_rr_iterator_next(db_rr_iterator_t *it);
145 db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
146 isc_uint32_t *ttl, dns_rdata_t **rdata);
149 db_rr_iterator_destroy(db_rr_iterator_t *it);
152 db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
161 result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit);
162 if (result != ISC_R_SUCCESS)
164 it->rdatasetit = NULL;
165 dns_rdata_init(&it->rdata);
166 dns_rdataset_init(&it->rdataset);
167 dns_fixedname_init(&it->fixedname);
168 INSIST(! dns_rdataset_isassociated(&it->rdataset));
169 it->result = ISC_R_SUCCESS;
174 db_rr_iterator_first(db_rr_iterator_t *it) {
175 it->result = dns_dbiterator_first(it->dbit);
177 * The top node may be empty when out of zone glue exists.
178 * Walk the tree to find the first node with data.
180 while (it->result == ISC_R_SUCCESS) {
181 it->result = dns_dbiterator_current(it->dbit, &it->node,
182 dns_fixedname_name(&it->fixedname));
183 if (it->result != ISC_R_SUCCESS)
186 it->result = dns_db_allrdatasets(it->db, it->node,
189 if (it->result != ISC_R_SUCCESS)
192 it->result = dns_rdatasetiter_first(it->rdatasetit);
193 if (it->result != ISC_R_SUCCESS) {
195 * This node is empty. Try next node.
197 dns_rdatasetiter_destroy(&it->rdatasetit);
198 dns_db_detachnode(it->db, &it->node);
199 it->result = dns_dbiterator_next(it->dbit);
202 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
203 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
204 it->result = dns_rdataset_first(&it->rdataset);
212 db_rr_iterator_next(db_rr_iterator_t *it) {
213 if (it->result != ISC_R_SUCCESS)
216 INSIST(it->dbit != NULL);
217 INSIST(it->node != NULL);
218 INSIST(it->rdatasetit != NULL);
220 it->result = dns_rdataset_next(&it->rdataset);
221 if (it->result == ISC_R_NOMORE) {
222 dns_rdataset_disassociate(&it->rdataset);
223 it->result = dns_rdatasetiter_next(it->rdatasetit);
225 * The while loop body is executed more than once
226 * only when an empty dbnode needs to be skipped.
228 while (it->result == ISC_R_NOMORE) {
229 dns_rdatasetiter_destroy(&it->rdatasetit);
230 dns_db_detachnode(it->db, &it->node);
231 it->result = dns_dbiterator_next(it->dbit);
232 if (it->result == ISC_R_NOMORE) {
233 /* We are at the end of the entire database. */
236 if (it->result != ISC_R_SUCCESS)
238 it->result = dns_dbiterator_current(it->dbit,
240 dns_fixedname_name(&it->fixedname));
241 if (it->result != ISC_R_SUCCESS)
243 it->result = dns_db_allrdatasets(it->db, it->node,
246 if (it->result != ISC_R_SUCCESS)
248 it->result = dns_rdatasetiter_first(it->rdatasetit);
250 if (it->result != ISC_R_SUCCESS)
252 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
253 it->rdataset.attributes |= DNS_RDATASETATTR_LOADORDER;
254 it->result = dns_rdataset_first(&it->rdataset);
255 if (it->result != ISC_R_SUCCESS)
262 db_rr_iterator_pause(db_rr_iterator_t *it) {
263 RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
267 db_rr_iterator_destroy(db_rr_iterator_t *it) {
268 if (dns_rdataset_isassociated(&it->rdataset))
269 dns_rdataset_disassociate(&it->rdataset);
270 if (it->rdatasetit != NULL)
271 dns_rdatasetiter_destroy(&it->rdatasetit);
272 if (it->node != NULL)
273 dns_db_detachnode(it->db, &it->node);
274 dns_dbiterator_destroy(&it->dbit);
278 db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
279 isc_uint32_t *ttl, dns_rdata_t **rdata)
281 REQUIRE(name != NULL && *name == NULL);
282 REQUIRE(it->result == ISC_R_SUCCESS);
283 *name = dns_fixedname_name(&it->fixedname);
284 *ttl = it->rdataset.ttl;
285 dns_rdata_reset(&it->rdata);
286 dns_rdataset_current(&it->rdataset, &it->rdata);
290 /**************************************************************************/
292 /*% Log an RR (for debugging) */
295 log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
301 dns_rdata_t rd = DNS_RDATA_INIT;
303 rdl.type = rdata->type;
304 rdl.rdclass = rdata->rdclass;
306 ISC_LIST_INIT(rdl.rdata);
307 ISC_LINK_INIT(&rdl, link);
308 dns_rdataset_init(&rds);
310 dns_rdata_clone(rdata, &rd);
311 ISC_LIST_APPEND(rdl.rdata, &rd, link);
312 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
314 isc_buffer_init(&buf, mem, sizeof(mem));
315 result = dns_rdataset_totext(&rds, name,
316 ISC_FALSE, ISC_FALSE, &buf);
319 * We could use xfrout_log(), but that would produce
320 * very long lines with a repetitive prefix.
322 if (result == ISC_R_SUCCESS) {
324 * Get rid of final newline.
326 INSIST(buf.used >= 1 &&
327 ((char *) buf.base)[buf.used - 1] == '\n');
330 isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
331 (int)isc_buffer_usedlength(&buf),
332 (char *)isc_buffer_base(&buf));
334 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
338 /**************************************************************************/
340 * An 'rrstream_t' is a polymorphic iterator that returns
341 * a stream of resource records. There are multiple implementations,
342 * e.g. for generating AXFR and IXFR records streams.
345 typedef struct rrstream_methods rrstream_methods_t;
347 typedef struct rrstream {
349 rrstream_methods_t *methods;
352 struct rrstream_methods {
353 isc_result_t (*first)(rrstream_t *);
354 isc_result_t (*next)(rrstream_t *);
355 void (*current)(rrstream_t *,
359 void (*pause)(rrstream_t *);
360 void (*destroy)(rrstream_t **);
364 rrstream_noop_pause(rrstream_t *rs) {
368 /**************************************************************************/
370 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
371 * an IXFR-like RR stream from a journal file.
373 * The SOA at the beginning of each sequence of additions
374 * or deletions are included in the stream, but the extra
375 * SOAs at the beginning and end of the entire transfer are
379 typedef struct ixfr_rrstream {
381 dns_journal_t *journal;
384 /* Forward declarations. */
386 ixfr_rrstream_destroy(rrstream_t **sp);
388 static rrstream_methods_t ixfr_rrstream_methods;
391 * Returns: anything dns_journal_open() or dns_journal_iter_init()
396 ixfr_rrstream_create(isc_mem_t *mctx,
397 const char *journal_filename,
398 isc_uint32_t begin_serial,
399 isc_uint32_t end_serial,
405 INSIST(sp != NULL && *sp == NULL);
407 s = isc_mem_get(mctx, sizeof(*s));
409 return (ISC_R_NOMEMORY);
410 s->common.mctx = mctx;
411 s->common.methods = &ixfr_rrstream_methods;
414 CHECK(dns_journal_open(mctx, journal_filename,
415 ISC_FALSE, &s->journal));
416 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
418 *sp = (rrstream_t *) s;
419 return (ISC_R_SUCCESS);
422 ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
427 ixfr_rrstream_first(rrstream_t *rs) {
428 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
429 return (dns_journal_first_rr(s->journal));
433 ixfr_rrstream_next(rrstream_t *rs) {
434 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
435 return (dns_journal_next_rr(s->journal));
439 ixfr_rrstream_current(rrstream_t *rs,
440 dns_name_t **name, isc_uint32_t *ttl,
443 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
444 dns_journal_current_rr(s->journal, name, ttl, rdata);
448 ixfr_rrstream_destroy(rrstream_t **rsp) {
449 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
451 dns_journal_destroy(&s->journal);
452 isc_mem_put(s->common.mctx, s, sizeof(*s));
455 static rrstream_methods_t ixfr_rrstream_methods = {
458 ixfr_rrstream_current,
460 ixfr_rrstream_destroy
463 /**************************************************************************/
465 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
466 * an AXFR-like RR stream from a database.
468 * The SOAs at the beginning and end of the transfer are
469 * not included in the stream.
472 typedef struct axfr_rrstream {
475 isc_boolean_t it_valid;
479 * Forward declarations.
482 axfr_rrstream_destroy(rrstream_t **rsp);
484 static rrstream_methods_t axfr_rrstream_methods;
487 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
493 INSIST(sp != NULL && *sp == NULL);
495 s = isc_mem_get(mctx, sizeof(*s));
497 return (ISC_R_NOMEMORY);
498 s->common.mctx = mctx;
499 s->common.methods = &axfr_rrstream_methods;
500 s->it_valid = ISC_FALSE;
502 CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
503 s->it_valid = ISC_TRUE;
505 *sp = (rrstream_t *) s;
506 return (ISC_R_SUCCESS);
509 axfr_rrstream_destroy((rrstream_t **) (void *)&s);
514 axfr_rrstream_first(rrstream_t *rs) {
515 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
517 result = db_rr_iterator_first(&s->it);
518 if (result != ISC_R_SUCCESS)
520 /* Skip SOA records. */
522 dns_name_t *name_dummy = NULL;
523 isc_uint32_t ttl_dummy;
524 dns_rdata_t *rdata = NULL;
525 db_rr_iterator_current(&s->it, &name_dummy,
527 if (rdata->type != dns_rdatatype_soa)
529 result = db_rr_iterator_next(&s->it);
530 if (result != ISC_R_SUCCESS)
537 axfr_rrstream_next(rrstream_t *rs) {
538 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
541 /* Skip SOA records. */
543 dns_name_t *name_dummy = NULL;
544 isc_uint32_t ttl_dummy;
545 dns_rdata_t *rdata = NULL;
546 result = db_rr_iterator_next(&s->it);
547 if (result != ISC_R_SUCCESS)
549 db_rr_iterator_current(&s->it, &name_dummy,
551 if (rdata->type != dns_rdatatype_soa)
558 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
561 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
562 db_rr_iterator_current(&s->it, name, ttl, rdata);
566 axfr_rrstream_pause(rrstream_t *rs) {
567 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
568 db_rr_iterator_pause(&s->it);
572 axfr_rrstream_destroy(rrstream_t **rsp) {
573 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
575 db_rr_iterator_destroy(&s->it);
576 isc_mem_put(s->common.mctx, s, sizeof(*s));
579 static rrstream_methods_t axfr_rrstream_methods = {
582 axfr_rrstream_current,
584 axfr_rrstream_destroy
587 /**************************************************************************/
589 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
590 * a single SOA record.
593 typedef struct soa_rrstream {
595 dns_difftuple_t *soa_tuple;
599 * Forward declarations.
602 soa_rrstream_destroy(rrstream_t **rsp);
604 static rrstream_methods_t soa_rrstream_methods;
607 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
613 INSIST(sp != NULL && *sp == NULL);
615 s = isc_mem_get(mctx, sizeof(*s));
617 return (ISC_R_NOMEMORY);
618 s->common.mctx = mctx;
619 s->common.methods = &soa_rrstream_methods;
622 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
625 *sp = (rrstream_t *) s;
626 return (ISC_R_SUCCESS);
629 soa_rrstream_destroy((rrstream_t **) (void *)&s);
634 soa_rrstream_first(rrstream_t *rs) {
636 return (ISC_R_SUCCESS);
640 soa_rrstream_next(rrstream_t *rs) {
642 return (ISC_R_NOMORE);
646 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
649 soa_rrstream_t *s = (soa_rrstream_t *) rs;
650 *name = &s->soa_tuple->name;
651 *ttl = s->soa_tuple->ttl;
652 *rdata = &s->soa_tuple->rdata;
656 soa_rrstream_destroy(rrstream_t **rsp) {
657 soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
658 if (s->soa_tuple != NULL)
659 dns_difftuple_free(&s->soa_tuple);
660 isc_mem_put(s->common.mctx, s, sizeof(*s));
663 static rrstream_methods_t soa_rrstream_methods = {
666 soa_rrstream_current,
671 /**************************************************************************/
673 * A 'compound_rrstream_t' objects owns a soa_rrstream
674 * and another rrstream, the "data stream". It returns
675 * a concatenated stream consisting of the soa_rrstream, then
676 * the data stream, then the soa_rrstream again.
678 * The component streams are owned by the compound_rrstream_t
679 * and are destroyed with it.
682 typedef struct compound_rrstream {
684 rrstream_t *components[3];
687 } compound_rrstream_t;
690 * Forward declarations.
693 compound_rrstream_destroy(rrstream_t **rsp);
696 compound_rrstream_next(rrstream_t *rs);
698 static rrstream_methods_t compound_rrstream_methods;
702 * soa_stream != NULL && *soa_stream != NULL
703 * data_stream != NULL && *data_stream != NULL
704 * sp != NULL && *sp == NULL
707 * *soa_stream == NULL
708 * *data_stream == NULL
709 * *sp points to a valid compound_rrstream_t
710 * The soa and data streams will be destroyed
711 * when the compound_rrstream_t is destroyed.
714 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
715 rrstream_t **data_stream, rrstream_t **sp)
717 compound_rrstream_t *s;
719 INSIST(sp != NULL && *sp == NULL);
721 s = isc_mem_get(mctx, sizeof(*s));
723 return (ISC_R_NOMEMORY);
724 s->common.mctx = mctx;
725 s->common.methods = &compound_rrstream_methods;
726 s->components[0] = *soa_stream;
727 s->components[1] = *data_stream;
728 s->components[2] = *soa_stream;
730 s->result = ISC_R_FAILURE;
734 *sp = (rrstream_t *) s;
735 return (ISC_R_SUCCESS);
739 compound_rrstream_first(rrstream_t *rs) {
740 compound_rrstream_t *s = (compound_rrstream_t *) rs;
743 rrstream_t *curstream = s->components[s->state];
744 s->result = curstream->methods->first(curstream);
745 } while (s->result == ISC_R_NOMORE && s->state < 2);
750 compound_rrstream_next(rrstream_t *rs) {
751 compound_rrstream_t *s = (compound_rrstream_t *) rs;
752 rrstream_t *curstream = s->components[s->state];
753 s->result = curstream->methods->next(curstream);
754 while (s->result == ISC_R_NOMORE) {
756 * Make sure locks held by the current stream
757 * are released before we switch streams.
759 curstream->methods->pause(curstream);
761 return (ISC_R_NOMORE);
763 curstream = s->components[s->state];
764 s->result = curstream->methods->first(curstream);
770 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
773 compound_rrstream_t *s = (compound_rrstream_t *) rs;
774 rrstream_t *curstream;
775 INSIST(0 <= s->state && s->state < 3);
776 INSIST(s->result == ISC_R_SUCCESS);
777 curstream = s->components[s->state];
778 curstream->methods->current(curstream, name, ttl, rdata);
782 compound_rrstream_pause(rrstream_t *rs)
784 compound_rrstream_t *s = (compound_rrstream_t *) rs;
785 rrstream_t *curstream;
786 INSIST(0 <= s->state && s->state < 3);
787 curstream = s->components[s->state];
788 curstream->methods->pause(curstream);
792 compound_rrstream_destroy(rrstream_t **rsp) {
793 compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
794 s->components[0]->methods->destroy(&s->components[0]);
795 s->components[1]->methods->destroy(&s->components[1]);
796 s->components[2] = NULL; /* Copy of components[0]. */
797 isc_mem_put(s->common.mctx, s, sizeof(*s));
800 static rrstream_methods_t compound_rrstream_methods = {
801 compound_rrstream_first,
802 compound_rrstream_next,
803 compound_rrstream_current,
804 compound_rrstream_pause,
805 compound_rrstream_destroy
808 /**************************************************************************/
810 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
817 unsigned int id; /* ID of request */
818 dns_name_t *qname; /* Question name of request */
819 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
820 dns_rdataclass_t qclass;
822 dns_dbversion_t *ver;
824 rrstream_t *stream; /* The XFR RR stream */
825 isc_boolean_t end_of_stream; /* EOS has been reached */
826 isc_buffer_t buf; /* Buffer for message owner
828 isc_buffer_t txlenbuf; /* Transmit length buffer */
829 isc_buffer_t txbuf; /* Transmit message buffer */
831 unsigned int txmemlen;
832 unsigned int nmsg; /* Number of messages sent */
833 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
834 isc_buffer_t *lasttsig; /* the last TSIG */
835 isc_boolean_t many_answers;
836 int sends; /* Send in progress */
837 isc_boolean_t shuttingdown;
838 const char *mnemonic; /* Style of transfer */
842 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
843 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
844 dns_rdataclass_t qclass,
845 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
846 rrstream_t *stream, dns_tsigkey_t *tsigkey,
847 isc_buffer_t *lasttsig,
848 unsigned int maxtime,
849 unsigned int idletime,
850 isc_boolean_t many_answers,
851 xfrout_ctx_t **xfrp);
854 sendstream(xfrout_ctx_t *xfr);
857 xfrout_senddone(isc_task_t *task, isc_event_t *event);
860 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
863 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
866 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
869 xfrout_client_shutdown(void *arg, isc_result_t result);
872 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
873 dns_rdataclass_t rdclass, int level,
874 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
877 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
878 ISC_FORMAT_PRINTF(3, 4);
880 /**************************************************************************/
883 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
885 dns_name_t *question_name;
886 dns_rdataset_t *question_rdataset;
887 dns_zone_t *zone = NULL;
889 dns_dbversion_t *ver = NULL;
890 dns_rdataclass_t question_class;
891 rrstream_t *soa_stream = NULL;
892 rrstream_t *data_stream = NULL;
893 rrstream_t *stream = NULL;
894 dns_difftuple_t *current_soa_tuple = NULL;
895 dns_name_t *soa_name;
896 dns_rdataset_t *soa_rdataset;
897 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
898 isc_boolean_t have_soa = ISC_FALSE;
899 const char *mnemonic = NULL;
900 isc_mem_t *mctx = client->mctx;
901 dns_message_t *request = client->message;
902 xfrout_ctx_t *xfr = NULL;
903 isc_quota_t *quota = NULL;
904 dns_transfer_format_t format = client->view->transfer_format;
906 dns_peer_t *peer = NULL;
907 isc_buffer_t *tsigbuf = NULL;
909 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
910 char keyname[DNS_NAME_FORMATSIZE];
911 isc_boolean_t is_poll = ISC_FALSE;
913 isc_boolean_t is_dlz = ISC_FALSE;
917 case dns_rdatatype_axfr:
920 case dns_rdatatype_ixfr:
928 ns_client_log(client,
929 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
930 ISC_LOG_DEBUG(6), "%s request", mnemonic);
934 result = isc_quota_attach(&ns_g_server->xfroutquota, "a);
935 if (result != ISC_R_SUCCESS) {
936 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
937 "%s request denied: %s", mnemonic,
938 isc_result_totext(result));
943 * Interpret the question section.
945 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
946 INSIST(result == ISC_R_SUCCESS);
949 * The question section must contain exactly one question, and
950 * it must be for AXFR/IXFR as appropriate.
952 question_name = NULL;
953 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
954 question_rdataset = ISC_LIST_HEAD(question_name->list);
955 question_class = question_rdataset->rdclass;
956 INSIST(question_rdataset->type == reqtype);
957 if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
958 FAILC(DNS_R_FORMERR, "multiple questions");
959 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
960 if (result != ISC_R_NOMORE)
961 FAILC(DNS_R_FORMERR, "multiple questions");
963 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
966 if (result != ISC_R_SUCCESS)
970 * Normal zone table does not have a match. Try the DLZ database
972 if (client->view->dlzdatabase != NULL) {
973 result = dns_dlzallowzonexfr(client->view,
974 question_name, &client->peeraddr,
977 if (result == ISC_R_NOPERM) {
978 char _buf1[DNS_NAME_FORMATSIZE];
979 char _buf2[DNS_RDATACLASS_FORMATSIZE];
981 result = DNS_R_REFUSED;
982 dns_name_format(question_name, _buf1,
984 dns_rdataclass_format(question_class,
985 _buf2, sizeof(_buf2));
986 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
987 NS_LOGMODULE_XFER_OUT,
989 "zone transfer '%s/%s' denied",
993 if (result != ISC_R_SUCCESS)
995 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
996 question_name, question_class);
1000 * DLZ only support full zone transfer, not incremental
1002 if (reqtype != dns_rdatatype_axfr) {
1003 mnemonic = "AXFR-style IXFR";
1004 reqtype = dns_rdatatype_axfr;
1009 * not DLZ and not in normal zone table, we are
1012 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
1013 question_name, question_class);
1016 /* zone table has a match */
1018 switch(dns_zone_gettype(zone)) {
1019 case dns_zone_master:
1020 case dns_zone_slave:
1021 break; /* Master and slave zones are OK for transfer. */
1023 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
1025 CHECK(dns_zone_getdb(zone, &db));
1026 dns_db_currentversion(db, &ver);
1031 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
1032 "%s question section OK", mnemonic);
1035 * Check the authority section. Look for a SOA record with
1036 * the same name and class as the question.
1038 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
1039 result == ISC_R_SUCCESS;
1040 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
1043 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
1047 * Ignore data whose owner name is not the zone apex.
1049 if (! dns_name_equal(soa_name, question_name))
1052 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
1053 soa_rdataset != NULL;
1054 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
1057 * Ignore non-SOA data.
1059 if (soa_rdataset->type != dns_rdatatype_soa)
1061 if (soa_rdataset->rdclass != question_class)
1064 CHECK(dns_rdataset_first(soa_rdataset));
1065 dns_rdataset_current(soa_rdataset, &soa_rdata);
1066 result = dns_rdataset_next(soa_rdataset);
1067 if (result == ISC_R_SUCCESS)
1068 FAILC(DNS_R_FORMERR,
1069 "IXFR authority section "
1070 "has multiple SOAs");
1071 have_soa = ISC_TRUE;
1076 if (result != ISC_R_NOMORE)
1079 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
1080 "%s authority section OK", mnemonic);
1083 * Decide whether to allow this transfer.
1087 * if not a DLZ zone decide whether to allow this transfer.
1091 ns_client_aclmsg("zone transfer", question_name, reqtype,
1092 client->view->rdclass, msg, sizeof(msg));
1093 CHECK(ns_client_checkacl(client, msg,
1094 dns_zone_getxfracl(zone), ISC_TRUE,
1101 * AXFR over UDP is not possible.
1103 if (reqtype == dns_rdatatype_axfr &&
1104 (client->attributes & NS_CLIENTATTR_TCP) == 0)
1105 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
1108 * Look up the requesting server in the peer table.
1110 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
1111 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
1114 * Decide on the transfer format (one-answer or many-answers).
1117 (void)dns_peer_gettransferformat(peer, &format);
1120 * Get a dynamically allocated copy of the current SOA.
1124 dns_db_currentversion(db, &ver);
1126 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
1127 ¤t_soa_tuple));
1129 if (reqtype == dns_rdatatype_ixfr) {
1130 isc_uint32_t begin_serial, current_serial;
1131 isc_boolean_t provide_ixfr;
1134 * Outgoing IXFR may have been disabled for this peer
1137 provide_ixfr = client->view->provideixfr;
1139 (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
1140 if (provide_ixfr == ISC_FALSE)
1144 FAILC(DNS_R_FORMERR,
1145 "IXFR request missing SOA");
1147 begin_serial = dns_soa_getserial(&soa_rdata);
1148 current_serial = dns_soa_getserial(¤t_soa_tuple->rdata);
1151 * RFC1995 says "If an IXFR query with the same or
1152 * newer version number than that of the server
1153 * is received, it is replied to with a single SOA
1154 * record of the server's current version, just as
1155 * in AXFR". The claim about AXFR is incorrect,
1156 * but other than that, we do as the RFC says.
1158 * Sending a single SOA record is also how we refuse
1159 * IXFR over UDP (currently, we always do).
1161 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
1162 (client->attributes & NS_CLIENTATTR_TCP) == 0)
1164 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
1168 journalfile = dns_zone_getjournal(zone);
1169 if (journalfile != NULL)
1170 result = ixfr_rrstream_create(mctx,
1176 result = ISC_R_NOTFOUND;
1177 if (result == ISC_R_NOTFOUND ||
1178 result == ISC_R_RANGE) {
1179 xfrout_log1(client, question_name, question_class,
1181 "IXFR version not in journal, "
1182 "falling back to AXFR");
1183 mnemonic = "AXFR-style IXFR";
1189 CHECK(axfr_rrstream_create(mctx, db, ver,
1194 * Bracket the the data stream with SOAs.
1196 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1197 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1203 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1205 * Create the xfrout context object. This transfers the ownership
1206 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1213 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1214 reqtype, question_class, db, ver, quota,
1215 stream, dns_message_gettsigkey(request),
1219 (format == dns_many_answers) ?
1220 ISC_TRUE : ISC_FALSE,
1224 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1225 reqtype, question_class, db, ver, quota,
1226 stream, dns_message_gettsigkey(request),
1228 dns_zone_getmaxxfrout(zone),
1229 dns_zone_getidleout(zone),
1230 (format == dns_many_answers) ?
1231 ISC_TRUE : ISC_FALSE,
1234 xfr->mnemonic = mnemonic;
1238 CHECK(xfr->stream->methods->first(xfr->stream));
1240 if (xfr->tsigkey != NULL) {
1241 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
1245 xfrout_log1(client, question_name, question_class,
1246 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
1247 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1249 xfrout_log1(client, question_name, question_class,
1250 ISC_LOG_INFO, "%s started%s%s", mnemonic,
1251 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1254 * Hand the context over to sendstream(). Set xfr to NULL;
1255 * sendstream() is responsible for either passing the
1256 * context on to a later event handler or destroying it.
1261 result = ISC_R_SUCCESS;
1265 isc_quota_detach("a);
1266 if (current_soa_tuple != NULL)
1267 dns_difftuple_free(¤t_soa_tuple);
1269 stream->methods->destroy(&stream);
1270 if (soa_stream != NULL)
1271 soa_stream->methods->destroy(&soa_stream);
1272 if (data_stream != NULL)
1273 data_stream->methods->destroy(&data_stream);
1275 dns_db_closeversion(db, &ver, ISC_FALSE);
1279 dns_zone_detach(&zone);
1282 xfrout_fail(xfr, result, "setting up zone transfer");
1283 } else if (result != ISC_R_SUCCESS) {
1284 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1285 NS_LOGMODULE_XFER_OUT,
1286 ISC_LOG_DEBUG(3), "zone transfer setup failed");
1287 ns_client_error(client, result);
1292 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1293 dns_name_t *qname, dns_rdatatype_t qtype,
1294 dns_rdataclass_t qclass,
1295 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
1296 rrstream_t *stream, dns_tsigkey_t *tsigkey,
1297 isc_buffer_t *lasttsig, unsigned int maxtime,
1298 unsigned int idletime, isc_boolean_t many_answers,
1299 xfrout_ctx_t **xfrp)
1302 isc_result_t result;
1306 INSIST(xfrp != NULL && *xfrp == NULL);
1307 xfr = isc_mem_get(mctx, sizeof(*xfr));
1309 return (ISC_R_NOMEMORY);
1312 ns_client_attach(client, &xfr->client);
1316 xfr->qclass = qclass;
1319 dns_db_attach(db, &xfr->db);
1320 dns_db_attachversion(db, ver, &xfr->ver);
1321 xfr->end_of_stream = ISC_FALSE;
1322 xfr->tsigkey = tsigkey;
1323 xfr->lasttsig = lasttsig;
1327 xfr->many_answers = many_answers,
1329 xfr->shuttingdown = ISC_FALSE;
1330 xfr->mnemonic = NULL;
1331 xfr->buf.base = NULL;
1332 xfr->buf.length = 0;
1339 * Allocate a temporary buffer for the uncompressed response
1340 * message data. The size should be no more than 65535 bytes
1341 * so that the compressed data will fit in a TCP message,
1342 * and no less than 65535 bytes so that an almost maximum-sized
1343 * RR will fit. Note that although 65535-byte RRs are allowed
1344 * in principle, they cannot be zone-transferred (at least not
1345 * if uncompressible), because the message and RR headers would
1346 * push the size of the TCP message over the 65536 byte limit.
1349 mem = isc_mem_get(mctx, len);
1351 result = ISC_R_NOMEMORY;
1354 isc_buffer_init(&xfr->buf, mem, len);
1357 * Allocate another temporary buffer for the compressed
1358 * response message and its TCP length prefix.
1361 mem = isc_mem_get(mctx, len);
1363 result = ISC_R_NOMEMORY;
1366 isc_buffer_init(&xfr->txlenbuf, mem, 2);
1367 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
1369 xfr->txmemlen = len;
1371 CHECK(dns_timer_setidle(xfr->client->timer,
1372 maxtime, idletime, ISC_FALSE));
1375 * Register a shutdown callback with the client, so that we
1376 * can stop the transfer immediately when the client task
1377 * gets a shutdown event.
1379 xfr->client->shutdown = xfrout_client_shutdown;
1380 xfr->client->shutdown_arg = xfr;
1382 * These MUST be after the last "goto failure;" / CHECK to
1383 * prevent a double free by the caller.
1386 xfr->stream = stream;
1389 return (ISC_R_SUCCESS);
1392 xfrout_ctx_destroy(&xfr);
1398 * Arrange to send as much as we can of "stream" without blocking.
1401 * The stream iterator is initialized and points at an RR,
1402 * or possiby at the end of the stream (that is, the
1403 * _first method of the iterator has been called).
1406 sendstream(xfrout_ctx_t *xfr) {
1407 dns_message_t *tcpmsg = NULL;
1408 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1409 isc_result_t result;
1411 isc_region_t region;
1412 dns_rdataset_t *qrdataset;
1413 dns_name_t *msgname = NULL;
1414 dns_rdata_t *msgrdata = NULL;
1415 dns_rdatalist_t *msgrdl = NULL;
1416 dns_rdataset_t *msgrds = NULL;
1417 dns_compress_t cctx;
1418 isc_boolean_t cleanup_cctx = ISC_FALSE;
1422 isc_buffer_clear(&xfr->buf);
1423 isc_buffer_clear(&xfr->txlenbuf);
1424 isc_buffer_clear(&xfr->txbuf);
1426 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
1428 * In the UDP case, we put the response data directly into
1429 * the client message.
1431 msg = xfr->client->message;
1432 CHECK(dns_message_reply(msg, ISC_TRUE));
1435 * TCP. Build a response dns_message_t, temporarily storing
1436 * the raw, uncompressed owner names and RR data contiguously
1437 * in xfr->buf. We know that if the uncompressed data fits
1438 * in xfr->buf, the compressed data will surely fit in a TCP
1442 CHECK(dns_message_create(xfr->mctx,
1443 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
1447 msg->rcode = dns_rcode_noerror;
1448 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1449 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
1450 msg->flags |= DNS_MESSAGEFLAG_RA;
1451 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1452 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1453 if (xfr->lasttsig != NULL)
1454 isc_buffer_free(&xfr->lasttsig);
1457 * Include a question section in the first message only.
1458 * BIND 8.2.1 will not recognize an IXFR if it does not
1459 * have a question section.
1461 if (xfr->nmsg == 0) {
1462 dns_name_t *qname = NULL;
1466 * Reserve space for the 12-byte message header
1467 * and 4 bytes of question.
1469 isc_buffer_add(&xfr->buf, 12 + 4);
1472 result = dns_message_gettemprdataset(msg, &qrdataset);
1473 if (result != ISC_R_SUCCESS)
1475 dns_rdataset_init(qrdataset);
1476 dns_rdataset_makequestion(qrdataset,
1477 xfr->client->message->rdclass,
1480 result = dns_message_gettempname(msg, &qname);
1481 if (result != ISC_R_SUCCESS)
1483 dns_name_init(qname, NULL);
1484 isc_buffer_availableregion(&xfr->buf, &r);
1485 INSIST(r.length >= xfr->qname->length);
1486 r.length = xfr->qname->length;
1487 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1488 xfr->qname->length);
1489 dns_name_fromregion(qname, &r);
1490 ISC_LIST_INIT(qname->list);
1491 ISC_LIST_APPEND(qname->list, qrdataset, link);
1493 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1496 msg->tcp_continuation = 1;
1500 * Try to fit in as many RRs as possible, unless "one-answer"
1501 * format has been requested.
1503 for (n_rrs = 0; ; n_rrs++) {
1504 dns_name_t *name = NULL;
1506 dns_rdata_t *rdata = NULL;
1516 xfr->stream->methods->current(xfr->stream,
1517 &name, &ttl, &rdata);
1518 size = name->length + 10 + rdata->length;
1519 isc_buffer_availableregion(&xfr->buf, &r);
1520 if (size >= r.length) {
1522 * RR would not fit. If there are other RRs in the
1523 * buffer, send them now and leave this RR to the
1524 * next message. If this RR overflows the buffer
1525 * all by itself, fail.
1527 * In theory some RRs might fit in a TCP message
1528 * when compressed even if they do not fit when
1529 * uncompressed, but surely we don't want
1530 * to send such monstrosities to an unsuspecting
1534 xfrout_log(xfr, ISC_LOG_WARNING,
1535 "RR too large for zone transfer "
1536 "(%d bytes)", size);
1537 /* XXX DNS_R_RRTOOLARGE? */
1538 result = ISC_R_NOSPACE;
1544 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
1545 log_rr(name, rdata, ttl); /* XXX */
1547 result = dns_message_gettempname(msg, &msgname);
1548 if (result != ISC_R_SUCCESS)
1550 dns_name_init(msgname, NULL);
1551 isc_buffer_availableregion(&xfr->buf, &r);
1552 INSIST(r.length >= name->length);
1553 r.length = name->length;
1554 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1555 dns_name_fromregion(msgname, &r);
1557 /* Reserve space for RR header. */
1558 isc_buffer_add(&xfr->buf, 10);
1560 result = dns_message_gettemprdata(msg, &msgrdata);
1561 if (result != ISC_R_SUCCESS)
1563 isc_buffer_availableregion(&xfr->buf, &r);
1564 r.length = rdata->length;
1565 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1566 dns_rdata_init(msgrdata);
1567 dns_rdata_fromregion(msgrdata,
1568 rdata->rdclass, rdata->type, &r);
1570 result = dns_message_gettemprdatalist(msg, &msgrdl);
1571 if (result != ISC_R_SUCCESS)
1573 msgrdl->type = rdata->type;
1574 msgrdl->rdclass = rdata->rdclass;
1576 ISC_LINK_INIT(msgrdl, link);
1577 ISC_LIST_INIT(msgrdl->rdata);
1578 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1580 result = dns_message_gettemprdataset(msg, &msgrds);
1581 if (result != ISC_R_SUCCESS)
1583 dns_rdataset_init(msgrds);
1584 result = dns_rdatalist_tordataset(msgrdl, msgrds);
1585 INSIST(result == ISC_R_SUCCESS);
1587 ISC_LIST_APPEND(msgname->list, msgrds, link);
1589 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1592 result = xfr->stream->methods->next(xfr->stream);
1593 if (result == ISC_R_NOMORE) {
1594 xfr->end_of_stream = ISC_TRUE;
1599 if (! xfr->many_answers)
1603 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
1604 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1605 dns_compress_setsensitive(&cctx, ISC_TRUE);
1606 cleanup_cctx = ISC_TRUE;
1607 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1608 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1609 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1610 CHECK(dns_message_renderend(msg));
1611 dns_compress_invalidate(&cctx);
1612 cleanup_cctx = ISC_FALSE;
1614 isc_buffer_usedregion(&xfr->txbuf, &used);
1615 isc_buffer_putuint16(&xfr->txlenbuf,
1616 (isc_uint16_t)used.length);
1617 region.base = xfr->txlenbuf.base;
1618 region.length = 2 + used.length;
1619 xfrout_log(xfr, ISC_LOG_DEBUG(8),
1620 "sending TCP message of %d bytes",
1622 CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
1623 ®ion, xfr->client->task,
1628 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1629 ns_client_send(xfr->client);
1630 xfr->stream->methods->pause(xfr->stream);
1631 xfrout_ctx_destroy(&xfr);
1635 /* Advance lasttsig to be the last TSIG generated */
1636 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1641 if (msgname != NULL) {
1642 if (msgrds != NULL) {
1643 if (dns_rdataset_isassociated(msgrds))
1644 dns_rdataset_disassociate(msgrds);
1645 dns_message_puttemprdataset(msg, &msgrds);
1647 if (msgrdl != NULL) {
1648 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1649 dns_message_puttemprdatalist(msg, &msgrdl);
1651 if (msgrdata != NULL)
1652 dns_message_puttemprdata(msg, &msgrdata);
1653 dns_message_puttempname(msg, &msgname);
1657 dns_message_destroy(&tcpmsg);
1660 dns_compress_invalidate(&cctx);
1662 * Make sure to release any locks held by database
1663 * iterators before returning from the event handler.
1665 xfr->stream->methods->pause(xfr->stream);
1667 if (result == ISC_R_SUCCESS)
1670 xfrout_fail(xfr, result, "sending zone data");
1674 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1675 xfrout_ctx_t *xfr = *xfrp;
1677 INSIST(xfr->sends == 0);
1679 xfr->client->shutdown = NULL;
1680 xfr->client->shutdown_arg = NULL;
1682 if (xfr->stream != NULL)
1683 xfr->stream->methods->destroy(&xfr->stream);
1684 if (xfr->buf.base != NULL)
1685 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1686 if (xfr->txmem != NULL)
1687 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1688 if (xfr->lasttsig != NULL)
1689 isc_buffer_free(&xfr->lasttsig);
1690 if (xfr->quota != NULL)
1691 isc_quota_detach(&xfr->quota);
1692 if (xfr->ver != NULL)
1693 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1694 if (xfr->db != NULL)
1695 dns_db_detach(&xfr->db);
1697 ns_client_detach(&xfr->client);
1699 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1705 xfrout_senddone(isc_task_t *task, isc_event_t *event) {
1706 isc_socketevent_t *sev = (isc_socketevent_t *)event;
1707 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
1708 isc_result_t evresult = sev->result;
1712 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1714 isc_event_free(&event);
1716 INSIST(xfr->sends == 0);
1718 (void)isc_timer_touch(xfr->client->timer);
1719 if (xfr->shuttingdown == ISC_TRUE) {
1720 xfrout_maybe_destroy(xfr);
1721 } else if (evresult != ISC_R_SUCCESS) {
1722 xfrout_fail(xfr, evresult, "send");
1723 } else if (xfr->end_of_stream == ISC_FALSE) {
1726 /* End of zone transfer stream. */
1727 xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
1728 ns_client_next(xfr->client, ISC_R_SUCCESS);
1729 xfrout_ctx_destroy(&xfr);
1734 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1735 xfr->shuttingdown = ISC_TRUE;
1736 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
1737 msg, isc_result_totext(result));
1738 xfrout_maybe_destroy(xfr);
1742 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1743 INSIST(xfr->shuttingdown == ISC_TRUE);
1744 if (xfr->sends > 0) {
1746 * If we are currently sending, cancel it and wait for
1747 * cancel event before destroying the context.
1749 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
1750 ISC_SOCKCANCEL_SEND);
1752 ns_client_next(xfr->client, ISC_R_CANCELED);
1753 xfrout_ctx_destroy(&xfr);
1758 xfrout_client_shutdown(void *arg, isc_result_t result) {
1759 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
1760 xfrout_fail(xfr, result, "aborted");
1764 * Log outgoing zone transfer messages in a format like
1765 * <client>: transfer of <zone>: <message>
1769 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1770 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1771 ISC_FORMAT_PRINTF(5, 0);
1774 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1775 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1778 char namebuf[DNS_NAME_FORMATSIZE];
1779 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1781 dns_name_format(zonename, namebuf, sizeof(namebuf));
1782 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1783 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1784 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1785 NS_LOGMODULE_XFER_OUT, level,
1786 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
1790 * Logging function for use when a xfrout_ctx_t has not yet been created.
1793 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
1794 dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
1797 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1802 * Logging function for use when there is a xfrout_ctx_t.
1805 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
1808 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);