Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / bin / named / xfrout.c
blob8823a7a01ef08a980d41a204eb3b5b1b1a8db329
1 /*
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: xfrout.c,v 1.101.2.8 2004/04/15 01:38:05 marka Exp $ */
20 #include <config.h>
22 #include <isc/formatcheck.h>
23 #include <isc/mem.h>
24 #include <isc/timer.h>
25 #include <isc/print.h>
26 #include <isc/util.h>
28 #include <dns/db.h>
29 #include <dns/dbiterator.h>
30 #include <dns/fixedname.h>
31 #include <dns/journal.h>
32 #include <dns/message.h>
33 #include <dns/peer.h>
34 #include <dns/rdataclass.h>
35 #include <dns/rdatalist.h>
36 #include <dns/rdataset.h>
37 #include <dns/rdatasetiter.h>
38 #include <dns/result.h>
39 #include <dns/soa.h>
40 #include <dns/timer.h>
41 #include <dns/view.h>
42 #include <dns/zone.h>
43 #include <dns/zt.h>
45 #include <named/client.h>
46 #include <named/log.h>
47 #include <named/server.h>
48 #include <named/xfrout.h>
51 * Outgoing AXFR and IXFR.
55 * TODO:
56 * - IXFR over UDP
59 #define XFROUT_COMMON_LOGARGS \
60 ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
62 #define XFROUT_PROTOCOL_LOGARGS \
63 XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
65 #define XFROUT_DEBUG_LOGARGS(n) \
66 XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
68 #define XFROUT_RR_LOGARGS \
69 XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
71 #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
74 * Fail unconditionally and log as a client error.
75 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
76 * from complaining about "end-of-loop code not reached".
78 #define FAILC(code, msg) \
79 do { \
80 result = (code); \
81 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
82 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
83 "bad zone transfer request: %s (%s)", \
84 msg, isc_result_totext(code)); \
85 if (result != ISC_R_SUCCESS) goto failure; \
86 } while (0)
88 #define FAILQ(code, msg, question, rdclass) \
89 do { \
90 char _buf1[DNS_NAME_FORMATSIZE]; \
91 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
92 result = (code); \
93 dns_name_format(question, _buf1, sizeof(_buf1)); \
94 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
95 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
96 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
97 "bad zone transfer request: '%s/%s': %s (%s)", \
98 _buf1, _buf2, msg, isc_result_totext(code)); \
99 if (result != ISC_R_SUCCESS) goto failure; \
100 } while (0)
102 #define CHECK(op) \
103 do { result = (op); \
104 if (result != ISC_R_SUCCESS) goto failure; \
105 } while (0)
107 /**************************************************************************/
109 * A db_rr_iterator_t is an iterator that iterates over an entire database,
110 * returning one RR at a time, in some arbitrary order.
113 typedef struct db_rr_iterator db_rr_iterator_t;
115 struct db_rr_iterator {
116 isc_result_t result;
117 dns_db_t *db;
118 dns_dbiterator_t *dbit;
119 dns_dbversion_t *ver;
120 isc_stdtime_t now;
121 dns_dbnode_t *node;
122 dns_fixedname_t fixedname;
123 dns_rdatasetiter_t *rdatasetit;
124 dns_rdataset_t rdataset;
125 dns_rdata_t rdata;
128 static isc_result_t
129 db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
130 isc_stdtime_t now);
132 static isc_result_t
133 db_rr_iterator_first(db_rr_iterator_t *it);
135 static isc_result_t
136 db_rr_iterator_next(db_rr_iterator_t *it);
138 static void
139 db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
140 isc_uint32_t *ttl, dns_rdata_t **rdata);
142 static void
143 db_rr_iterator_destroy(db_rr_iterator_t *it);
145 static isc_result_t
146 db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
147 isc_stdtime_t now)
149 isc_result_t result;
150 it->db = db;
151 it->dbit = NULL;
152 it->ver = ver;
153 it->now = now;
154 it->node = NULL;
155 result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit);
156 if (result != ISC_R_SUCCESS)
157 return (result);
158 it->rdatasetit = NULL;
159 dns_rdata_init(&it->rdata);
160 dns_rdataset_init(&it->rdataset);
161 dns_fixedname_init(&it->fixedname);
162 INSIST(! dns_rdataset_isassociated(&it->rdataset));
163 it->result = ISC_R_SUCCESS;
164 return (it->result);
167 static isc_result_t
168 db_rr_iterator_first(db_rr_iterator_t *it) {
169 it->result = dns_dbiterator_first(it->dbit);
171 * The top node may be empty when out of zone glue exists.
172 * Walk the tree to find the first node with data.
174 while (it->result == ISC_R_SUCCESS) {
175 it->result = dns_dbiterator_current(it->dbit, &it->node,
176 dns_fixedname_name(&it->fixedname));
177 if (it->result != ISC_R_SUCCESS)
178 return (it->result);
180 it->result = dns_db_allrdatasets(it->db, it->node,
181 it->ver, it->now,
182 &it->rdatasetit);
183 if (it->result != ISC_R_SUCCESS)
184 return (it->result);
186 it->result = dns_rdatasetiter_first(it->rdatasetit);
187 if (it->result != ISC_R_SUCCESS) {
189 * This node is empty. Try next node.
191 dns_rdatasetiter_destroy(&it->rdatasetit);
192 dns_db_detachnode(it->db, &it->node);
193 it->result = dns_dbiterator_next(it->dbit);
194 continue;
196 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
198 it->result = dns_rdataset_first(&it->rdataset);
199 return (it->result);
201 return (it->result);
205 static isc_result_t
206 db_rr_iterator_next(db_rr_iterator_t *it) {
207 if (it->result != ISC_R_SUCCESS)
208 return (it->result);
210 INSIST(it->dbit != NULL);
211 INSIST(it->node != NULL);
212 INSIST(it->rdatasetit != NULL);
214 it->result = dns_rdataset_next(&it->rdataset);
215 if (it->result == ISC_R_NOMORE) {
216 dns_rdataset_disassociate(&it->rdataset);
217 it->result = dns_rdatasetiter_next(it->rdatasetit);
219 * The while loop body is executed more than once
220 * only when an empty dbnode needs to be skipped.
222 while (it->result == ISC_R_NOMORE) {
223 dns_rdatasetiter_destroy(&it->rdatasetit);
224 dns_db_detachnode(it->db, &it->node);
225 it->result = dns_dbiterator_next(it->dbit);
226 if (it->result == ISC_R_NOMORE) {
227 /* We are at the end of the entire database. */
228 return (it->result);
230 if (it->result != ISC_R_SUCCESS)
231 return (it->result);
232 it->result = dns_dbiterator_current(it->dbit,
233 &it->node,
234 dns_fixedname_name(&it->fixedname));
235 if (it->result != ISC_R_SUCCESS)
236 return (it->result);
237 it->result = dns_db_allrdatasets(it->db, it->node,
238 it->ver, it->now,
239 &it->rdatasetit);
240 if (it->result != ISC_R_SUCCESS)
241 return (it->result);
242 it->result = dns_rdatasetiter_first(it->rdatasetit);
244 if (it->result != ISC_R_SUCCESS)
245 return (it->result);
246 dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
247 it->result = dns_rdataset_first(&it->rdataset);
248 if (it->result != ISC_R_SUCCESS)
249 return (it->result);
251 return (it->result);
254 static void
255 db_rr_iterator_pause(db_rr_iterator_t *it) {
256 dns_dbiterator_pause(it->dbit);
259 static void
260 db_rr_iterator_destroy(db_rr_iterator_t *it) {
261 if (dns_rdataset_isassociated(&it->rdataset))
262 dns_rdataset_disassociate(&it->rdataset);
263 if (it->rdatasetit != NULL)
264 dns_rdatasetiter_destroy(&it->rdatasetit);
265 if (it->node != NULL)
266 dns_db_detachnode(it->db, &it->node);
267 dns_dbiterator_destroy(&it->dbit);
270 static void
271 db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
272 isc_uint32_t *ttl, dns_rdata_t **rdata)
274 REQUIRE(name != NULL && *name == NULL);
275 REQUIRE(it->result == ISC_R_SUCCESS);
276 *name = dns_fixedname_name(&it->fixedname);
277 *ttl = it->rdataset.ttl;
278 dns_rdata_reset(&it->rdata);
279 dns_rdataset_current(&it->rdataset, &it->rdata);
280 *rdata = &it->rdata;
283 /**************************************************************************/
285 /* Log an RR (for debugging) */
287 static void
288 log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
289 isc_result_t result;
290 isc_buffer_t buf;
291 char mem[2000];
292 dns_rdatalist_t rdl;
293 dns_rdataset_t rds;
294 dns_rdata_t rd = DNS_RDATA_INIT;
296 rdl.type = rdata->type;
297 rdl.rdclass = rdata->rdclass;
298 rdl.ttl = ttl;
299 ISC_LIST_INIT(rdl.rdata);
300 ISC_LINK_INIT(&rdl, link);
301 dns_rdataset_init(&rds);
302 dns_rdata_init(&rd);
303 dns_rdata_clone(rdata, &rd);
304 ISC_LIST_APPEND(rdl.rdata, &rd, link);
305 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
307 isc_buffer_init(&buf, mem, sizeof(mem));
308 result = dns_rdataset_totext(&rds, name,
309 ISC_FALSE, ISC_FALSE, &buf);
312 * We could use xfrout_log(), but that would produce
313 * very long lines with a repetitive prefix.
315 if (result == ISC_R_SUCCESS) {
317 * Get rid of final newline.
319 INSIST(buf.used >= 1 &&
320 ((char *) buf.base)[buf.used - 1] == '\n');
321 buf.used--;
323 isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
324 (int)isc_buffer_usedlength(&buf),
325 (char *)isc_buffer_base(&buf));
326 } else {
327 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
331 /**************************************************************************/
333 * An 'rrstream_t' is a polymorphic iterator that returns
334 * a stream of resource records. There are multiple implementations,
335 * e.g. for generating AXFR and IXFR records streams.
338 typedef struct rrstream_methods rrstream_methods_t;
340 typedef struct rrstream {
341 isc_mem_t *mctx;
342 rrstream_methods_t *methods;
343 } rrstream_t;
345 struct rrstream_methods {
346 isc_result_t (*first)(rrstream_t *);
347 isc_result_t (*next)(rrstream_t *);
348 void (*current)(rrstream_t *,
349 dns_name_t **,
350 isc_uint32_t *,
351 dns_rdata_t **);
352 void (*pause)(rrstream_t *);
353 void (*destroy)(rrstream_t **);
356 static void
357 rrstream_noop_pause(rrstream_t *rs) {
358 UNUSED(rs);
361 /**************************************************************************/
363 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
364 * an IXFR-like RR stream from a journal file.
366 * The SOA at the beginning of each sequence of additions
367 * or deletions are included in the stream, but the extra
368 * SOAs at the beginning and end of the entire transfer are
369 * not included.
372 typedef struct ixfr_rrstream {
373 rrstream_t common;
374 dns_journal_t *journal;
375 } ixfr_rrstream_t;
377 /* Forward declarations. */
378 static void
379 ixfr_rrstream_destroy(rrstream_t **sp);
381 static rrstream_methods_t ixfr_rrstream_methods;
384 * Returns: anything dns_journal_open() or dns_journal_iter_init()
385 * may return.
388 static isc_result_t
389 ixfr_rrstream_create(isc_mem_t *mctx,
390 const char *journal_filename,
391 isc_uint32_t begin_serial,
392 isc_uint32_t end_serial,
393 rrstream_t **sp)
395 ixfr_rrstream_t *s;
396 isc_result_t result;
398 INSIST(sp != NULL && *sp == NULL);
400 s = isc_mem_get(mctx, sizeof(*s));
401 if (s == NULL)
402 return (ISC_R_NOMEMORY);
403 s->common.mctx = mctx;
404 s->common.methods = &ixfr_rrstream_methods;
405 s->journal = NULL;
407 CHECK(dns_journal_open(mctx, journal_filename,
408 ISC_FALSE, &s->journal));
409 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
411 *sp = (rrstream_t *) s;
412 return (ISC_R_SUCCESS);
414 failure:
415 ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
416 return (result);
419 static isc_result_t
420 ixfr_rrstream_first(rrstream_t *rs) {
421 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
422 return (dns_journal_first_rr(s->journal));
425 static isc_result_t
426 ixfr_rrstream_next(rrstream_t *rs) {
427 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
428 return (dns_journal_next_rr(s->journal));
431 static void
432 ixfr_rrstream_current(rrstream_t *rs,
433 dns_name_t **name, isc_uint32_t *ttl,
434 dns_rdata_t **rdata)
436 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
437 dns_journal_current_rr(s->journal, name, ttl, rdata);
440 static void
441 ixfr_rrstream_destroy(rrstream_t **rsp) {
442 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
443 if (s->journal != 0)
444 dns_journal_destroy(&s->journal);
445 isc_mem_put(s->common.mctx, s, sizeof(*s));
448 static rrstream_methods_t ixfr_rrstream_methods = {
449 ixfr_rrstream_first,
450 ixfr_rrstream_next,
451 ixfr_rrstream_current,
452 rrstream_noop_pause,
453 ixfr_rrstream_destroy
456 /**************************************************************************/
458 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
459 * an AXFR-like RR stream from a database.
461 * The SOAs at the beginning and end of the transfer are
462 * not included in the stream.
465 typedef struct axfr_rrstream {
466 rrstream_t common;
467 db_rr_iterator_t it;
468 isc_boolean_t it_valid;
469 } axfr_rrstream_t;
472 * Forward declarations.
474 static void
475 axfr_rrstream_destroy(rrstream_t **rsp);
477 static rrstream_methods_t axfr_rrstream_methods;
479 static isc_result_t
480 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
481 rrstream_t **sp)
483 axfr_rrstream_t *s;
484 isc_result_t result;
486 INSIST(sp != NULL && *sp == NULL);
488 s = isc_mem_get(mctx, sizeof(*s));
489 if (s == NULL)
490 return (ISC_R_NOMEMORY);
491 s->common.mctx = mctx;
492 s->common.methods = &axfr_rrstream_methods;
493 s->it_valid = ISC_FALSE;
495 CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
496 s->it_valid = ISC_TRUE;
498 *sp = (rrstream_t *) s;
499 return (ISC_R_SUCCESS);
501 failure:
502 axfr_rrstream_destroy((rrstream_t **) (void *)&s);
503 return (result);
506 static isc_result_t
507 axfr_rrstream_first(rrstream_t *rs) {
508 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
509 isc_result_t result;
510 result = db_rr_iterator_first(&s->it);
511 if (result != ISC_R_SUCCESS)
512 return (result);
513 /* Skip SOA records. */
514 for (;;) {
515 dns_name_t *name_dummy = NULL;
516 isc_uint32_t ttl_dummy;
517 dns_rdata_t *rdata = NULL;
518 db_rr_iterator_current(&s->it, &name_dummy,
519 &ttl_dummy, &rdata);
520 if (rdata->type != dns_rdatatype_soa)
521 break;
522 result = db_rr_iterator_next(&s->it);
523 if (result != ISC_R_SUCCESS)
524 break;
526 return (result);
529 static isc_result_t
530 axfr_rrstream_next(rrstream_t *rs) {
531 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
532 isc_result_t result;
534 /* Skip SOA records. */
535 for (;;) {
536 dns_name_t *name_dummy = NULL;
537 isc_uint32_t ttl_dummy;
538 dns_rdata_t *rdata = NULL;
539 result = db_rr_iterator_next(&s->it);
540 if (result != ISC_R_SUCCESS)
541 break;
542 db_rr_iterator_current(&s->it, &name_dummy,
543 &ttl_dummy, &rdata);
544 if (rdata->type != dns_rdatatype_soa)
545 break;
547 return (result);
550 static void
551 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
552 dns_rdata_t **rdata)
554 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
555 db_rr_iterator_current(&s->it, name, ttl, rdata);
558 static void
559 axfr_rrstream_pause(rrstream_t *rs) {
560 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
561 db_rr_iterator_pause(&s->it);
564 static void
565 axfr_rrstream_destroy(rrstream_t **rsp) {
566 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
567 if (s->it_valid)
568 db_rr_iterator_destroy(&s->it);
569 isc_mem_put(s->common.mctx, s, sizeof(*s));
572 static rrstream_methods_t axfr_rrstream_methods = {
573 axfr_rrstream_first,
574 axfr_rrstream_next,
575 axfr_rrstream_current,
576 axfr_rrstream_pause,
577 axfr_rrstream_destroy
580 /**************************************************************************/
582 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
583 * a single SOA record.
586 typedef struct soa_rrstream {
587 rrstream_t common;
588 dns_difftuple_t *soa_tuple;
589 } soa_rrstream_t;
592 * Forward declarations.
594 static void
595 soa_rrstream_destroy(rrstream_t **rsp);
597 static rrstream_methods_t soa_rrstream_methods;
599 static isc_result_t
600 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
601 rrstream_t **sp)
603 soa_rrstream_t *s;
604 isc_result_t result;
606 INSIST(sp != NULL && *sp == NULL);
608 s = isc_mem_get(mctx, sizeof(*s));
609 if (s == NULL)
610 return (ISC_R_NOMEMORY);
611 s->common.mctx = mctx;
612 s->common.methods = &soa_rrstream_methods;
613 s->soa_tuple = NULL;
615 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
616 &s->soa_tuple));
618 *sp = (rrstream_t *) s;
619 return (ISC_R_SUCCESS);
621 failure:
622 soa_rrstream_destroy((rrstream_t **) (void *)&s);
623 return (result);
626 static isc_result_t
627 soa_rrstream_first(rrstream_t *rs) {
628 UNUSED(rs);
629 return (ISC_R_SUCCESS);
632 static isc_result_t
633 soa_rrstream_next(rrstream_t *rs) {
634 UNUSED(rs);
635 return (ISC_R_NOMORE);
638 static void
639 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
640 dns_rdata_t **rdata)
642 soa_rrstream_t *s = (soa_rrstream_t *) rs;
643 *name = &s->soa_tuple->name;
644 *ttl = s->soa_tuple->ttl;
645 *rdata = &s->soa_tuple->rdata;
648 static void
649 soa_rrstream_destroy(rrstream_t **rsp) {
650 soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
651 if (s->soa_tuple != NULL)
652 dns_difftuple_free(&s->soa_tuple);
653 isc_mem_put(s->common.mctx, s, sizeof(*s));
656 static rrstream_methods_t soa_rrstream_methods = {
657 soa_rrstream_first,
658 soa_rrstream_next,
659 soa_rrstream_current,
660 rrstream_noop_pause,
661 soa_rrstream_destroy
664 /**************************************************************************/
666 * A 'compound_rrstream_t' objects owns a soa_rrstream
667 * and another rrstream, the "data stream". It returns
668 * a concatenated stream consisting of the soa_rrstream, then
669 * the data stream, then the soa_rrstream again.
671 * The component streams are owned by the compound_rrstream_t
672 * and are destroyed with it.
675 typedef struct compound_rrstream {
676 rrstream_t common;
677 rrstream_t *components[3];
678 int state;
679 isc_result_t result;
680 } compound_rrstream_t;
683 * Forward declarations.
685 static void
686 compound_rrstream_destroy(rrstream_t **rsp);
688 static isc_result_t
689 compound_rrstream_next(rrstream_t *rs);
691 static rrstream_methods_t compound_rrstream_methods;
694 * Requires:
695 * soa_stream != NULL && *soa_stream != NULL
696 * data_stream != NULL && *data_stream != NULL
697 * sp != NULL && *sp == NULL
699 * Ensures:
700 * *soa_stream == NULL
701 * *data_stream == NULL
702 * *sp points to a valid compound_rrstream_t
703 * The soa and data streams will be destroyed
704 * when the compound_rrstream_t is destroyed.
706 static isc_result_t
707 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
708 rrstream_t **data_stream, rrstream_t **sp)
710 compound_rrstream_t *s;
712 INSIST(sp != NULL && *sp == NULL);
714 s = isc_mem_get(mctx, sizeof(*s));
715 if (s == NULL)
716 return (ISC_R_NOMEMORY);
717 s->common.mctx = mctx;
718 s->common.methods = &compound_rrstream_methods;
719 s->components[0] = *soa_stream;
720 s->components[1] = *data_stream;
721 s->components[2] = *soa_stream;
722 s->state = -1;
723 s->result = ISC_R_FAILURE;
725 *soa_stream = NULL;
726 *data_stream = NULL;
727 *sp = (rrstream_t *) s;
728 return (ISC_R_SUCCESS);
731 static isc_result_t
732 compound_rrstream_first(rrstream_t *rs) {
733 compound_rrstream_t *s = (compound_rrstream_t *) rs;
734 s->state = 0;
735 do {
736 rrstream_t *curstream = s->components[s->state];
737 s->result = curstream->methods->first(curstream);
738 } while (s->result == ISC_R_NOMORE && s->state < 2) ;
739 return (s->result);
742 static isc_result_t
743 compound_rrstream_next(rrstream_t *rs) {
744 compound_rrstream_t *s = (compound_rrstream_t *) rs;
745 rrstream_t *curstream = s->components[s->state];
746 s->result = curstream->methods->next(curstream);
747 while (s->result == ISC_R_NOMORE) {
749 * Make sure locks held by the current stream
750 * are released before we switch streams.
752 curstream->methods->pause(curstream);
753 if (s->state == 2)
754 return (ISC_R_NOMORE);
755 s->state++;
756 curstream = s->components[s->state];
757 s->result = curstream->methods->first(curstream);
759 return (s->result);
762 static void
763 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
764 dns_rdata_t **rdata)
766 compound_rrstream_t *s = (compound_rrstream_t *) rs;
767 rrstream_t *curstream;
768 INSIST(0 <= s->state && s->state < 3);
769 INSIST(s->result == ISC_R_SUCCESS);
770 curstream = s->components[s->state];
771 curstream->methods->current(curstream, name, ttl, rdata);
774 static void
775 compound_rrstream_pause(rrstream_t *rs)
777 compound_rrstream_t *s = (compound_rrstream_t *) rs;
778 rrstream_t *curstream;
779 INSIST(0 <= s->state && s->state < 3);
780 curstream = s->components[s->state];
781 curstream->methods->pause(curstream);
784 static void
785 compound_rrstream_destroy(rrstream_t **rsp) {
786 compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
787 s->components[0]->methods->destroy(&s->components[0]);
788 s->components[1]->methods->destroy(&s->components[1]);
789 s->components[2] = NULL; /* Copy of components[0]. */
790 isc_mem_put(s->common.mctx, s, sizeof(*s));
793 static rrstream_methods_t compound_rrstream_methods = {
794 compound_rrstream_first,
795 compound_rrstream_next,
796 compound_rrstream_current,
797 compound_rrstream_pause,
798 compound_rrstream_destroy
801 /**************************************************************************/
803 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
804 * in progress.
807 typedef struct {
808 isc_mem_t *mctx;
809 ns_client_t *client;
810 unsigned int id; /* ID of request */
811 dns_name_t *qname; /* Question name of request */
812 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
813 dns_rdataclass_t qclass;
814 dns_db_t *db;
815 dns_dbversion_t *ver;
816 isc_quota_t *quota;
817 rrstream_t *stream; /* The XFR RR stream */
818 isc_boolean_t end_of_stream; /* EOS has been reached */
819 isc_buffer_t buf; /* Buffer for message owner
820 names and rdatas */
821 isc_buffer_t txlenbuf; /* Transmit length buffer */
822 isc_buffer_t txbuf; /* Transmit message buffer */
823 void *txmem;
824 unsigned int txmemlen;
825 unsigned int nmsg; /* Number of messages sent */
826 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
827 isc_buffer_t *lasttsig; /* the last TSIG */
828 isc_boolean_t many_answers;
829 int sends; /* Send in progress */
830 isc_boolean_t shuttingdown;
831 } xfrout_ctx_t;
833 static isc_result_t
834 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
835 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
836 dns_rdataclass_t qclass,
837 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
838 rrstream_t *stream, dns_tsigkey_t *tsigkey,
839 isc_buffer_t *lasttsig,
840 unsigned int maxtime,
841 unsigned int idletime,
842 isc_boolean_t many_answers,
843 xfrout_ctx_t **xfrp);
845 static void
846 sendstream(xfrout_ctx_t *xfr);
848 static void
849 xfrout_senddone(isc_task_t *task, isc_event_t *event);
851 static void
852 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
854 static void
855 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
857 static void
858 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
860 static void
861 xfrout_client_shutdown(void *arg, isc_result_t result);
863 static void
864 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
865 dns_rdataclass_t rdclass, int level,
866 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
868 static void
869 xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...)
870 ISC_FORMAT_PRINTF(3, 4);
872 /**************************************************************************/
874 void
875 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
876 isc_result_t result;
877 dns_name_t *question_name;
878 dns_rdataset_t *question_rdataset;
879 dns_zone_t *zone = NULL;
880 dns_db_t *db = NULL;
881 dns_dbversion_t *ver = NULL;
882 dns_rdataclass_t question_class;
883 rrstream_t *soa_stream = NULL;
884 rrstream_t *data_stream = NULL;
885 rrstream_t *stream = NULL;
886 dns_difftuple_t *current_soa_tuple = NULL;
887 dns_name_t *soa_name;
888 dns_rdataset_t *soa_rdataset;
889 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
890 isc_boolean_t have_soa = ISC_FALSE;
891 const char *mnemonic = NULL;
892 isc_mem_t *mctx = client->mctx;
893 dns_message_t *request = client->message;
894 xfrout_ctx_t *xfr = NULL;
895 isc_quota_t *quota = NULL;
896 dns_transfer_format_t format = client->view->transfer_format;
897 isc_netaddr_t na;
898 dns_peer_t *peer = NULL;
899 isc_buffer_t *tsigbuf = NULL;
900 char *journalfile;
901 char msg[DNS_RDATACLASS_FORMATSIZE + DNS_NAME_FORMATSIZE
902 + sizeof("zone transfer '/'")];
903 isc_boolean_t is_poll = ISC_FALSE;
905 switch (reqtype) {
906 case dns_rdatatype_axfr:
907 mnemonic = "AXFR";
908 break;
909 case dns_rdatatype_ixfr:
910 mnemonic = "IXFR";
911 break;
912 default:
913 INSIST(0);
914 break;
917 ns_client_log(client,
918 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
919 ISC_LOG_DEBUG(6), "%s request", mnemonic);
921 * Apply quota.
923 result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
924 if (result != ISC_R_SUCCESS) {
925 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
926 "%s request denied: %s", mnemonic,
927 isc_result_totext(result));
928 goto failure;
932 * Interpret the question section.
934 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
935 INSIST(result == ISC_R_SUCCESS);
938 * The question section must contain exactly one question, and
939 * it must be for AXFR/IXFR as appropriate.
941 question_name = NULL;
942 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
943 question_rdataset = ISC_LIST_HEAD(question_name->list);
944 question_class = question_rdataset->rdclass;
945 INSIST(question_rdataset->type == reqtype);
946 if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
947 FAILC(DNS_R_FORMERR, "multiple questions");
948 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
949 if (result != ISC_R_NOMORE)
950 FAILC(DNS_R_FORMERR, "multiple questions");
952 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
953 &zone);
954 if (result != ISC_R_SUCCESS)
955 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
956 question_name, question_class);
957 switch(dns_zone_gettype(zone)) {
958 case dns_zone_master:
959 case dns_zone_slave:
960 break; /* Master and slave zones are OK for transfer. */
961 default:
962 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
963 question_name, question_class);
965 CHECK(dns_zone_getdb(zone, &db));
966 dns_db_currentversion(db, &ver);
968 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
969 "%s question section OK", mnemonic);
972 * Check the authority section. Look for a SOA record with
973 * the same name and class as the question.
975 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
976 result == ISC_R_SUCCESS;
977 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
979 soa_name = NULL;
980 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
981 &soa_name);
984 * Ignore data whose owner name is not the zone apex.
986 if (! dns_name_equal(soa_name, question_name))
987 continue;
989 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
990 soa_rdataset != NULL;
991 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
994 * Ignore non-SOA data.
996 if (soa_rdataset->type != dns_rdatatype_soa)
997 continue;
998 if (soa_rdataset->rdclass != question_class)
999 continue;
1001 CHECK(dns_rdataset_first(soa_rdataset));
1002 dns_rdataset_current(soa_rdataset, &soa_rdata);
1003 result = dns_rdataset_next(soa_rdataset);
1004 if (result == ISC_R_SUCCESS)
1005 FAILC(DNS_R_FORMERR,
1006 "IXFR authority section "
1007 "has multiple SOAs");
1008 have_soa = ISC_TRUE;
1009 goto got_soa;
1012 got_soa:
1013 if (result != ISC_R_NOMORE)
1014 CHECK(result);
1016 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
1017 "%s authority section OK", mnemonic);
1020 * Decide whether to allow this transfer.
1022 ns_client_aclmsg("zone transfer", question_name,
1023 client->view->rdclass, msg, sizeof(msg));
1024 CHECK(ns_client_checkacl(client, msg,
1025 dns_zone_getxfracl(zone), ISC_TRUE,
1026 ISC_LOG_ERROR));
1029 * AXFR over UDP is not possible.
1031 if (reqtype == dns_rdatatype_axfr &&
1032 (client->attributes & NS_CLIENTATTR_TCP) == 0)
1033 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
1036 * Look up the requesting server in the peer table.
1038 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
1039 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
1042 * Decide on the transfer format (one-answer or many-answers).
1044 if (peer != NULL)
1045 (void)dns_peer_gettransferformat(peer, &format);
1048 * Get a dynamically allocated copy of the current SOA.
1050 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
1051 &current_soa_tuple));
1053 if (reqtype == dns_rdatatype_ixfr) {
1054 isc_uint32_t begin_serial, current_serial;
1055 isc_boolean_t provide_ixfr;
1058 * Outgoing IXFR may have been disabled for this peer
1059 * or globally.
1061 provide_ixfr = client->view->provideixfr;
1062 if (peer != NULL)
1063 (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
1064 if (provide_ixfr == ISC_FALSE)
1065 goto axfr_fallback;
1067 if (! have_soa)
1068 FAILC(DNS_R_FORMERR,
1069 "IXFR request missing SOA");
1071 begin_serial = dns_soa_getserial(&soa_rdata);
1072 current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
1075 * RFC1995 says "If an IXFR query with the same or
1076 * newer version number than that of the server
1077 * is received, it is replied to with a single SOA
1078 * record of the server's current version, just as
1079 * in AXFR". The claim about AXFR is incorrect,
1080 * but other than that, we do as the RFC says.
1082 * Sending a single SOA record is also how we refuse
1083 * IXFR over UDP (currently, we always do).
1085 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
1086 (client->attributes & NS_CLIENTATTR_TCP) == 0)
1088 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
1089 is_poll = ISC_TRUE;
1090 goto have_stream;
1092 journalfile = dns_zone_getjournal(zone);
1093 if (journalfile != NULL)
1094 result = ixfr_rrstream_create(mctx,
1095 journalfile,
1096 begin_serial,
1097 current_serial,
1098 &data_stream);
1099 else
1100 result = ISC_R_NOTFOUND;
1101 if (result == ISC_R_NOTFOUND ||
1102 result == ISC_R_RANGE) {
1103 xfrout_log1(client, question_name, question_class,
1104 ISC_LOG_DEBUG(4),
1105 "IXFR version not in journal, "
1106 "falling back to AXFR");
1107 mnemonic = "AXFR-style IXFR";
1108 goto axfr_fallback;
1110 CHECK(result);
1111 } else {
1112 axfr_fallback:
1113 CHECK(axfr_rrstream_create(mctx, db, ver,
1114 &data_stream));
1118 * Bracket the the data stream with SOAs.
1120 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1121 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1122 &stream));
1123 soa_stream = NULL;
1124 data_stream = NULL;
1126 have_stream:
1127 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1129 * Create the xfrout context object. This transfers the ownership
1130 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1132 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1133 reqtype, question_class, db, ver, quota,
1134 stream, dns_message_gettsigkey(request),
1135 tsigbuf,
1136 dns_zone_getmaxxfrout(zone),
1137 dns_zone_getidleout(zone),
1138 (format == dns_many_answers) ?
1139 ISC_TRUE : ISC_FALSE,
1140 &xfr));
1141 stream = NULL;
1142 quota = NULL;
1144 CHECK(xfr->stream->methods->first(xfr->stream));
1146 if (is_poll)
1147 xfrout_log1(client, question_name, question_class,
1148 ISC_LOG_DEBUG(1), "IXFR poll up to date");
1149 else
1150 xfrout_log1(client, question_name, question_class,
1151 ISC_LOG_INFO, "%s started", mnemonic);
1154 * Hand the context over to sendstream(). Set xfr to NULL;
1155 * sendstream() is responsible for either passing the
1156 * context on to a later event handler or destroying it.
1158 sendstream(xfr);
1159 xfr = NULL;
1161 result = ISC_R_SUCCESS;
1163 failure:
1164 if (quota != NULL)
1165 isc_quota_detach(&quota);
1166 if (current_soa_tuple != NULL)
1167 dns_difftuple_free(&current_soa_tuple);
1168 if (stream != NULL)
1169 stream->methods->destroy(&stream);
1170 if (soa_stream != NULL)
1171 soa_stream->methods->destroy(&soa_stream);
1172 if (data_stream != NULL)
1173 data_stream->methods->destroy(&data_stream);
1174 if (ver != NULL)
1175 dns_db_closeversion(db, &ver, ISC_FALSE);
1176 if (db != NULL)
1177 dns_db_detach(&db);
1178 if (zone != NULL)
1179 dns_zone_detach(&zone);
1180 /* XXX kludge */
1181 if (xfr != NULL) {
1182 xfrout_fail(xfr, result, "setting up zone transfer");
1183 } else if (result != ISC_R_SUCCESS) {
1184 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1185 NS_LOGMODULE_XFER_OUT,
1186 ISC_LOG_DEBUG(3), "zone transfer setup failed");
1187 ns_client_error(client, result);
1191 static isc_result_t
1192 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1193 dns_name_t *qname, dns_rdatatype_t qtype,
1194 dns_rdataclass_t qclass,
1195 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
1196 rrstream_t *stream, dns_tsigkey_t *tsigkey,
1197 isc_buffer_t *lasttsig, unsigned int maxtime,
1198 unsigned int idletime, isc_boolean_t many_answers,
1199 xfrout_ctx_t **xfrp)
1201 xfrout_ctx_t *xfr;
1202 isc_result_t result;
1203 unsigned int len;
1204 void *mem;
1206 INSIST(xfrp != NULL && *xfrp == NULL);
1207 xfr = isc_mem_get(mctx, sizeof(*xfr));
1208 if (xfr == NULL)
1209 return (ISC_R_NOMEMORY);
1210 xfr->mctx = mctx;
1211 xfr->client = NULL;
1212 ns_client_attach(client, &xfr->client);
1213 xfr->id = id;
1214 xfr->qname = qname;
1215 xfr->qtype = qtype;
1216 xfr->qclass = qclass;
1217 xfr->db = NULL;
1218 xfr->ver = NULL;
1219 dns_db_attach(db, &xfr->db);
1220 dns_db_attachversion(db, ver, &xfr->ver);
1221 xfr->end_of_stream = ISC_FALSE;
1222 xfr->tsigkey = tsigkey;
1223 xfr->lasttsig = lasttsig;
1224 xfr->txmem = NULL;
1225 xfr->txmemlen = 0;
1226 xfr->nmsg = 0;
1227 xfr->many_answers = many_answers,
1228 xfr->sends = 0;
1229 xfr->shuttingdown = ISC_FALSE;
1230 xfr->buf.base = NULL;
1231 xfr->buf.length = 0;
1232 xfr->txmem = NULL;
1233 xfr->txmemlen = 0;
1234 xfr->stream = NULL;
1235 xfr->quota = NULL;
1238 * Allocate a temporary buffer for the uncompressed response
1239 * message data. The size should be no more than 65535 bytes
1240 * so that the compressed data will fit in a TCP message,
1241 * and no less than 65535 bytes so that an almost maximum-sized
1242 * RR will fit. Note that although 65535-byte RRs are allowed
1243 * in principle, they cannot be zone-transferred (at least not
1244 * if uncompressible), because the message and RR headers would
1245 * push the size of the TCP message over the 65536 byte limit.
1247 len = 65535;
1248 mem = isc_mem_get(mctx, len);
1249 if (mem == NULL) {
1250 result = ISC_R_NOMEMORY;
1251 goto failure;
1253 isc_buffer_init(&xfr->buf, mem, len);
1256 * Allocate another temporary buffer for the compressed
1257 * response message and its TCP length prefix.
1259 len = 2 + 65535;
1260 mem = isc_mem_get(mctx, len);
1261 if (mem == NULL) {
1262 result = ISC_R_NOMEMORY;
1263 goto failure;
1265 isc_buffer_init(&xfr->txlenbuf, mem, 2);
1266 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
1267 xfr->txmem = mem;
1268 xfr->txmemlen = len;
1270 CHECK(dns_timer_setidle(xfr->client->timer,
1271 maxtime, idletime, ISC_FALSE));
1274 * Register a shutdown callback with the client, so that we
1275 * can stop the transfer immediately when the client task
1276 * gets a shutdown event.
1278 xfr->client->shutdown = xfrout_client_shutdown;
1279 xfr->client->shutdown_arg = xfr;
1281 * These MUST be after the last "goto failure;" / CHECK to
1282 * prevent a double free by the caller.
1284 xfr->quota = quota;
1285 xfr->stream = stream;
1287 *xfrp = xfr;
1288 return (ISC_R_SUCCESS);
1290 failure:
1291 xfrout_ctx_destroy(&xfr);
1292 return (result);
1297 * Arrange to send as much as we can of "stream" without blocking.
1299 * Requires:
1300 * The stream iterator is initialized and points at an RR,
1301 * or possiby at the end of the stream (that is, the
1302 * _first method of the iterator has been called).
1304 static void
1305 sendstream(xfrout_ctx_t *xfr) {
1306 dns_message_t *tcpmsg = NULL;
1307 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1308 isc_result_t result;
1309 isc_region_t used;
1310 isc_region_t region;
1311 dns_rdataset_t *qrdataset;
1312 dns_name_t *msgname = NULL;
1313 dns_rdata_t *msgrdata = NULL;
1314 dns_rdatalist_t *msgrdl = NULL;
1315 dns_rdataset_t *msgrds = NULL;
1316 dns_compress_t cctx;
1317 isc_boolean_t cleanup_cctx = ISC_FALSE;
1319 int n_rrs;
1321 isc_buffer_clear(&xfr->buf);
1322 isc_buffer_clear(&xfr->txlenbuf);
1323 isc_buffer_clear(&xfr->txbuf);
1325 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
1327 * In the UDP case, we put the response data directly into
1328 * the client message.
1330 msg = xfr->client->message;
1331 CHECK(dns_message_reply(msg, ISC_TRUE));
1332 } else {
1334 * TCP. Build a response dns_message_t, temporarily storing
1335 * the raw, uncompressed owner names and RR data contiguously
1336 * in xfr->buf. We know that if the uncompressed data fits
1337 * in xfr->buf, the compressed data will surely fit in a TCP
1338 * message.
1341 CHECK(dns_message_create(xfr->mctx,
1342 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
1343 msg = tcpmsg;
1345 msg->id = xfr->id;
1346 msg->rcode = dns_rcode_noerror;
1347 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1348 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
1349 msg->flags |= DNS_MESSAGEFLAG_RA;
1350 dns_message_settsigkey(msg, xfr->tsigkey);
1351 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1352 if (xfr->lasttsig != NULL)
1353 isc_buffer_free(&xfr->lasttsig);
1356 * Include a question section in the first message only.
1357 * BIND 8.2.1 will not recognize an IXFR if it does not
1358 * have a question section.
1360 if (xfr->nmsg == 0) {
1361 dns_name_t *qname = NULL;
1362 isc_region_t r;
1365 * Reserve space for the 12-byte message header
1366 * and 4 bytes of question.
1368 isc_buffer_add(&xfr->buf, 12 + 4);
1370 qrdataset = NULL;
1371 result = dns_message_gettemprdataset(msg, &qrdataset);
1372 if (result != ISC_R_SUCCESS)
1373 goto failure;
1374 dns_rdataset_init(qrdataset);
1375 dns_rdataset_makequestion(qrdataset,
1376 xfr->client->message->rdclass,
1377 xfr->qtype);
1379 result = dns_message_gettempname(msg, &qname);
1380 if (result != ISC_R_SUCCESS)
1381 goto failure;
1382 dns_name_init(qname, NULL);
1383 isc_buffer_availableregion(&xfr->buf, &r);
1384 INSIST(r.length >= xfr->qname->length);
1385 r.length = xfr->qname->length;
1386 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1387 xfr->qname->length);
1388 dns_name_fromregion(qname, &r);
1389 ISC_LIST_INIT(qname->list);
1390 ISC_LIST_APPEND(qname->list, qrdataset, link);
1392 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1394 else
1395 msg->tcp_continuation = 1;
1399 * Try to fit in as many RRs as possible, unless "one-answer"
1400 * format has been requested.
1402 for (n_rrs = 0; ; n_rrs++) {
1403 dns_name_t *name = NULL;
1404 isc_uint32_t ttl;
1405 dns_rdata_t *rdata = NULL;
1407 unsigned int size;
1408 isc_region_t r;
1410 msgname = NULL;
1411 msgrdata = NULL;
1412 msgrdl = NULL;
1413 msgrds = NULL;
1415 xfr->stream->methods->current(xfr->stream,
1416 &name, &ttl, &rdata);
1417 size = name->length + 10 + rdata->length;
1418 isc_buffer_availableregion(&xfr->buf, &r);
1419 if (size >= r.length) {
1421 * RR would not fit. If there are other RRs in the
1422 * buffer, send them now and leave this RR to the
1423 * next message. If this RR overflows the buffer
1424 * all by itself, fail.
1426 * In theory some RRs might fit in a TCP message
1427 * when compressed even if they do not fit when
1428 * uncompressed, but surely we don't want
1429 * to send such monstrosities to an unsuspecting
1430 * slave.
1432 if (n_rrs == 0) {
1433 xfrout_log(xfr, ISC_LOG_WARNING,
1434 "RR too large for zone transfer "
1435 "(%d bytes)", size);
1436 /* XXX DNS_R_RRTOOLARGE? */
1437 result = ISC_R_NOSPACE;
1438 goto failure;
1440 break;
1443 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
1444 log_rr(name, rdata, ttl); /* XXX */
1446 result = dns_message_gettempname(msg, &msgname);
1447 if (result != ISC_R_SUCCESS)
1448 goto failure;
1449 dns_name_init(msgname, NULL);
1450 isc_buffer_availableregion(&xfr->buf, &r);
1451 INSIST(r.length >= name->length);
1452 r.length = name->length;
1453 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1454 dns_name_fromregion(msgname, &r);
1456 /* Reserve space for RR header. */
1457 isc_buffer_add(&xfr->buf, 10);
1459 result = dns_message_gettemprdata(msg, &msgrdata);
1460 if (result != ISC_R_SUCCESS)
1461 goto failure;
1462 isc_buffer_availableregion(&xfr->buf, &r);
1463 r.length = rdata->length;
1464 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1465 dns_rdata_init(msgrdata);
1466 dns_rdata_fromregion(msgrdata,
1467 rdata->rdclass, rdata->type, &r);
1469 result = dns_message_gettemprdatalist(msg, &msgrdl);
1470 if (result != ISC_R_SUCCESS)
1471 goto failure;
1472 msgrdl->type = rdata->type;
1473 msgrdl->rdclass = rdata->rdclass;
1474 msgrdl->ttl = ttl;
1475 ISC_LINK_INIT(msgrdl, link);
1476 ISC_LIST_INIT(msgrdl->rdata);
1477 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1479 result = dns_message_gettemprdataset(msg, &msgrds);
1480 if (result != ISC_R_SUCCESS)
1481 goto failure;
1482 dns_rdataset_init(msgrds);
1483 result = dns_rdatalist_tordataset(msgrdl, msgrds);
1484 INSIST(result == ISC_R_SUCCESS);
1486 ISC_LIST_APPEND(msgname->list, msgrds, link);
1488 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1489 msgname = NULL;
1491 result = xfr->stream->methods->next(xfr->stream);
1492 if (result == ISC_R_NOMORE) {
1493 xfr->end_of_stream = ISC_TRUE;
1494 break;
1496 CHECK(result);
1498 if (! xfr->many_answers)
1499 break;
1502 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
1503 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1504 cleanup_cctx = ISC_TRUE;
1505 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1506 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1507 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1508 CHECK(dns_message_renderend(msg));
1509 dns_compress_invalidate(&cctx);
1510 cleanup_cctx = ISC_FALSE;
1512 isc_buffer_usedregion(&xfr->txbuf, &used);
1513 isc_buffer_putuint16(&xfr->txlenbuf,
1514 (isc_uint16_t)used.length);
1515 region.base = xfr->txlenbuf.base;
1516 region.length = 2 + used.length;
1517 xfrout_log(xfr, ISC_LOG_DEBUG(8),
1518 "sending TCP message of %d bytes",
1519 used.length);
1520 CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
1521 &region, xfr->client->task,
1522 xfrout_senddone,
1523 xfr));
1524 xfr->sends++;
1525 } else {
1526 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1527 ns_client_send(xfr->client);
1528 xfr->stream->methods->pause(xfr->stream);
1529 xfrout_ctx_destroy(&xfr);
1530 return;
1533 /* Advance lasttsig to be the last TSIG generated */
1534 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1536 xfr->nmsg++;
1538 failure:
1539 if (msgname != NULL) {
1540 if (msgrds != NULL) {
1541 if (dns_rdataset_isassociated(msgrds))
1542 dns_rdataset_disassociate(msgrds);
1543 dns_message_puttemprdataset(msg, &msgrds);
1545 if (msgrdl != NULL) {
1546 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1547 dns_message_puttemprdatalist(msg, &msgrdl);
1549 if (msgrdata != NULL)
1550 dns_message_puttemprdata(msg, &msgrdata);
1551 dns_message_puttempname(msg, &msgname);
1554 if (tcpmsg != NULL)
1555 dns_message_destroy(&tcpmsg);
1557 if (cleanup_cctx)
1558 dns_compress_invalidate(&cctx);
1560 * Make sure to release any locks held by database
1561 * iterators before returning from the event handler.
1563 xfr->stream->methods->pause(xfr->stream);
1565 if (result == ISC_R_SUCCESS)
1566 return;
1568 xfrout_fail(xfr, result, "sending zone data");
1571 static void
1572 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1573 xfrout_ctx_t *xfr = *xfrp;
1575 INSIST(xfr->sends == 0);
1577 xfr->client->shutdown = NULL;
1578 xfr->client->shutdown_arg = NULL;
1580 if (xfr->stream != NULL)
1581 xfr->stream->methods->destroy(&xfr->stream);
1582 if (xfr->buf.base != NULL)
1583 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1584 if (xfr->txmem != NULL)
1585 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1586 if (xfr->lasttsig != NULL)
1587 isc_buffer_free(&xfr->lasttsig);
1588 if (xfr->quota != NULL)
1589 isc_quota_detach(&xfr->quota);
1590 if (xfr->ver != NULL)
1591 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1592 if (xfr->db != NULL)
1593 dns_db_detach(&xfr->db);
1595 ns_client_detach(&xfr->client);
1597 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1599 *xfrp = NULL;
1602 static void
1603 xfrout_senddone(isc_task_t *task, isc_event_t *event) {
1604 isc_socketevent_t *sev = (isc_socketevent_t *)event;
1605 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
1606 isc_result_t evresult = sev->result;
1608 UNUSED(task);
1610 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1612 isc_event_free(&event);
1613 xfr->sends--;
1614 INSIST(xfr->sends == 0);
1616 (void)isc_timer_touch(xfr->client->timer);
1617 if (xfr->shuttingdown == ISC_TRUE) {
1618 xfrout_maybe_destroy(xfr);
1619 } else if (evresult != ISC_R_SUCCESS) {
1620 xfrout_fail(xfr, evresult, "send");
1621 } else if (xfr->end_of_stream == ISC_FALSE) {
1622 sendstream(xfr);
1623 } else {
1624 /* End of zone transfer stream. */
1625 xfrout_log(xfr, ISC_LOG_DEBUG(6),
1626 "end of transfer");
1627 ns_client_next(xfr->client, ISC_R_SUCCESS);
1628 xfrout_ctx_destroy(&xfr);
1632 static void
1633 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1634 xfr->shuttingdown = ISC_TRUE;
1635 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
1636 msg, isc_result_totext(result));
1637 xfrout_maybe_destroy(xfr);
1640 static void
1641 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1642 INSIST(xfr->shuttingdown == ISC_TRUE);
1643 if (xfr->sends > 0) {
1645 * If we are currently sending, cancel it and wait for
1646 * cancel event before destroying the context.
1648 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
1649 ISC_SOCKCANCEL_SEND);
1650 } else {
1651 ns_client_next(xfr->client, ISC_R_CANCELED);
1652 xfrout_ctx_destroy(&xfr);
1656 static void
1657 xfrout_client_shutdown(void *arg, isc_result_t result) {
1658 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
1659 xfrout_fail(xfr, result, "aborted");
1663 * Log outgoing zone transfer messages in a format like
1664 * <client>: transfer of <zone>: <message>
1667 static void
1668 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1669 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1670 ISC_FORMAT_PRINTF(5, 0);
1672 static void
1673 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1674 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1676 char msgbuf[2048];
1677 char namebuf[DNS_NAME_FORMATSIZE];
1678 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1680 dns_name_format(zonename, namebuf, sizeof(namebuf));
1681 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1682 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1683 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1684 NS_LOGMODULE_XFER_OUT, level,
1685 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
1689 * Logging function for use when a xfrout_ctx_t has not yet been created.
1691 static void
1692 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
1693 dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
1694 va_list ap;
1695 va_start(ap, fmt);
1696 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1697 va_end(ap);
1701 * Logging function for use when there is a xfrout_ctx_t.
1703 static void
1704 xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) {
1705 va_list ap;
1706 va_start(ap, fmt);
1707 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
1708 va_end(ap);