No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / named / xfrout.c
blob67e8ddb71cf7209005c4b4abedc5de56c8e075c5
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: xfrout.c,v 1.136 2009/06/30 02:52:32 each Exp */
22 #include <config.h>
24 #include <isc/formatcheck.h>
25 #include <isc/mem.h>
26 #include <isc/timer.h>
27 #include <isc/print.h>
28 #include <isc/stats.h>
29 #include <isc/util.h>
31 #include <dns/db.h>
32 #include <dns/dbiterator.h>
33 #ifdef DLZ
34 #include <dns/dlz.h>
35 #endif
36 #include <dns/fixedname.h>
37 #include <dns/journal.h>
38 #include <dns/message.h>
39 #include <dns/peer.h>
40 #include <dns/rdataclass.h>
41 #include <dns/rdatalist.h>
42 #include <dns/rdataset.h>
43 #include <dns/rdatasetiter.h>
44 #include <dns/result.h>
45 #include <dns/rriterator.h>
46 #include <dns/soa.h>
47 #include <dns/stats.h>
48 #include <dns/timer.h>
49 #include <dns/tsig.h>
50 #include <dns/view.h>
51 #include <dns/zone.h>
52 #include <dns/zt.h>
54 #include <named/client.h>
55 #include <named/log.h>
56 #include <named/server.h>
57 #include <named/xfrout.h>
59 /*! \file
60 * \brief
61 * Outgoing AXFR and IXFR.
65 * TODO:
66 * - IXFR over UDP
69 #define XFROUT_COMMON_LOGARGS \
70 ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
72 #define XFROUT_PROTOCOL_LOGARGS \
73 XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
75 #define XFROUT_DEBUG_LOGARGS(n) \
76 XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
78 #define XFROUT_RR_LOGARGS \
79 XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
81 #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
83 /*%
84 * Fail unconditionally and log as a client error.
85 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
86 * from complaining about "end-of-loop code not reached".
88 #define FAILC(code, msg) \
89 do { \
90 result = (code); \
91 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
92 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
93 "bad zone transfer request: %s (%s)", \
94 msg, isc_result_totext(code)); \
95 if (result != ISC_R_SUCCESS) goto failure; \
96 } while (0)
98 #define FAILQ(code, msg, question, rdclass) \
99 do { \
100 char _buf1[DNS_NAME_FORMATSIZE]; \
101 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
102 result = (code); \
103 dns_name_format(question, _buf1, sizeof(_buf1)); \
104 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
105 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
106 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
107 "bad zone transfer request: '%s/%s': %s (%s)", \
108 _buf1, _buf2, msg, isc_result_totext(code)); \
109 if (result != ISC_R_SUCCESS) goto failure; \
110 } while (0)
112 #define CHECK(op) \
113 do { result = (op); \
114 if (result != ISC_R_SUCCESS) goto failure; \
115 } while (0)
117 /**************************************************************************/
119 static inline void
120 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
121 isc_stats_increment(ns_g_server->nsstats, counter);
122 if (zone != NULL) {
123 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
124 if (zonestats != NULL)
125 isc_stats_increment(zonestats, counter);
129 /**************************************************************************/
131 /*% Log an RR (for debugging) */
133 static void
134 log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
135 isc_result_t result;
136 isc_buffer_t buf;
137 char mem[2000];
138 dns_rdatalist_t rdl;
139 dns_rdataset_t rds;
140 dns_rdata_t rd = DNS_RDATA_INIT;
142 rdl.type = rdata->type;
143 rdl.rdclass = rdata->rdclass;
144 rdl.ttl = ttl;
145 if (rdata->type == dns_rdatatype_sig ||
146 rdata->type == dns_rdatatype_rrsig)
147 rdl.covers = dns_rdata_covers(rdata);
148 else
149 rdl.covers = dns_rdatatype_none;
150 ISC_LIST_INIT(rdl.rdata);
151 ISC_LINK_INIT(&rdl, link);
152 dns_rdataset_init(&rds);
153 dns_rdata_init(&rd);
154 dns_rdata_clone(rdata, &rd);
155 ISC_LIST_APPEND(rdl.rdata, &rd, link);
156 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
158 isc_buffer_init(&buf, mem, sizeof(mem));
159 result = dns_rdataset_totext(&rds, name,
160 ISC_FALSE, ISC_FALSE, &buf);
163 * We could use xfrout_log(), but that would produce
164 * very long lines with a repetitive prefix.
166 if (result == ISC_R_SUCCESS) {
168 * Get rid of final newline.
170 INSIST(buf.used >= 1 &&
171 ((char *) buf.base)[buf.used - 1] == '\n');
172 buf.used--;
174 isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
175 (int)isc_buffer_usedlength(&buf),
176 (char *)isc_buffer_base(&buf));
177 } else {
178 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
182 /**************************************************************************/
184 * An 'rrstream_t' is a polymorphic iterator that returns
185 * a stream of resource records. There are multiple implementations,
186 * e.g. for generating AXFR and IXFR records streams.
189 typedef struct rrstream_methods rrstream_methods_t;
191 typedef struct rrstream {
192 isc_mem_t *mctx;
193 rrstream_methods_t *methods;
194 } rrstream_t;
196 struct rrstream_methods {
197 isc_result_t (*first)(rrstream_t *);
198 isc_result_t (*next)(rrstream_t *);
199 void (*current)(rrstream_t *,
200 dns_name_t **,
201 isc_uint32_t *,
202 dns_rdata_t **);
203 void (*pause)(rrstream_t *);
204 void (*destroy)(rrstream_t **);
207 static void
208 rrstream_noop_pause(rrstream_t *rs) {
209 UNUSED(rs);
212 /**************************************************************************/
214 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
215 * an IXFR-like RR stream from a journal file.
217 * The SOA at the beginning of each sequence of additions
218 * or deletions are included in the stream, but the extra
219 * SOAs at the beginning and end of the entire transfer are
220 * not included.
223 typedef struct ixfr_rrstream {
224 rrstream_t common;
225 dns_journal_t *journal;
226 } ixfr_rrstream_t;
228 /* Forward declarations. */
229 static void
230 ixfr_rrstream_destroy(rrstream_t **sp);
232 static rrstream_methods_t ixfr_rrstream_methods;
235 * Returns: anything dns_journal_open() or dns_journal_iter_init()
236 * may return.
239 static isc_result_t
240 ixfr_rrstream_create(isc_mem_t *mctx,
241 const char *journal_filename,
242 isc_uint32_t begin_serial,
243 isc_uint32_t end_serial,
244 rrstream_t **sp)
246 ixfr_rrstream_t *s;
247 isc_result_t result;
249 INSIST(sp != NULL && *sp == NULL);
251 s = isc_mem_get(mctx, sizeof(*s));
252 if (s == NULL)
253 return (ISC_R_NOMEMORY);
254 s->common.mctx = mctx;
255 s->common.methods = &ixfr_rrstream_methods;
256 s->journal = NULL;
258 CHECK(dns_journal_open(mctx, journal_filename,
259 ISC_FALSE, &s->journal));
260 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
262 *sp = (rrstream_t *) s;
263 return (ISC_R_SUCCESS);
265 failure:
266 ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
267 return (result);
270 static isc_result_t
271 ixfr_rrstream_first(rrstream_t *rs) {
272 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
273 return (dns_journal_first_rr(s->journal));
276 static isc_result_t
277 ixfr_rrstream_next(rrstream_t *rs) {
278 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
279 return (dns_journal_next_rr(s->journal));
282 static void
283 ixfr_rrstream_current(rrstream_t *rs,
284 dns_name_t **name, isc_uint32_t *ttl,
285 dns_rdata_t **rdata)
287 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
288 dns_journal_current_rr(s->journal, name, ttl, rdata);
291 static void
292 ixfr_rrstream_destroy(rrstream_t **rsp) {
293 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
294 if (s->journal != 0)
295 dns_journal_destroy(&s->journal);
296 isc_mem_put(s->common.mctx, s, sizeof(*s));
299 static rrstream_methods_t ixfr_rrstream_methods = {
300 ixfr_rrstream_first,
301 ixfr_rrstream_next,
302 ixfr_rrstream_current,
303 rrstream_noop_pause,
304 ixfr_rrstream_destroy
307 /**************************************************************************/
309 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
310 * an AXFR-like RR stream from a database.
312 * The SOAs at the beginning and end of the transfer are
313 * not included in the stream.
316 typedef struct axfr_rrstream {
317 rrstream_t common;
318 dns_rriterator_t it;
319 isc_boolean_t it_valid;
320 } axfr_rrstream_t;
323 * Forward declarations.
325 static void
326 axfr_rrstream_destroy(rrstream_t **rsp);
328 static rrstream_methods_t axfr_rrstream_methods;
330 static isc_result_t
331 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
332 rrstream_t **sp)
334 axfr_rrstream_t *s;
335 isc_result_t result;
337 INSIST(sp != NULL && *sp == NULL);
339 s = isc_mem_get(mctx, sizeof(*s));
340 if (s == NULL)
341 return (ISC_R_NOMEMORY);
342 s->common.mctx = mctx;
343 s->common.methods = &axfr_rrstream_methods;
344 s->it_valid = ISC_FALSE;
346 CHECK(dns_rriterator_init(&s->it, db, ver, 0));
347 s->it_valid = ISC_TRUE;
349 *sp = (rrstream_t *) s;
350 return (ISC_R_SUCCESS);
352 failure:
353 axfr_rrstream_destroy((rrstream_t **) (void *)&s);
354 return (result);
357 static isc_result_t
358 axfr_rrstream_first(rrstream_t *rs) {
359 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
360 isc_result_t result;
361 result = dns_rriterator_first(&s->it);
362 if (result != ISC_R_SUCCESS)
363 return (result);
364 /* Skip SOA records. */
365 for (;;) {
366 dns_name_t *name_dummy = NULL;
367 isc_uint32_t ttl_dummy;
368 dns_rdata_t *rdata = NULL;
369 dns_rriterator_current(&s->it, &name_dummy,
370 &ttl_dummy, NULL, &rdata);
371 if (rdata->type != dns_rdatatype_soa)
372 break;
373 result = dns_rriterator_next(&s->it);
374 if (result != ISC_R_SUCCESS)
375 break;
377 return (result);
380 static isc_result_t
381 axfr_rrstream_next(rrstream_t *rs) {
382 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
383 isc_result_t result;
385 /* Skip SOA records. */
386 for (;;) {
387 dns_name_t *name_dummy = NULL;
388 isc_uint32_t ttl_dummy;
389 dns_rdata_t *rdata = NULL;
390 result = dns_rriterator_next(&s->it);
391 if (result != ISC_R_SUCCESS)
392 break;
393 dns_rriterator_current(&s->it, &name_dummy,
394 &ttl_dummy, NULL, &rdata);
395 if (rdata->type != dns_rdatatype_soa)
396 break;
398 return (result);
401 static void
402 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
403 dns_rdata_t **rdata)
405 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
406 dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
409 static void
410 axfr_rrstream_pause(rrstream_t *rs) {
411 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
412 dns_rriterator_pause(&s->it);
415 static void
416 axfr_rrstream_destroy(rrstream_t **rsp) {
417 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
418 if (s->it_valid)
419 dns_rriterator_destroy(&s->it);
420 isc_mem_put(s->common.mctx, s, sizeof(*s));
423 static rrstream_methods_t axfr_rrstream_methods = {
424 axfr_rrstream_first,
425 axfr_rrstream_next,
426 axfr_rrstream_current,
427 axfr_rrstream_pause,
428 axfr_rrstream_destroy
431 /**************************************************************************/
433 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
434 * a single SOA record.
437 typedef struct soa_rrstream {
438 rrstream_t common;
439 dns_difftuple_t *soa_tuple;
440 } soa_rrstream_t;
443 * Forward declarations.
445 static void
446 soa_rrstream_destroy(rrstream_t **rsp);
448 static rrstream_methods_t soa_rrstream_methods;
450 static isc_result_t
451 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
452 rrstream_t **sp)
454 soa_rrstream_t *s;
455 isc_result_t result;
457 INSIST(sp != NULL && *sp == NULL);
459 s = isc_mem_get(mctx, sizeof(*s));
460 if (s == NULL)
461 return (ISC_R_NOMEMORY);
462 s->common.mctx = mctx;
463 s->common.methods = &soa_rrstream_methods;
464 s->soa_tuple = NULL;
466 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
467 &s->soa_tuple));
469 *sp = (rrstream_t *) s;
470 return (ISC_R_SUCCESS);
472 failure:
473 soa_rrstream_destroy((rrstream_t **) (void *)&s);
474 return (result);
477 static isc_result_t
478 soa_rrstream_first(rrstream_t *rs) {
479 UNUSED(rs);
480 return (ISC_R_SUCCESS);
483 static isc_result_t
484 soa_rrstream_next(rrstream_t *rs) {
485 UNUSED(rs);
486 return (ISC_R_NOMORE);
489 static void
490 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
491 dns_rdata_t **rdata)
493 soa_rrstream_t *s = (soa_rrstream_t *) rs;
494 *name = &s->soa_tuple->name;
495 *ttl = s->soa_tuple->ttl;
496 *rdata = &s->soa_tuple->rdata;
499 static void
500 soa_rrstream_destroy(rrstream_t **rsp) {
501 soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
502 if (s->soa_tuple != NULL)
503 dns_difftuple_free(&s->soa_tuple);
504 isc_mem_put(s->common.mctx, s, sizeof(*s));
507 static rrstream_methods_t soa_rrstream_methods = {
508 soa_rrstream_first,
509 soa_rrstream_next,
510 soa_rrstream_current,
511 rrstream_noop_pause,
512 soa_rrstream_destroy
515 /**************************************************************************/
517 * A 'compound_rrstream_t' objects owns a soa_rrstream
518 * and another rrstream, the "data stream". It returns
519 * a concatenated stream consisting of the soa_rrstream, then
520 * the data stream, then the soa_rrstream again.
522 * The component streams are owned by the compound_rrstream_t
523 * and are destroyed with it.
526 typedef struct compound_rrstream {
527 rrstream_t common;
528 rrstream_t *components[3];
529 int state;
530 isc_result_t result;
531 } compound_rrstream_t;
534 * Forward declarations.
536 static void
537 compound_rrstream_destroy(rrstream_t **rsp);
539 static isc_result_t
540 compound_rrstream_next(rrstream_t *rs);
542 static rrstream_methods_t compound_rrstream_methods;
545 * Requires:
546 * soa_stream != NULL && *soa_stream != NULL
547 * data_stream != NULL && *data_stream != NULL
548 * sp != NULL && *sp == NULL
550 * Ensures:
551 * *soa_stream == NULL
552 * *data_stream == NULL
553 * *sp points to a valid compound_rrstream_t
554 * The soa and data streams will be destroyed
555 * when the compound_rrstream_t is destroyed.
557 static isc_result_t
558 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
559 rrstream_t **data_stream, rrstream_t **sp)
561 compound_rrstream_t *s;
563 INSIST(sp != NULL && *sp == NULL);
565 s = isc_mem_get(mctx, sizeof(*s));
566 if (s == NULL)
567 return (ISC_R_NOMEMORY);
568 s->common.mctx = mctx;
569 s->common.methods = &compound_rrstream_methods;
570 s->components[0] = *soa_stream;
571 s->components[1] = *data_stream;
572 s->components[2] = *soa_stream;
573 s->state = -1;
574 s->result = ISC_R_FAILURE;
576 *soa_stream = NULL;
577 *data_stream = NULL;
578 *sp = (rrstream_t *) s;
579 return (ISC_R_SUCCESS);
582 static isc_result_t
583 compound_rrstream_first(rrstream_t *rs) {
584 compound_rrstream_t *s = (compound_rrstream_t *) rs;
585 s->state = 0;
586 do {
587 rrstream_t *curstream = s->components[s->state];
588 s->result = curstream->methods->first(curstream);
589 } while (s->result == ISC_R_NOMORE && s->state < 2);
590 return (s->result);
593 static isc_result_t
594 compound_rrstream_next(rrstream_t *rs) {
595 compound_rrstream_t *s = (compound_rrstream_t *) rs;
596 rrstream_t *curstream = s->components[s->state];
597 s->result = curstream->methods->next(curstream);
598 while (s->result == ISC_R_NOMORE) {
600 * Make sure locks held by the current stream
601 * are released before we switch streams.
603 curstream->methods->pause(curstream);
604 if (s->state == 2)
605 return (ISC_R_NOMORE);
606 s->state++;
607 curstream = s->components[s->state];
608 s->result = curstream->methods->first(curstream);
610 return (s->result);
613 static void
614 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
615 dns_rdata_t **rdata)
617 compound_rrstream_t *s = (compound_rrstream_t *) rs;
618 rrstream_t *curstream;
619 INSIST(0 <= s->state && s->state < 3);
620 INSIST(s->result == ISC_R_SUCCESS);
621 curstream = s->components[s->state];
622 curstream->methods->current(curstream, name, ttl, rdata);
625 static void
626 compound_rrstream_pause(rrstream_t *rs)
628 compound_rrstream_t *s = (compound_rrstream_t *) rs;
629 rrstream_t *curstream;
630 INSIST(0 <= s->state && s->state < 3);
631 curstream = s->components[s->state];
632 curstream->methods->pause(curstream);
635 static void
636 compound_rrstream_destroy(rrstream_t **rsp) {
637 compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
638 s->components[0]->methods->destroy(&s->components[0]);
639 s->components[1]->methods->destroy(&s->components[1]);
640 s->components[2] = NULL; /* Copy of components[0]. */
641 isc_mem_put(s->common.mctx, s, sizeof(*s));
644 static rrstream_methods_t compound_rrstream_methods = {
645 compound_rrstream_first,
646 compound_rrstream_next,
647 compound_rrstream_current,
648 compound_rrstream_pause,
649 compound_rrstream_destroy
652 /**************************************************************************/
654 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
655 * in progress.
658 typedef struct {
659 isc_mem_t *mctx;
660 ns_client_t *client;
661 unsigned int id; /* ID of request */
662 dns_name_t *qname; /* Question name of request */
663 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
664 dns_rdataclass_t qclass;
665 dns_zone_t *zone; /* (necessary for stats) */
666 dns_db_t *db;
667 dns_dbversion_t *ver;
668 isc_quota_t *quota;
669 rrstream_t *stream; /* The XFR RR stream */
670 isc_boolean_t end_of_stream; /* EOS has been reached */
671 isc_buffer_t buf; /* Buffer for message owner
672 names and rdatas */
673 isc_buffer_t txlenbuf; /* Transmit length buffer */
674 isc_buffer_t txbuf; /* Transmit message buffer */
675 void *txmem;
676 unsigned int txmemlen;
677 unsigned int nmsg; /* Number of messages sent */
678 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
679 isc_buffer_t *lasttsig; /* the last TSIG */
680 isc_boolean_t many_answers;
681 int sends; /* Send in progress */
682 isc_boolean_t shuttingdown;
683 const char *mnemonic; /* Style of transfer */
684 } xfrout_ctx_t;
686 static isc_result_t
687 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
688 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
689 dns_rdataclass_t qclass, dns_zone_t *zone,
690 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
691 rrstream_t *stream, dns_tsigkey_t *tsigkey,
692 isc_buffer_t *lasttsig,
693 unsigned int maxtime,
694 unsigned int idletime,
695 isc_boolean_t many_answers,
696 xfrout_ctx_t **xfrp);
698 static void
699 sendstream(xfrout_ctx_t *xfr);
701 static void
702 xfrout_senddone(isc_task_t *task, isc_event_t *event);
704 static void
705 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
707 static void
708 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
710 static void
711 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
713 static void
714 xfrout_client_shutdown(void *arg, isc_result_t result);
716 static void
717 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
718 dns_rdataclass_t rdclass, int level,
719 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
721 static void
722 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
723 ISC_FORMAT_PRINTF(3, 4);
725 /**************************************************************************/
727 void
728 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
729 isc_result_t result;
730 dns_name_t *question_name;
731 dns_rdataset_t *question_rdataset;
732 dns_zone_t *zone = NULL;
733 dns_db_t *db = NULL;
734 dns_dbversion_t *ver = NULL;
735 dns_rdataclass_t question_class;
736 rrstream_t *soa_stream = NULL;
737 rrstream_t *data_stream = NULL;
738 rrstream_t *stream = NULL;
739 dns_difftuple_t *current_soa_tuple = NULL;
740 dns_name_t *soa_name;
741 dns_rdataset_t *soa_rdataset;
742 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
743 isc_boolean_t have_soa = ISC_FALSE;
744 const char *mnemonic = NULL;
745 isc_mem_t *mctx = client->mctx;
746 dns_message_t *request = client->message;
747 xfrout_ctx_t *xfr = NULL;
748 isc_quota_t *quota = NULL;
749 dns_transfer_format_t format = client->view->transfer_format;
750 isc_netaddr_t na;
751 dns_peer_t *peer = NULL;
752 isc_buffer_t *tsigbuf = NULL;
753 char *journalfile;
754 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
755 char keyname[DNS_NAME_FORMATSIZE];
756 isc_boolean_t is_poll = ISC_FALSE;
757 #ifdef DLZ
758 isc_boolean_t is_dlz = ISC_FALSE;
759 #endif
761 switch (reqtype) {
762 case dns_rdatatype_axfr:
763 mnemonic = "AXFR";
764 break;
765 case dns_rdatatype_ixfr:
766 mnemonic = "IXFR";
767 break;
768 default:
769 INSIST(0);
770 break;
773 ns_client_log(client,
774 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
775 ISC_LOG_DEBUG(6), "%s request", mnemonic);
777 * Apply quota.
779 result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
780 if (result != ISC_R_SUCCESS) {
781 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
782 "%s request denied: %s", mnemonic,
783 isc_result_totext(result));
784 goto failure;
788 * Interpret the question section.
790 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
791 INSIST(result == ISC_R_SUCCESS);
794 * The question section must contain exactly one question, and
795 * it must be for AXFR/IXFR as appropriate.
797 question_name = NULL;
798 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
799 question_rdataset = ISC_LIST_HEAD(question_name->list);
800 question_class = question_rdataset->rdclass;
801 INSIST(question_rdataset->type == reqtype);
802 if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
803 FAILC(DNS_R_FORMERR, "multiple questions");
804 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
805 if (result != ISC_R_NOMORE)
806 FAILC(DNS_R_FORMERR, "multiple questions");
808 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
809 &zone);
811 if (result != ISC_R_SUCCESS)
812 #ifdef DLZ
815 * Normal zone table does not have a match. Try the DLZ database
817 if (client->view->dlzdatabase != NULL) {
818 result = dns_dlzallowzonexfr(client->view,
819 question_name, &client->peeraddr,
820 &db);
822 if (result == ISC_R_NOPERM) {
823 char _buf1[DNS_NAME_FORMATSIZE];
824 char _buf2[DNS_RDATACLASS_FORMATSIZE];
826 result = DNS_R_REFUSED;
827 dns_name_format(question_name, _buf1,
828 sizeof(_buf1));
829 dns_rdataclass_format(question_class,
830 _buf2, sizeof(_buf2));
831 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
832 NS_LOGMODULE_XFER_OUT,
833 ISC_LOG_ERROR,
834 "zone transfer '%s/%s' denied",
835 _buf1, _buf2);
836 goto failure;
838 if (result != ISC_R_SUCCESS)
839 #endif
840 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
841 question_name, question_class);
842 #ifdef DLZ
843 is_dlz = ISC_TRUE;
845 * DLZ only support full zone transfer, not incremental
847 if (reqtype != dns_rdatatype_axfr) {
848 mnemonic = "AXFR-style IXFR";
849 reqtype = dns_rdatatype_axfr;
852 } else {
854 * not DLZ and not in normal zone table, we are
855 * not authoritative
857 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
858 question_name, question_class);
860 } else {
861 /* zone table has a match */
862 #endif
863 switch(dns_zone_gettype(zone)) {
864 case dns_zone_master:
865 case dns_zone_slave:
866 break; /* Master and slave zones are OK for transfer. */
867 default:
868 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
870 CHECK(dns_zone_getdb(zone, &db));
871 dns_db_currentversion(db, &ver);
872 #ifdef DLZ
874 #endif
876 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
877 "%s question section OK", mnemonic);
880 * Check the authority section. Look for a SOA record with
881 * the same name and class as the question.
883 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
884 result == ISC_R_SUCCESS;
885 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
887 soa_name = NULL;
888 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
889 &soa_name);
892 * Ignore data whose owner name is not the zone apex.
894 if (! dns_name_equal(soa_name, question_name))
895 continue;
897 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
898 soa_rdataset != NULL;
899 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
902 * Ignore non-SOA data.
904 if (soa_rdataset->type != dns_rdatatype_soa)
905 continue;
906 if (soa_rdataset->rdclass != question_class)
907 continue;
909 CHECK(dns_rdataset_first(soa_rdataset));
910 dns_rdataset_current(soa_rdataset, &soa_rdata);
911 result = dns_rdataset_next(soa_rdataset);
912 if (result == ISC_R_SUCCESS)
913 FAILC(DNS_R_FORMERR,
914 "IXFR authority section "
915 "has multiple SOAs");
916 have_soa = ISC_TRUE;
917 goto got_soa;
920 got_soa:
921 if (result != ISC_R_NOMORE)
922 CHECK(result);
924 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
925 "%s authority section OK", mnemonic);
928 * Decide whether to allow this transfer.
930 #ifdef DLZ
932 * if not a DLZ zone decide whether to allow this transfer.
934 if (!is_dlz) {
935 #endif
936 ns_client_aclmsg("zone transfer", question_name, reqtype,
937 client->view->rdclass, msg, sizeof(msg));
938 CHECK(ns_client_checkacl(client, NULL, msg,
939 dns_zone_getxfracl(zone),
940 ISC_TRUE, ISC_LOG_ERROR));
941 #ifdef DLZ
943 #endif
946 * AXFR over UDP is not possible.
948 if (reqtype == dns_rdatatype_axfr &&
949 (client->attributes & NS_CLIENTATTR_TCP) == 0)
950 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
953 * Look up the requesting server in the peer table.
955 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
956 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
959 * Decide on the transfer format (one-answer or many-answers).
961 if (peer != NULL)
962 (void)dns_peer_gettransferformat(peer, &format);
965 * Get a dynamically allocated copy of the current SOA.
967 #ifdef DLZ
968 if (is_dlz)
969 dns_db_currentversion(db, &ver);
970 #endif
971 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
972 &current_soa_tuple));
974 if (reqtype == dns_rdatatype_ixfr) {
975 isc_uint32_t begin_serial, current_serial;
976 isc_boolean_t provide_ixfr;
979 * Outgoing IXFR may have been disabled for this peer
980 * or globally.
982 provide_ixfr = client->view->provideixfr;
983 if (peer != NULL)
984 (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
985 if (provide_ixfr == ISC_FALSE)
986 goto axfr_fallback;
988 if (! have_soa)
989 FAILC(DNS_R_FORMERR,
990 "IXFR request missing SOA");
992 begin_serial = dns_soa_getserial(&soa_rdata);
993 current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
996 * RFC1995 says "If an IXFR query with the same or
997 * newer version number than that of the server
998 * is received, it is replied to with a single SOA
999 * record of the server's current version, just as
1000 * in AXFR". The claim about AXFR is incorrect,
1001 * but other than that, we do as the RFC says.
1003 * Sending a single SOA record is also how we refuse
1004 * IXFR over UDP (currently, we always do).
1006 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
1007 (client->attributes & NS_CLIENTATTR_TCP) == 0)
1009 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
1010 is_poll = ISC_TRUE;
1011 goto have_stream;
1013 journalfile = dns_zone_getjournal(zone);
1014 if (journalfile != NULL)
1015 result = ixfr_rrstream_create(mctx,
1016 journalfile,
1017 begin_serial,
1018 current_serial,
1019 &data_stream);
1020 else
1021 result = ISC_R_NOTFOUND;
1022 if (result == ISC_R_NOTFOUND ||
1023 result == ISC_R_RANGE) {
1024 xfrout_log1(client, question_name, question_class,
1025 ISC_LOG_DEBUG(4),
1026 "IXFR version not in journal, "
1027 "falling back to AXFR");
1028 mnemonic = "AXFR-style IXFR";
1029 goto axfr_fallback;
1031 CHECK(result);
1032 } else {
1033 axfr_fallback:
1034 CHECK(axfr_rrstream_create(mctx, db, ver,
1035 &data_stream));
1039 * Bracket the data stream with SOAs.
1041 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1042 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1043 &stream));
1044 soa_stream = NULL;
1045 data_stream = NULL;
1047 have_stream:
1048 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1050 * Create the xfrout context object. This transfers the ownership
1051 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1056 #ifdef DLZ
1057 if (is_dlz)
1058 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1059 reqtype, question_class, zone, db, ver,
1060 quota, stream,
1061 dns_message_gettsigkey(request),
1062 tsigbuf,
1063 3600,
1064 3600,
1065 (format == dns_many_answers) ?
1066 ISC_TRUE : ISC_FALSE,
1067 &xfr));
1068 else
1069 #endif
1070 CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1071 reqtype, question_class, zone, db, ver,
1072 quota, stream,
1073 dns_message_gettsigkey(request),
1074 tsigbuf,
1075 dns_zone_getmaxxfrout(zone),
1076 dns_zone_getidleout(zone),
1077 (format == dns_many_answers) ?
1078 ISC_TRUE : ISC_FALSE,
1079 &xfr));
1081 xfr->mnemonic = mnemonic;
1082 stream = NULL;
1083 quota = NULL;
1085 CHECK(xfr->stream->methods->first(xfr->stream));
1087 if (xfr->tsigkey != NULL) {
1088 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
1089 } else
1090 keyname[0] = '\0';
1091 if (is_poll)
1092 xfrout_log1(client, question_name, question_class,
1093 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
1094 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1095 else
1096 xfrout_log1(client, question_name, question_class,
1097 ISC_LOG_INFO, "%s started%s%s", mnemonic,
1098 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1101 * Hand the context over to sendstream(). Set xfr to NULL;
1102 * sendstream() is responsible for either passing the
1103 * context on to a later event handler or destroying it.
1105 sendstream(xfr);
1106 xfr = NULL;
1108 result = ISC_R_SUCCESS;
1110 failure:
1111 if (result == DNS_R_REFUSED)
1112 inc_stats(zone, dns_nsstatscounter_xfrrej);
1113 if (quota != NULL)
1114 isc_quota_detach(&quota);
1115 if (current_soa_tuple != NULL)
1116 dns_difftuple_free(&current_soa_tuple);
1117 if (stream != NULL)
1118 stream->methods->destroy(&stream);
1119 if (soa_stream != NULL)
1120 soa_stream->methods->destroy(&soa_stream);
1121 if (data_stream != NULL)
1122 data_stream->methods->destroy(&data_stream);
1123 if (ver != NULL)
1124 dns_db_closeversion(db, &ver, ISC_FALSE);
1125 if (db != NULL)
1126 dns_db_detach(&db);
1127 if (zone != NULL)
1128 dns_zone_detach(&zone);
1129 /* XXX kludge */
1130 if (xfr != NULL) {
1131 xfrout_fail(xfr, result, "setting up zone transfer");
1132 } else if (result != ISC_R_SUCCESS) {
1133 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1134 NS_LOGMODULE_XFER_OUT,
1135 ISC_LOG_DEBUG(3), "zone transfer setup failed");
1136 ns_client_error(client, result);
1140 static isc_result_t
1141 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1142 dns_name_t *qname, dns_rdatatype_t qtype,
1143 dns_rdataclass_t qclass, dns_zone_t *zone,
1144 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
1145 rrstream_t *stream, dns_tsigkey_t *tsigkey,
1146 isc_buffer_t *lasttsig, unsigned int maxtime,
1147 unsigned int idletime, isc_boolean_t many_answers,
1148 xfrout_ctx_t **xfrp)
1150 xfrout_ctx_t *xfr;
1151 isc_result_t result;
1152 unsigned int len;
1153 void *mem;
1155 INSIST(xfrp != NULL && *xfrp == NULL);
1156 xfr = isc_mem_get(mctx, sizeof(*xfr));
1157 if (xfr == NULL)
1158 return (ISC_R_NOMEMORY);
1159 xfr->mctx = mctx;
1160 xfr->client = NULL;
1161 ns_client_attach(client, &xfr->client);
1162 xfr->id = id;
1163 xfr->qname = qname;
1164 xfr->qtype = qtype;
1165 xfr->qclass = qclass;
1166 xfr->zone = NULL;
1167 xfr->db = NULL;
1168 xfr->ver = NULL;
1169 if (zone != NULL) /* zone will be NULL if it's DLZ */
1170 dns_zone_attach(zone, &xfr->zone);
1171 dns_db_attach(db, &xfr->db);
1172 dns_db_attachversion(db, ver, &xfr->ver);
1173 xfr->end_of_stream = ISC_FALSE;
1174 xfr->tsigkey = tsigkey;
1175 xfr->lasttsig = lasttsig;
1176 xfr->txmem = NULL;
1177 xfr->txmemlen = 0;
1178 xfr->nmsg = 0;
1179 xfr->many_answers = many_answers,
1180 xfr->sends = 0;
1181 xfr->shuttingdown = ISC_FALSE;
1182 xfr->mnemonic = NULL;
1183 xfr->buf.base = NULL;
1184 xfr->buf.length = 0;
1185 xfr->txmem = NULL;
1186 xfr->txmemlen = 0;
1187 xfr->stream = NULL;
1188 xfr->quota = NULL;
1191 * Allocate a temporary buffer for the uncompressed response
1192 * message data. The size should be no more than 65535 bytes
1193 * so that the compressed data will fit in a TCP message,
1194 * and no less than 65535 bytes so that an almost maximum-sized
1195 * RR will fit. Note that although 65535-byte RRs are allowed
1196 * in principle, they cannot be zone-transferred (at least not
1197 * if uncompressible), because the message and RR headers would
1198 * push the size of the TCP message over the 65536 byte limit.
1200 len = 65535;
1201 mem = isc_mem_get(mctx, len);
1202 if (mem == NULL) {
1203 result = ISC_R_NOMEMORY;
1204 goto failure;
1206 isc_buffer_init(&xfr->buf, mem, len);
1209 * Allocate another temporary buffer for the compressed
1210 * response message and its TCP length prefix.
1212 len = 2 + 65535;
1213 mem = isc_mem_get(mctx, len);
1214 if (mem == NULL) {
1215 result = ISC_R_NOMEMORY;
1216 goto failure;
1218 isc_buffer_init(&xfr->txlenbuf, mem, 2);
1219 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
1220 xfr->txmem = mem;
1221 xfr->txmemlen = len;
1223 CHECK(dns_timer_setidle(xfr->client->timer,
1224 maxtime, idletime, ISC_FALSE));
1227 * Register a shutdown callback with the client, so that we
1228 * can stop the transfer immediately when the client task
1229 * gets a shutdown event.
1231 xfr->client->shutdown = xfrout_client_shutdown;
1232 xfr->client->shutdown_arg = xfr;
1234 * These MUST be after the last "goto failure;" / CHECK to
1235 * prevent a double free by the caller.
1237 xfr->quota = quota;
1238 xfr->stream = stream;
1240 *xfrp = xfr;
1241 return (ISC_R_SUCCESS);
1243 failure:
1244 xfrout_ctx_destroy(&xfr);
1245 return (result);
1250 * Arrange to send as much as we can of "stream" without blocking.
1252 * Requires:
1253 * The stream iterator is initialized and points at an RR,
1254 * or possibly at the end of the stream (that is, the
1255 * _first method of the iterator has been called).
1257 static void
1258 sendstream(xfrout_ctx_t *xfr) {
1259 dns_message_t *tcpmsg = NULL;
1260 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1261 isc_result_t result;
1262 isc_region_t used;
1263 isc_region_t region;
1264 dns_rdataset_t *qrdataset;
1265 dns_name_t *msgname = NULL;
1266 dns_rdata_t *msgrdata = NULL;
1267 dns_rdatalist_t *msgrdl = NULL;
1268 dns_rdataset_t *msgrds = NULL;
1269 dns_compress_t cctx;
1270 isc_boolean_t cleanup_cctx = ISC_FALSE;
1272 int n_rrs;
1274 isc_buffer_clear(&xfr->buf);
1275 isc_buffer_clear(&xfr->txlenbuf);
1276 isc_buffer_clear(&xfr->txbuf);
1278 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
1280 * In the UDP case, we put the response data directly into
1281 * the client message.
1283 msg = xfr->client->message;
1284 CHECK(dns_message_reply(msg, ISC_TRUE));
1285 } else {
1287 * TCP. Build a response dns_message_t, temporarily storing
1288 * the raw, uncompressed owner names and RR data contiguously
1289 * in xfr->buf. We know that if the uncompressed data fits
1290 * in xfr->buf, the compressed data will surely fit in a TCP
1291 * message.
1294 CHECK(dns_message_create(xfr->mctx,
1295 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
1296 msg = tcpmsg;
1298 msg->id = xfr->id;
1299 msg->rcode = dns_rcode_noerror;
1300 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1301 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
1302 msg->flags |= DNS_MESSAGEFLAG_RA;
1303 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1304 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1305 if (xfr->lasttsig != NULL)
1306 isc_buffer_free(&xfr->lasttsig);
1309 * Include a question section in the first message only.
1310 * BIND 8.2.1 will not recognize an IXFR if it does not
1311 * have a question section.
1313 if (xfr->nmsg == 0) {
1314 dns_name_t *qname = NULL;
1315 isc_region_t r;
1318 * Reserve space for the 12-byte message header
1319 * and 4 bytes of question.
1321 isc_buffer_add(&xfr->buf, 12 + 4);
1323 qrdataset = NULL;
1324 result = dns_message_gettemprdataset(msg, &qrdataset);
1325 if (result != ISC_R_SUCCESS)
1326 goto failure;
1327 dns_rdataset_init(qrdataset);
1328 dns_rdataset_makequestion(qrdataset,
1329 xfr->client->message->rdclass,
1330 xfr->qtype);
1332 result = dns_message_gettempname(msg, &qname);
1333 if (result != ISC_R_SUCCESS)
1334 goto failure;
1335 dns_name_init(qname, NULL);
1336 isc_buffer_availableregion(&xfr->buf, &r);
1337 INSIST(r.length >= xfr->qname->length);
1338 r.length = xfr->qname->length;
1339 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1340 xfr->qname->length);
1341 dns_name_fromregion(qname, &r);
1342 ISC_LIST_INIT(qname->list);
1343 ISC_LIST_APPEND(qname->list, qrdataset, link);
1345 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1347 else
1348 msg->tcp_continuation = 1;
1352 * Try to fit in as many RRs as possible, unless "one-answer"
1353 * format has been requested.
1355 for (n_rrs = 0; ; n_rrs++) {
1356 dns_name_t *name = NULL;
1357 isc_uint32_t ttl;
1358 dns_rdata_t *rdata = NULL;
1360 unsigned int size;
1361 isc_region_t r;
1363 msgname = NULL;
1364 msgrdata = NULL;
1365 msgrdl = NULL;
1366 msgrds = NULL;
1368 xfr->stream->methods->current(xfr->stream,
1369 &name, &ttl, &rdata);
1370 size = name->length + 10 + rdata->length;
1371 isc_buffer_availableregion(&xfr->buf, &r);
1372 if (size >= r.length) {
1374 * RR would not fit. If there are other RRs in the
1375 * buffer, send them now and leave this RR to the
1376 * next message. If this RR overflows the buffer
1377 * all by itself, fail.
1379 * In theory some RRs might fit in a TCP message
1380 * when compressed even if they do not fit when
1381 * uncompressed, but surely we don't want
1382 * to send such monstrosities to an unsuspecting
1383 * slave.
1385 if (n_rrs == 0) {
1386 xfrout_log(xfr, ISC_LOG_WARNING,
1387 "RR too large for zone transfer "
1388 "(%d bytes)", size);
1389 /* XXX DNS_R_RRTOOLARGE? */
1390 result = ISC_R_NOSPACE;
1391 goto failure;
1393 break;
1396 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
1397 log_rr(name, rdata, ttl); /* XXX */
1399 result = dns_message_gettempname(msg, &msgname);
1400 if (result != ISC_R_SUCCESS)
1401 goto failure;
1402 dns_name_init(msgname, NULL);
1403 isc_buffer_availableregion(&xfr->buf, &r);
1404 INSIST(r.length >= name->length);
1405 r.length = name->length;
1406 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1407 dns_name_fromregion(msgname, &r);
1409 /* Reserve space for RR header. */
1410 isc_buffer_add(&xfr->buf, 10);
1412 result = dns_message_gettemprdata(msg, &msgrdata);
1413 if (result != ISC_R_SUCCESS)
1414 goto failure;
1415 isc_buffer_availableregion(&xfr->buf, &r);
1416 r.length = rdata->length;
1417 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1418 dns_rdata_init(msgrdata);
1419 dns_rdata_fromregion(msgrdata,
1420 rdata->rdclass, rdata->type, &r);
1422 result = dns_message_gettemprdatalist(msg, &msgrdl);
1423 if (result != ISC_R_SUCCESS)
1424 goto failure;
1425 msgrdl->type = rdata->type;
1426 msgrdl->rdclass = rdata->rdclass;
1427 msgrdl->ttl = ttl;
1428 if (rdata->type == dns_rdatatype_sig ||
1429 rdata->type == dns_rdatatype_rrsig)
1430 msgrdl->covers = dns_rdata_covers(rdata);
1431 else
1432 msgrdl->covers = dns_rdatatype_none;
1433 ISC_LINK_INIT(msgrdl, link);
1434 ISC_LIST_INIT(msgrdl->rdata);
1435 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1437 result = dns_message_gettemprdataset(msg, &msgrds);
1438 if (result != ISC_R_SUCCESS)
1439 goto failure;
1440 dns_rdataset_init(msgrds);
1441 result = dns_rdatalist_tordataset(msgrdl, msgrds);
1442 INSIST(result == ISC_R_SUCCESS);
1444 ISC_LIST_APPEND(msgname->list, msgrds, link);
1446 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1447 msgname = NULL;
1449 result = xfr->stream->methods->next(xfr->stream);
1450 if (result == ISC_R_NOMORE) {
1451 xfr->end_of_stream = ISC_TRUE;
1452 break;
1454 CHECK(result);
1456 if (! xfr->many_answers)
1457 break;
1460 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
1461 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1462 dns_compress_setsensitive(&cctx, ISC_TRUE);
1463 cleanup_cctx = ISC_TRUE;
1464 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1465 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1466 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1467 CHECK(dns_message_renderend(msg));
1468 dns_compress_invalidate(&cctx);
1469 cleanup_cctx = ISC_FALSE;
1471 isc_buffer_usedregion(&xfr->txbuf, &used);
1472 isc_buffer_putuint16(&xfr->txlenbuf,
1473 (isc_uint16_t)used.length);
1474 region.base = xfr->txlenbuf.base;
1475 region.length = 2 + used.length;
1476 xfrout_log(xfr, ISC_LOG_DEBUG(8),
1477 "sending TCP message of %d bytes",
1478 used.length);
1479 CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
1480 &region, xfr->client->task,
1481 xfrout_senddone,
1482 xfr));
1483 xfr->sends++;
1484 } else {
1485 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1486 ns_client_send(xfr->client);
1487 xfr->stream->methods->pause(xfr->stream);
1488 xfrout_ctx_destroy(&xfr);
1489 return;
1492 /* Advance lasttsig to be the last TSIG generated */
1493 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1495 xfr->nmsg++;
1497 failure:
1498 if (msgname != NULL) {
1499 if (msgrds != NULL) {
1500 if (dns_rdataset_isassociated(msgrds))
1501 dns_rdataset_disassociate(msgrds);
1502 dns_message_puttemprdataset(msg, &msgrds);
1504 if (msgrdl != NULL) {
1505 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1506 dns_message_puttemprdatalist(msg, &msgrdl);
1508 if (msgrdata != NULL)
1509 dns_message_puttemprdata(msg, &msgrdata);
1510 dns_message_puttempname(msg, &msgname);
1513 if (tcpmsg != NULL)
1514 dns_message_destroy(&tcpmsg);
1516 if (cleanup_cctx)
1517 dns_compress_invalidate(&cctx);
1519 * Make sure to release any locks held by database
1520 * iterators before returning from the event handler.
1522 xfr->stream->methods->pause(xfr->stream);
1524 if (result == ISC_R_SUCCESS)
1525 return;
1527 xfrout_fail(xfr, result, "sending zone data");
1530 static void
1531 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1532 xfrout_ctx_t *xfr = *xfrp;
1534 INSIST(xfr->sends == 0);
1536 xfr->client->shutdown = NULL;
1537 xfr->client->shutdown_arg = NULL;
1539 if (xfr->stream != NULL)
1540 xfr->stream->methods->destroy(&xfr->stream);
1541 if (xfr->buf.base != NULL)
1542 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1543 if (xfr->txmem != NULL)
1544 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1545 if (xfr->lasttsig != NULL)
1546 isc_buffer_free(&xfr->lasttsig);
1547 if (xfr->quota != NULL)
1548 isc_quota_detach(&xfr->quota);
1549 if (xfr->ver != NULL)
1550 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1551 if (xfr->zone != NULL)
1552 dns_zone_detach(&xfr->zone);
1553 if (xfr->db != NULL)
1554 dns_db_detach(&xfr->db);
1556 ns_client_detach(&xfr->client);
1558 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1560 *xfrp = NULL;
1563 static void
1564 xfrout_senddone(isc_task_t *task, isc_event_t *event) {
1565 isc_socketevent_t *sev = (isc_socketevent_t *)event;
1566 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
1567 isc_result_t evresult = sev->result;
1569 UNUSED(task);
1571 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1573 isc_event_free(&event);
1574 xfr->sends--;
1575 INSIST(xfr->sends == 0);
1577 (void)isc_timer_touch(xfr->client->timer);
1578 if (xfr->shuttingdown == ISC_TRUE) {
1579 xfrout_maybe_destroy(xfr);
1580 } else if (evresult != ISC_R_SUCCESS) {
1581 xfrout_fail(xfr, evresult, "send");
1582 } else if (xfr->end_of_stream == ISC_FALSE) {
1583 sendstream(xfr);
1584 } else {
1585 /* End of zone transfer stream. */
1586 inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
1587 xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
1588 ns_client_next(xfr->client, ISC_R_SUCCESS);
1589 xfrout_ctx_destroy(&xfr);
1593 static void
1594 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1595 xfr->shuttingdown = ISC_TRUE;
1596 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
1597 msg, isc_result_totext(result));
1598 xfrout_maybe_destroy(xfr);
1601 static void
1602 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1603 INSIST(xfr->shuttingdown == ISC_TRUE);
1604 if (xfr->sends > 0) {
1606 * If we are currently sending, cancel it and wait for
1607 * cancel event before destroying the context.
1609 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
1610 ISC_SOCKCANCEL_SEND);
1611 } else {
1612 ns_client_next(xfr->client, ISC_R_CANCELED);
1613 xfrout_ctx_destroy(&xfr);
1617 static void
1618 xfrout_client_shutdown(void *arg, isc_result_t result) {
1619 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
1620 xfrout_fail(xfr, result, "aborted");
1624 * Log outgoing zone transfer messages in a format like
1625 * <client>: transfer of <zone>: <message>
1628 static void
1629 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1630 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1631 ISC_FORMAT_PRINTF(5, 0);
1633 static void
1634 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1635 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1637 char msgbuf[2048];
1638 char namebuf[DNS_NAME_FORMATSIZE];
1639 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1641 dns_name_format(zonename, namebuf, sizeof(namebuf));
1642 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1643 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1644 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1645 NS_LOGMODULE_XFER_OUT, level,
1646 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
1650 * Logging function for use when a xfrout_ctx_t has not yet been created.
1652 static void
1653 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
1654 dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
1655 va_list ap;
1656 va_start(ap, fmt);
1657 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1658 va_end(ap);
1662 * Logging function for use when there is a xfrout_ctx_t.
1664 static void
1665 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
1666 va_list ap;
1667 va_start(ap, fmt);
1668 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
1669 va_end(ap);