etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / named / xfrout.c
blob9c0aa35eadc7fb19305ebeaf15ae17851c74c02d
1 /* $NetBSD: xfrout.c,v 1.9 2015/07/08 17:28:55 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2015 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 */
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 #include <dns/dlz.h>
34 #include <dns/fixedname.h>
35 #include <dns/journal.h>
36 #include <dns/message.h>
37 #include <dns/peer.h>
38 #include <dns/rdataclass.h>
39 #include <dns/rdatalist.h>
40 #include <dns/rdataset.h>
41 #include <dns/rdatasetiter.h>
42 #include <dns/result.h>
43 #include <dns/rriterator.h>
44 #include <dns/soa.h>
45 #include <dns/stats.h>
46 #include <dns/timer.h>
47 #include <dns/tsig.h>
48 #include <dns/view.h>
49 #include <dns/zone.h>
50 #include <dns/zt.h>
52 #include <named/client.h>
53 #include <named/log.h>
54 #include <named/server.h>
55 #include <named/xfrout.h>
57 #include "pfilter.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 (/*CONSTCOND*/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 (/*CONSTCOND*/0)
112 #define CHECK(op) \
113 do { result = (op); \
114 if (result != ISC_R_SUCCESS) goto failure; \
115 } while (/*CONSTCOND*/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 = NULL;
255 isc_mem_attach(mctx, &s->common.mctx);
256 s->common.methods = &ixfr_rrstream_methods;
257 s->journal = NULL;
259 CHECK(dns_journal_open(mctx, journal_filename,
260 DNS_JOURNAL_READ, &s->journal));
261 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
263 *sp = (rrstream_t *) s;
264 return (ISC_R_SUCCESS);
266 failure:
267 ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
268 return (result);
271 static isc_result_t
272 ixfr_rrstream_first(rrstream_t *rs) {
273 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
274 return (dns_journal_first_rr(s->journal));
277 static isc_result_t
278 ixfr_rrstream_next(rrstream_t *rs) {
279 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
280 return (dns_journal_next_rr(s->journal));
283 static void
284 ixfr_rrstream_current(rrstream_t *rs,
285 dns_name_t **name, isc_uint32_t *ttl,
286 dns_rdata_t **rdata)
288 ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
289 dns_journal_current_rr(s->journal, name, ttl, rdata);
292 static void
293 ixfr_rrstream_destroy(rrstream_t **rsp) {
294 ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
295 if (s->journal != 0)
296 dns_journal_destroy(&s->journal);
297 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
300 static rrstream_methods_t ixfr_rrstream_methods = {
301 ixfr_rrstream_first,
302 ixfr_rrstream_next,
303 ixfr_rrstream_current,
304 rrstream_noop_pause,
305 ixfr_rrstream_destroy
308 /**************************************************************************/
310 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
311 * an AXFR-like RR stream from a database.
313 * The SOAs at the beginning and end of the transfer are
314 * not included in the stream.
317 typedef struct axfr_rrstream {
318 rrstream_t common;
319 dns_rriterator_t it;
320 isc_boolean_t it_valid;
321 } axfr_rrstream_t;
324 * Forward declarations.
326 static void
327 axfr_rrstream_destroy(rrstream_t **rsp);
329 static rrstream_methods_t axfr_rrstream_methods;
331 static isc_result_t
332 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
333 rrstream_t **sp)
335 axfr_rrstream_t *s;
336 isc_result_t result;
338 INSIST(sp != NULL && *sp == NULL);
340 s = isc_mem_get(mctx, sizeof(*s));
341 if (s == NULL)
342 return (ISC_R_NOMEMORY);
343 s->common.mctx = NULL;
344 isc_mem_attach(mctx, &s->common.mctx);
345 s->common.methods = &axfr_rrstream_methods;
346 s->it_valid = ISC_FALSE;
348 CHECK(dns_rriterator_init(&s->it, db, ver, 0));
349 s->it_valid = ISC_TRUE;
351 *sp = (rrstream_t *) s;
352 return (ISC_R_SUCCESS);
354 failure:
355 axfr_rrstream_destroy((rrstream_t **) (void *)&s);
356 return (result);
359 static isc_result_t
360 axfr_rrstream_first(rrstream_t *rs) {
361 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
362 isc_result_t result;
363 result = dns_rriterator_first(&s->it);
364 if (result != ISC_R_SUCCESS)
365 return (result);
366 /* Skip SOA records. */
367 for (;;) {
368 dns_name_t *name_dummy = NULL;
369 isc_uint32_t ttl_dummy;
370 dns_rdata_t *rdata = NULL;
371 dns_rriterator_current(&s->it, &name_dummy,
372 &ttl_dummy, NULL, &rdata);
373 if (rdata->type != dns_rdatatype_soa)
374 break;
375 result = dns_rriterator_next(&s->it);
376 if (result != ISC_R_SUCCESS)
377 break;
379 return (result);
382 static isc_result_t
383 axfr_rrstream_next(rrstream_t *rs) {
384 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
385 isc_result_t result;
387 /* Skip SOA records. */
388 for (;;) {
389 dns_name_t *name_dummy = NULL;
390 isc_uint32_t ttl_dummy;
391 dns_rdata_t *rdata = NULL;
392 result = dns_rriterator_next(&s->it);
393 if (result != ISC_R_SUCCESS)
394 break;
395 dns_rriterator_current(&s->it, &name_dummy,
396 &ttl_dummy, NULL, &rdata);
397 if (rdata->type != dns_rdatatype_soa)
398 break;
400 return (result);
403 static void
404 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
405 dns_rdata_t **rdata)
407 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
408 dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
411 static void
412 axfr_rrstream_pause(rrstream_t *rs) {
413 axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
414 dns_rriterator_pause(&s->it);
417 static void
418 axfr_rrstream_destroy(rrstream_t **rsp) {
419 axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
420 if (s->it_valid)
421 dns_rriterator_destroy(&s->it);
422 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
425 static rrstream_methods_t axfr_rrstream_methods = {
426 axfr_rrstream_first,
427 axfr_rrstream_next,
428 axfr_rrstream_current,
429 axfr_rrstream_pause,
430 axfr_rrstream_destroy
433 /**************************************************************************/
435 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
436 * a single SOA record.
439 typedef struct soa_rrstream {
440 rrstream_t common;
441 dns_difftuple_t *soa_tuple;
442 } soa_rrstream_t;
445 * Forward declarations.
447 static void
448 soa_rrstream_destroy(rrstream_t **rsp);
450 static rrstream_methods_t soa_rrstream_methods;
452 static isc_result_t
453 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
454 rrstream_t **sp)
456 soa_rrstream_t *s;
457 isc_result_t result;
459 INSIST(sp != NULL && *sp == NULL);
461 s = isc_mem_get(mctx, sizeof(*s));
462 if (s == NULL)
463 return (ISC_R_NOMEMORY);
464 s->common.mctx = NULL;
465 isc_mem_attach(mctx, &s->common.mctx);
466 s->common.methods = &soa_rrstream_methods;
467 s->soa_tuple = NULL;
469 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
470 &s->soa_tuple));
472 *sp = (rrstream_t *) s;
473 return (ISC_R_SUCCESS);
475 failure:
476 soa_rrstream_destroy((rrstream_t **) (void *)&s);
477 return (result);
480 static isc_result_t
481 soa_rrstream_first(rrstream_t *rs) {
482 UNUSED(rs);
483 return (ISC_R_SUCCESS);
486 static isc_result_t
487 soa_rrstream_next(rrstream_t *rs) {
488 UNUSED(rs);
489 return (ISC_R_NOMORE);
492 static void
493 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
494 dns_rdata_t **rdata)
496 soa_rrstream_t *s = (soa_rrstream_t *) rs;
497 *name = &s->soa_tuple->name;
498 *ttl = s->soa_tuple->ttl;
499 *rdata = &s->soa_tuple->rdata;
502 static void
503 soa_rrstream_destroy(rrstream_t **rsp) {
504 soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
505 if (s->soa_tuple != NULL)
506 dns_difftuple_free(&s->soa_tuple);
507 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
510 static rrstream_methods_t soa_rrstream_methods = {
511 soa_rrstream_first,
512 soa_rrstream_next,
513 soa_rrstream_current,
514 rrstream_noop_pause,
515 soa_rrstream_destroy
518 /**************************************************************************/
520 * A 'compound_rrstream_t' objects owns a soa_rrstream
521 * and another rrstream, the "data stream". It returns
522 * a concatenated stream consisting of the soa_rrstream, then
523 * the data stream, then the soa_rrstream again.
525 * The component streams are owned by the compound_rrstream_t
526 * and are destroyed with it.
529 typedef struct compound_rrstream {
530 rrstream_t common;
531 rrstream_t *components[3];
532 int state;
533 isc_result_t result;
534 } compound_rrstream_t;
537 * Forward declarations.
539 static void
540 compound_rrstream_destroy(rrstream_t **rsp);
542 static isc_result_t
543 compound_rrstream_next(rrstream_t *rs);
545 static rrstream_methods_t compound_rrstream_methods;
548 * Requires:
549 * soa_stream != NULL && *soa_stream != NULL
550 * data_stream != NULL && *data_stream != NULL
551 * sp != NULL && *sp == NULL
553 * Ensures:
554 * *soa_stream == NULL
555 * *data_stream == NULL
556 * *sp points to a valid compound_rrstream_t
557 * The soa and data streams will be destroyed
558 * when the compound_rrstream_t is destroyed.
560 static isc_result_t
561 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
562 rrstream_t **data_stream, rrstream_t **sp)
564 compound_rrstream_t *s;
566 INSIST(sp != NULL && *sp == NULL);
568 s = isc_mem_get(mctx, sizeof(*s));
569 if (s == NULL)
570 return (ISC_R_NOMEMORY);
571 s->common.mctx = NULL;
572 isc_mem_attach(mctx, &s->common.mctx);
573 s->common.methods = &compound_rrstream_methods;
574 s->components[0] = *soa_stream;
575 s->components[1] = *data_stream;
576 s->components[2] = *soa_stream;
577 s->state = -1;
578 s->result = ISC_R_FAILURE;
580 *soa_stream = NULL;
581 *data_stream = NULL;
582 *sp = (rrstream_t *) s;
583 return (ISC_R_SUCCESS);
586 static isc_result_t
587 compound_rrstream_first(rrstream_t *rs) {
588 compound_rrstream_t *s = (compound_rrstream_t *) rs;
589 s->state = 0;
590 do {
591 rrstream_t *curstream = s->components[s->state];
592 s->result = curstream->methods->first(curstream);
593 } while (s->result == ISC_R_NOMORE && s->state < 2);
594 return (s->result);
597 static isc_result_t
598 compound_rrstream_next(rrstream_t *rs) {
599 compound_rrstream_t *s = (compound_rrstream_t *) rs;
600 rrstream_t *curstream = s->components[s->state];
601 s->result = curstream->methods->next(curstream);
602 while (s->result == ISC_R_NOMORE) {
604 * Make sure locks held by the current stream
605 * are released before we switch streams.
607 curstream->methods->pause(curstream);
608 if (s->state == 2)
609 return (ISC_R_NOMORE);
610 s->state++;
611 curstream = s->components[s->state];
612 s->result = curstream->methods->first(curstream);
614 return (s->result);
617 static void
618 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
619 dns_rdata_t **rdata)
621 compound_rrstream_t *s = (compound_rrstream_t *) rs;
622 rrstream_t *curstream;
623 INSIST(0 <= s->state && s->state < 3);
624 INSIST(s->result == ISC_R_SUCCESS);
625 curstream = s->components[s->state];
626 curstream->methods->current(curstream, name, ttl, rdata);
629 static void
630 compound_rrstream_pause(rrstream_t *rs)
632 compound_rrstream_t *s = (compound_rrstream_t *) rs;
633 rrstream_t *curstream;
634 INSIST(0 <= s->state && s->state < 3);
635 curstream = s->components[s->state];
636 curstream->methods->pause(curstream);
639 static void
640 compound_rrstream_destroy(rrstream_t **rsp) {
641 compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
642 s->components[0]->methods->destroy(&s->components[0]);
643 s->components[1]->methods->destroy(&s->components[1]);
644 s->components[2] = NULL; /* Copy of components[0]. */
645 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
648 static rrstream_methods_t compound_rrstream_methods = {
649 compound_rrstream_first,
650 compound_rrstream_next,
651 compound_rrstream_current,
652 compound_rrstream_pause,
653 compound_rrstream_destroy
656 /**************************************************************************/
658 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
659 * in progress.
662 typedef struct {
663 isc_mem_t *mctx;
664 ns_client_t *client;
665 unsigned int id; /* ID of request */
666 dns_name_t *qname; /* Question name of request */
667 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
668 dns_rdataclass_t qclass;
669 dns_zone_t *zone; /* (necessary for stats) */
670 dns_db_t *db;
671 dns_dbversion_t *ver;
672 isc_quota_t *quota;
673 rrstream_t *stream; /* The XFR RR stream */
674 isc_boolean_t end_of_stream; /* EOS has been reached */
675 isc_buffer_t buf; /* Buffer for message owner
676 names and rdatas */
677 isc_buffer_t txlenbuf; /* Transmit length buffer */
678 isc_buffer_t txbuf; /* Transmit message buffer */
679 void *txmem;
680 unsigned int txmemlen;
681 unsigned int nmsg; /* Number of messages sent */
682 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
683 isc_buffer_t *lasttsig; /* the last TSIG */
684 isc_boolean_t many_answers;
685 int sends; /* Send in progress */
686 isc_boolean_t shuttingdown;
687 const char *mnemonic; /* Style of transfer */
688 } xfrout_ctx_t;
690 static isc_result_t
691 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
692 unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
693 dns_rdataclass_t qclass, dns_zone_t *zone,
694 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
695 rrstream_t *stream, dns_tsigkey_t *tsigkey,
696 isc_buffer_t *lasttsig,
697 unsigned int maxtime,
698 unsigned int idletime,
699 isc_boolean_t many_answers,
700 xfrout_ctx_t **xfrp);
702 static void
703 sendstream(xfrout_ctx_t *xfr);
705 static void
706 xfrout_senddone(isc_task_t *task, isc_event_t *event);
708 static void
709 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
711 static void
712 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
714 static void
715 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
717 static void
718 xfrout_client_shutdown(void *arg, isc_result_t result);
720 static void
721 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
722 dns_rdataclass_t rdclass, int level,
723 const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
725 static void
726 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
727 ISC_FORMAT_PRINTF(3, 4);
729 /**************************************************************************/
731 void
732 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
733 isc_result_t result;
734 dns_name_t *question_name;
735 dns_rdataset_t *question_rdataset;
736 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
737 dns_db_t *db = NULL;
738 dns_dbversion_t *ver = NULL;
739 dns_rdataclass_t question_class;
740 rrstream_t *soa_stream = NULL;
741 rrstream_t *data_stream = NULL;
742 rrstream_t *stream = NULL;
743 dns_difftuple_t *current_soa_tuple = NULL;
744 dns_name_t *soa_name;
745 dns_rdataset_t *soa_rdataset;
746 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
747 isc_boolean_t have_soa = ISC_FALSE;
748 const char *mnemonic = NULL;
749 isc_mem_t *mctx = client->mctx;
750 dns_message_t *request = client->message;
751 xfrout_ctx_t *xfr = NULL;
752 isc_quota_t *quota = NULL;
753 dns_transfer_format_t format = client->view->transfer_format;
754 isc_netaddr_t na;
755 dns_peer_t *peer = NULL;
756 isc_buffer_t *tsigbuf = NULL;
757 char *journalfile;
758 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
759 char keyname[DNS_NAME_FORMATSIZE];
760 isc_boolean_t is_poll = ISC_FALSE;
761 isc_boolean_t is_dlz = ISC_FALSE;
762 isc_boolean_t is_ixfr = ISC_FALSE;
763 isc_uint32_t begin_serial = 0, current_serial;
765 switch (reqtype) {
766 case dns_rdatatype_axfr:
767 mnemonic = "AXFR";
768 break;
769 case dns_rdatatype_ixfr:
770 mnemonic = "IXFR";
771 break;
772 default:
773 INSIST(0);
774 break;
777 ns_client_log(client,
778 DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
779 ISC_LOG_DEBUG(6), "%s request", mnemonic);
781 * Apply quota.
783 result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
784 if (result != ISC_R_SUCCESS) {
785 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
786 "%s request denied: %s", mnemonic,
787 isc_result_totext(result));
788 goto failure;
792 * Interpret the question section.
794 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
795 INSIST(result == ISC_R_SUCCESS);
798 * The question section must contain exactly one question, and
799 * it must be for AXFR/IXFR as appropriate.
801 question_name = NULL;
802 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
803 question_rdataset = ISC_LIST_HEAD(question_name->list);
804 question_class = question_rdataset->rdclass;
805 INSIST(question_rdataset->type == reqtype);
806 if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
807 FAILC(DNS_R_FORMERR, "multiple questions");
808 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
809 if (result != ISC_R_NOMORE)
810 FAILC(DNS_R_FORMERR, "multiple questions");
812 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
813 &zone);
815 if (result != ISC_R_SUCCESS) {
817 * Normal zone table does not have a match.
818 * Try the DLZ database
820 // Temporary: only searching the first DLZ database
821 if (! ISC_LIST_EMPTY(client->view->dlz_searched)) {
822 result = dns_dlzallowzonexfr(client->view,
823 question_name,
824 &client->peeraddr,
825 &db);
827 pfilter_notify(result, client, "zonexfr");
828 if (result == ISC_R_NOPERM) {
829 char _buf1[DNS_NAME_FORMATSIZE];
830 char _buf2[DNS_RDATACLASS_FORMATSIZE];
832 result = DNS_R_REFUSED;
833 dns_name_format(question_name, _buf1,
834 sizeof(_buf1));
835 dns_rdataclass_format(question_class,
836 _buf2, sizeof(_buf2));
837 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
838 NS_LOGMODULE_XFER_OUT,
839 ISC_LOG_ERROR,
840 "zone transfer '%s/%s' denied",
841 _buf1, _buf2);
842 goto failure;
844 if (result != ISC_R_SUCCESS)
845 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
846 question_name, question_class);
847 is_dlz = ISC_TRUE;
848 } else {
850 * not DLZ and not in normal zone table, we are
851 * not authoritative
853 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
854 question_name, question_class);
856 } else {
857 /* zone table has a match */
858 switch(dns_zone_gettype(zone)) {
859 /* Master and slave zones are OK for transfer. */
860 case dns_zone_master:
861 case dns_zone_slave:
862 case dns_zone_dlz:
863 break;
864 default:
865 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
866 question_name, question_class);
868 CHECK(dns_zone_getdb(zone, &db));
869 dns_db_currentversion(db, &ver);
872 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
873 "%s question section OK", mnemonic);
876 * Check the authority section. Look for a SOA record with
877 * the same name and class as the question.
879 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
880 result == ISC_R_SUCCESS;
881 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
883 soa_name = NULL;
884 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
885 &soa_name);
888 * Ignore data whose owner name is not the zone apex.
890 if (! dns_name_equal(soa_name, question_name))
891 continue;
893 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
894 soa_rdataset != NULL;
895 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
898 * Ignore non-SOA data.
900 if (soa_rdataset->type != dns_rdatatype_soa)
901 continue;
902 if (soa_rdataset->rdclass != question_class)
903 continue;
905 CHECK(dns_rdataset_first(soa_rdataset));
906 dns_rdataset_current(soa_rdataset, &soa_rdata);
907 result = dns_rdataset_next(soa_rdataset);
908 if (result == ISC_R_SUCCESS)
909 FAILC(DNS_R_FORMERR,
910 "IXFR authority section "
911 "has multiple SOAs");
912 have_soa = ISC_TRUE;
913 goto got_soa;
916 got_soa:
917 if (result != ISC_R_NOMORE)
918 CHECK(result);
920 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
921 "%s authority section OK", mnemonic);
924 * If not a DLZ zone, decide whether to allow this transfer.
926 if (!is_dlz) {
927 ns_client_aclmsg("zone transfer", question_name, reqtype,
928 client->view->rdclass, msg, sizeof(msg));
929 CHECK(ns_client_checkacl(client, NULL, msg,
930 dns_zone_getxfracl(zone),
931 ISC_TRUE, ISC_LOG_ERROR));
935 * AXFR over UDP is not possible.
937 if (reqtype == dns_rdatatype_axfr &&
938 (client->attributes & NS_CLIENTATTR_TCP) == 0)
939 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
942 * Look up the requesting server in the peer table.
944 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
945 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
948 * Decide on the transfer format (one-answer or many-answers).
950 if (peer != NULL)
951 (void)dns_peer_gettransferformat(peer, &format);
954 * Get a dynamically allocated copy of the current SOA.
956 if (is_dlz)
957 dns_db_currentversion(db, &ver);
959 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
960 &current_soa_tuple));
962 current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
963 if (reqtype == dns_rdatatype_ixfr) {
964 isc_boolean_t provide_ixfr;
967 * Outgoing IXFR may have been disabled for this peer
968 * or globally.
970 provide_ixfr = client->view->provideixfr;
971 if (peer != NULL)
972 (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
973 if (provide_ixfr == ISC_FALSE)
974 goto axfr_fallback;
976 if (! have_soa)
977 FAILC(DNS_R_FORMERR,
978 "IXFR request missing SOA");
980 begin_serial = dns_soa_getserial(&soa_rdata);
983 * RFC1995 says "If an IXFR query with the same or
984 * newer version number than that of the server
985 * is received, it is replied to with a single SOA
986 * record of the server's current version, just as
987 * in AXFR". The claim about AXFR is incorrect,
988 * but other than that, we do as the RFC says.
990 * Sending a single SOA record is also how we refuse
991 * IXFR over UDP (currently, we always do).
993 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
994 (client->attributes & NS_CLIENTATTR_TCP) == 0)
996 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
997 is_poll = ISC_TRUE;
998 goto have_stream;
1000 journalfile = is_dlz ? NULL : dns_zone_getjournal(zone);
1001 if (journalfile != NULL)
1002 result = ixfr_rrstream_create(mctx,
1003 journalfile,
1004 begin_serial,
1005 current_serial,
1006 &data_stream);
1007 else
1008 result = ISC_R_NOTFOUND;
1009 if (result == ISC_R_NOTFOUND ||
1010 result == ISC_R_RANGE) {
1011 xfrout_log1(client, question_name, question_class,
1012 ISC_LOG_DEBUG(4),
1013 "IXFR version not in journal, "
1014 "falling back to AXFR");
1015 mnemonic = "AXFR-style IXFR";
1016 goto axfr_fallback;
1018 CHECK(result);
1019 is_ixfr = ISC_TRUE;
1020 } else {
1021 axfr_fallback:
1022 CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream));
1026 * Bracket the data stream with SOAs.
1028 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1029 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1030 &stream));
1031 soa_stream = NULL;
1032 data_stream = NULL;
1034 have_stream:
1035 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1037 * Create the xfrout context object. This transfers the ownership
1038 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1043 if (is_dlz)
1044 CHECK(xfrout_ctx_create(mctx, client, request->id,
1045 question_name, reqtype, question_class,
1046 zone, db, ver, quota, stream,
1047 dns_message_gettsigkey(request),
1048 tsigbuf,
1049 3600,
1050 3600,
1051 (format == dns_many_answers) ?
1052 ISC_TRUE : ISC_FALSE,
1053 &xfr));
1054 else
1055 CHECK(xfrout_ctx_create(mctx, client, request->id,
1056 question_name, reqtype, question_class,
1057 zone, db, ver, quota, stream,
1058 dns_message_gettsigkey(request),
1059 tsigbuf,
1060 dns_zone_getmaxxfrout(zone),
1061 dns_zone_getidleout(zone),
1062 (format == dns_many_answers) ?
1063 ISC_TRUE : ISC_FALSE,
1064 &xfr));
1066 xfr->mnemonic = mnemonic;
1067 stream = NULL;
1068 quota = NULL;
1070 CHECK(xfr->stream->methods->first(xfr->stream));
1072 if (xfr->tsigkey != NULL)
1073 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
1074 else
1075 keyname[0] = '\0';
1076 if (is_poll)
1077 xfrout_log1(client, question_name, question_class,
1078 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
1079 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1080 else if (is_ixfr)
1081 xfrout_log1(client, question_name, question_class,
1082 ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)",
1083 mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
1084 keyname, begin_serial, current_serial);
1085 else
1086 xfrout_log1(client, question_name, question_class,
1087 ISC_LOG_INFO, "%s started%s%s (serial %u)",
1088 mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "",
1089 keyname, current_serial);
1092 if (zone != NULL) {
1093 dns_zone_getraw(zone, &raw);
1094 mayberaw = (raw != NULL) ? raw : zone;
1095 if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
1096 dns_zone_gettype(mayberaw) == dns_zone_slave) {
1097 isc_time_t expiretime;
1098 isc_uint32_t secs;
1099 dns_zone_getexpiretime(zone, &expiretime);
1100 secs = isc_time_seconds(&expiretime);
1101 if (secs >= client->now && result == ISC_R_SUCCESS) {
1102 client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
1103 client->expire = secs - client->now;
1106 if (raw != NULL)
1107 dns_zone_detach(&raw);
1111 * Hand the context over to sendstream(). Set xfr to NULL;
1112 * sendstream() is responsible for either passing the
1113 * context on to a later event handler or destroying it.
1115 sendstream(xfr);
1116 xfr = NULL;
1118 result = ISC_R_SUCCESS;
1120 failure:
1121 if (result == DNS_R_REFUSED)
1122 inc_stats(zone, dns_nsstatscounter_xfrrej);
1123 if (quota != NULL)
1124 isc_quota_detach(&quota);
1125 if (current_soa_tuple != NULL)
1126 dns_difftuple_free(&current_soa_tuple);
1127 if (stream != NULL)
1128 stream->methods->destroy(&stream);
1129 if (soa_stream != NULL)
1130 soa_stream->methods->destroy(&soa_stream);
1131 if (data_stream != NULL)
1132 data_stream->methods->destroy(&data_stream);
1133 if (ver != NULL)
1134 dns_db_closeversion(db, &ver, ISC_FALSE);
1135 if (db != NULL)
1136 dns_db_detach(&db);
1137 if (zone != NULL)
1138 dns_zone_detach(&zone);
1139 /* XXX kludge */
1140 if (xfr != NULL) {
1141 xfrout_fail(xfr, result, "setting up zone transfer");
1142 } else if (result != ISC_R_SUCCESS) {
1143 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1144 NS_LOGMODULE_XFER_OUT,
1145 ISC_LOG_DEBUG(3), "zone transfer setup failed");
1146 ns_client_error(client, result);
1150 static isc_result_t
1151 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1152 dns_name_t *qname, dns_rdatatype_t qtype,
1153 dns_rdataclass_t qclass, dns_zone_t *zone,
1154 dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
1155 rrstream_t *stream, dns_tsigkey_t *tsigkey,
1156 isc_buffer_t *lasttsig, unsigned int maxtime,
1157 unsigned int idletime, isc_boolean_t many_answers,
1158 xfrout_ctx_t **xfrp)
1160 xfrout_ctx_t *xfr;
1161 isc_result_t result;
1162 unsigned int len;
1163 void *mem;
1165 INSIST(xfrp != NULL && *xfrp == NULL);
1166 xfr = isc_mem_get(mctx, sizeof(*xfr));
1167 if (xfr == NULL)
1168 return (ISC_R_NOMEMORY);
1169 xfr->mctx = NULL;
1170 isc_mem_attach(mctx, &xfr->mctx);
1171 xfr->client = NULL;
1172 ns_client_attach(client, &xfr->client);
1173 xfr->id = id;
1174 xfr->qname = qname;
1175 xfr->qtype = qtype;
1176 xfr->qclass = qclass;
1177 xfr->zone = NULL;
1178 xfr->db = NULL;
1179 xfr->ver = NULL;
1180 if (zone != NULL) /* zone will be NULL if it's DLZ */
1181 dns_zone_attach(zone, &xfr->zone);
1182 dns_db_attach(db, &xfr->db);
1183 dns_db_attachversion(db, ver, &xfr->ver);
1184 xfr->end_of_stream = ISC_FALSE;
1185 xfr->tsigkey = tsigkey;
1186 xfr->lasttsig = lasttsig;
1187 xfr->txmem = NULL;
1188 xfr->txmemlen = 0;
1189 xfr->nmsg = 0;
1190 xfr->many_answers = many_answers,
1191 xfr->sends = 0;
1192 xfr->shuttingdown = ISC_FALSE;
1193 xfr->mnemonic = NULL;
1194 xfr->buf.base = NULL;
1195 xfr->buf.length = 0;
1196 xfr->txmem = NULL;
1197 xfr->txmemlen = 0;
1198 xfr->stream = NULL;
1199 xfr->quota = NULL;
1202 * Allocate a temporary buffer for the uncompressed response
1203 * message data. The size should be no more than 65535 bytes
1204 * so that the compressed data will fit in a TCP message,
1205 * and no less than 65535 bytes so that an almost maximum-sized
1206 * RR will fit. Note that although 65535-byte RRs are allowed
1207 * in principle, they cannot be zone-transferred (at least not
1208 * if uncompressible), because the message and RR headers would
1209 * push the size of the TCP message over the 65536 byte limit.
1211 len = 65535;
1212 mem = isc_mem_get(mctx, len);
1213 if (mem == NULL) {
1214 result = ISC_R_NOMEMORY;
1215 goto failure;
1217 isc_buffer_init(&xfr->buf, mem, len);
1220 * Allocate another temporary buffer for the compressed
1221 * response message and its TCP length prefix.
1223 len = 2 + 65535;
1224 mem = isc_mem_get(mctx, len);
1225 if (mem == NULL) {
1226 result = ISC_R_NOMEMORY;
1227 goto failure;
1229 isc_buffer_init(&xfr->txlenbuf, mem, 2);
1230 isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
1231 xfr->txmem = mem;
1232 xfr->txmemlen = len;
1234 CHECK(dns_timer_setidle(xfr->client->timer,
1235 maxtime, idletime, ISC_FALSE));
1238 * Register a shutdown callback with the client, so that we
1239 * can stop the transfer immediately when the client task
1240 * gets a shutdown event.
1242 xfr->client->shutdown = xfrout_client_shutdown;
1243 xfr->client->shutdown_arg = xfr;
1245 * These MUST be after the last "goto failure;" / CHECK to
1246 * prevent a double free by the caller.
1248 xfr->quota = quota;
1249 xfr->stream = stream;
1251 *xfrp = xfr;
1252 return (ISC_R_SUCCESS);
1254 failure:
1255 xfrout_ctx_destroy(&xfr);
1256 return (result);
1261 * Arrange to send as much as we can of "stream" without blocking.
1263 * Requires:
1264 * The stream iterator is initialized and points at an RR,
1265 * or possibly at the end of the stream (that is, the
1266 * _first method of the iterator has been called).
1268 static void
1269 sendstream(xfrout_ctx_t *xfr) {
1270 dns_message_t *tcpmsg = NULL;
1271 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1272 isc_result_t result;
1273 isc_region_t used;
1274 isc_region_t region;
1275 dns_rdataset_t *qrdataset;
1276 dns_name_t *msgname = NULL;
1277 dns_rdata_t *msgrdata = NULL;
1278 dns_rdatalist_t *msgrdl = NULL;
1279 dns_rdataset_t *msgrds = NULL;
1280 dns_compress_t cctx;
1281 isc_boolean_t cleanup_cctx = ISC_FALSE;
1283 int n_rrs;
1285 isc_buffer_clear(&xfr->buf);
1286 isc_buffer_clear(&xfr->txlenbuf);
1287 isc_buffer_clear(&xfr->txbuf);
1289 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
1291 * In the UDP case, we put the response data directly into
1292 * the client message.
1294 msg = xfr->client->message;
1295 CHECK(dns_message_reply(msg, ISC_TRUE));
1296 } else {
1298 * TCP. Build a response dns_message_t, temporarily storing
1299 * the raw, uncompressed owner names and RR data contiguously
1300 * in xfr->buf. We know that if the uncompressed data fits
1301 * in xfr->buf, the compressed data will surely fit in a TCP
1302 * message.
1305 CHECK(dns_message_create(xfr->mctx,
1306 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
1307 msg = tcpmsg;
1309 msg->id = xfr->id;
1310 msg->rcode = dns_rcode_noerror;
1311 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1312 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
1313 msg->flags |= DNS_MESSAGEFLAG_RA;
1314 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1315 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1316 if (xfr->lasttsig != NULL)
1317 isc_buffer_free(&xfr->lasttsig);
1320 * Add a EDNS option to the message?
1322 if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
1323 dns_rdataset_t *opt = NULL;
1325 CHECK(ns_client_addopt(xfr->client, msg, &opt));
1326 CHECK(dns_message_setopt(msg, opt));
1328 * Add to first message only.
1330 xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
1331 xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
1335 * Account for reserved space.
1337 if (xfr->tsigkey != NULL)
1338 INSIST(msg->reserved != 0U);
1339 isc_buffer_add(&xfr->buf, msg->reserved);
1342 * Include a question section in the first message only.
1343 * BIND 8.2.1 will not recognize an IXFR if it does not
1344 * have a question section.
1346 if (xfr->nmsg == 0) {
1347 dns_name_t *qname = NULL;
1348 isc_region_t r;
1351 * Reserve space for the 12-byte message header
1352 * and 4 bytes of question.
1354 isc_buffer_add(&xfr->buf, 12 + 4);
1356 qrdataset = NULL;
1357 result = dns_message_gettemprdataset(msg, &qrdataset);
1358 if (result != ISC_R_SUCCESS)
1359 goto failure;
1360 dns_rdataset_makequestion(qrdataset,
1361 xfr->client->message->rdclass,
1362 xfr->qtype);
1364 result = dns_message_gettempname(msg, &qname);
1365 if (result != ISC_R_SUCCESS)
1366 goto failure;
1367 dns_name_init(qname, NULL);
1368 isc_buffer_availableregion(&xfr->buf, &r);
1369 INSIST(r.length >= xfr->qname->length);
1370 r.length = xfr->qname->length;
1371 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1372 xfr->qname->length);
1373 dns_name_fromregion(qname, &r);
1374 ISC_LIST_INIT(qname->list);
1375 ISC_LIST_APPEND(qname->list, qrdataset, link);
1377 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1378 } else {
1380 * Reserve space for the 12-byte message header
1382 isc_buffer_add(&xfr->buf, 12);
1383 msg->tcp_continuation = 1;
1388 * Try to fit in as many RRs as possible, unless "one-answer"
1389 * format has been requested.
1391 for (n_rrs = 0; ; n_rrs++) {
1392 dns_name_t *name = NULL;
1393 isc_uint32_t ttl;
1394 dns_rdata_t *rdata = NULL;
1396 unsigned int size;
1397 isc_region_t r;
1399 msgname = NULL;
1400 msgrdata = NULL;
1401 msgrdl = NULL;
1402 msgrds = NULL;
1404 xfr->stream->methods->current(xfr->stream,
1405 &name, &ttl, &rdata);
1406 size = name->length + 10 + rdata->length;
1407 isc_buffer_availableregion(&xfr->buf, &r);
1408 if (size >= r.length) {
1410 * RR would not fit. If there are other RRs in the
1411 * buffer, send them now and leave this RR to the
1412 * next message. If this RR overflows the buffer
1413 * all by itself, fail.
1415 * In theory some RRs might fit in a TCP message
1416 * when compressed even if they do not fit when
1417 * uncompressed, but surely we don't want
1418 * to send such monstrosities to an unsuspecting
1419 * slave.
1421 if (n_rrs == 0) {
1422 xfrout_log(xfr, ISC_LOG_WARNING,
1423 "RR too large for zone transfer "
1424 "(%d bytes)", size);
1425 /* XXX DNS_R_RRTOOLARGE? */
1426 result = ISC_R_NOSPACE;
1427 goto failure;
1429 break;
1432 if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
1433 log_rr(name, rdata, ttl); /* XXX */
1435 result = dns_message_gettempname(msg, &msgname);
1436 if (result != ISC_R_SUCCESS)
1437 goto failure;
1438 dns_name_init(msgname, NULL);
1439 isc_buffer_availableregion(&xfr->buf, &r);
1440 INSIST(r.length >= name->length);
1441 r.length = name->length;
1442 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1443 dns_name_fromregion(msgname, &r);
1445 /* Reserve space for RR header. */
1446 isc_buffer_add(&xfr->buf, 10);
1448 result = dns_message_gettemprdata(msg, &msgrdata);
1449 if (result != ISC_R_SUCCESS)
1450 goto failure;
1451 isc_buffer_availableregion(&xfr->buf, &r);
1452 r.length = rdata->length;
1453 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1454 dns_rdata_init(msgrdata);
1455 dns_rdata_fromregion(msgrdata,
1456 rdata->rdclass, rdata->type, &r);
1458 result = dns_message_gettemprdatalist(msg, &msgrdl);
1459 if (result != ISC_R_SUCCESS)
1460 goto failure;
1461 msgrdl->type = rdata->type;
1462 msgrdl->rdclass = rdata->rdclass;
1463 msgrdl->ttl = ttl;
1464 if (rdata->type == dns_rdatatype_sig ||
1465 rdata->type == dns_rdatatype_rrsig)
1466 msgrdl->covers = dns_rdata_covers(rdata);
1467 else
1468 msgrdl->covers = dns_rdatatype_none;
1469 ISC_LINK_INIT(msgrdl, link);
1470 ISC_LIST_INIT(msgrdl->rdata);
1471 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1473 result = dns_message_gettemprdataset(msg, &msgrds);
1474 if (result != ISC_R_SUCCESS)
1475 goto failure;
1476 result = dns_rdatalist_tordataset(msgrdl, msgrds);
1477 INSIST(result == ISC_R_SUCCESS);
1479 ISC_LIST_APPEND(msgname->list, msgrds, link);
1481 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1482 msgname = NULL;
1484 result = xfr->stream->methods->next(xfr->stream);
1485 if (result == ISC_R_NOMORE) {
1486 xfr->end_of_stream = ISC_TRUE;
1487 break;
1489 CHECK(result);
1491 if (! xfr->many_answers)
1492 break;
1495 if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
1496 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1497 dns_compress_setsensitive(&cctx, ISC_TRUE);
1498 cleanup_cctx = ISC_TRUE;
1499 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1500 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1501 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1502 CHECK(dns_message_renderend(msg));
1503 dns_compress_invalidate(&cctx);
1504 cleanup_cctx = ISC_FALSE;
1506 isc_buffer_usedregion(&xfr->txbuf, &used);
1507 isc_buffer_putuint16(&xfr->txlenbuf,
1508 (isc_uint16_t)used.length);
1509 region.base = xfr->txlenbuf.base;
1510 region.length = 2 + used.length;
1511 xfrout_log(xfr, ISC_LOG_DEBUG(8),
1512 "sending TCP message of %d bytes",
1513 used.length);
1514 CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
1515 &region, xfr->client->task,
1516 xfrout_senddone,
1517 xfr));
1518 xfr->sends++;
1519 } else {
1520 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1521 ns_client_send(xfr->client);
1522 xfr->stream->methods->pause(xfr->stream);
1523 xfrout_ctx_destroy(&xfr);
1524 return;
1527 /* Advance lasttsig to be the last TSIG generated */
1528 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1530 xfr->nmsg++;
1532 failure:
1533 if (msgname != NULL) {
1534 if (msgrds != NULL) {
1535 if (dns_rdataset_isassociated(msgrds))
1536 dns_rdataset_disassociate(msgrds);
1537 dns_message_puttemprdataset(msg, &msgrds);
1539 if (msgrdl != NULL) {
1540 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1541 dns_message_puttemprdatalist(msg, &msgrdl);
1543 if (msgrdata != NULL)
1544 dns_message_puttemprdata(msg, &msgrdata);
1545 dns_message_puttempname(msg, &msgname);
1548 if (tcpmsg != NULL)
1549 dns_message_destroy(&tcpmsg);
1551 if (cleanup_cctx)
1552 dns_compress_invalidate(&cctx);
1554 * Make sure to release any locks held by database
1555 * iterators before returning from the event handler.
1557 xfr->stream->methods->pause(xfr->stream);
1559 if (result == ISC_R_SUCCESS)
1560 return;
1562 xfrout_fail(xfr, result, "sending zone data");
1565 static void
1566 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1567 xfrout_ctx_t *xfr = *xfrp;
1568 ns_client_t *client = NULL;
1570 INSIST(xfr->sends == 0);
1572 xfr->client->shutdown = NULL;
1573 xfr->client->shutdown_arg = NULL;
1575 if (xfr->stream != NULL)
1576 xfr->stream->methods->destroy(&xfr->stream);
1577 if (xfr->buf.base != NULL)
1578 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1579 if (xfr->txmem != NULL)
1580 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1581 if (xfr->lasttsig != NULL)
1582 isc_buffer_free(&xfr->lasttsig);
1583 if (xfr->quota != NULL)
1584 isc_quota_detach(&xfr->quota);
1585 if (xfr->ver != NULL)
1586 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1587 if (xfr->zone != NULL)
1588 dns_zone_detach(&xfr->zone);
1589 if (xfr->db != NULL)
1590 dns_db_detach(&xfr->db);
1593 * We want to detch the client after we have released the memory
1594 * context as ns_client_detach checks the memory reference count.
1596 ns_client_attach(xfr->client, &client);
1597 ns_client_detach(&xfr->client);
1598 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
1599 ns_client_detach(&client);
1601 *xfrp = NULL;
1604 static void
1605 xfrout_senddone(isc_task_t *task, isc_event_t *event) {
1606 isc_socketevent_t *sev = (isc_socketevent_t *)event;
1607 xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
1608 isc_result_t evresult = sev->result;
1610 UNUSED(task);
1612 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1614 isc_event_free(&event);
1615 xfr->sends--;
1616 INSIST(xfr->sends == 0);
1618 (void)isc_timer_touch(xfr->client->timer);
1619 if (xfr->shuttingdown == ISC_TRUE) {
1620 xfrout_maybe_destroy(xfr);
1621 } else if (evresult != ISC_R_SUCCESS) {
1622 xfrout_fail(xfr, evresult, "send");
1623 } else if (xfr->end_of_stream == ISC_FALSE) {
1624 sendstream(xfr);
1625 } else {
1626 /* End of zone transfer stream. */
1627 inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
1628 xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
1629 ns_client_next(xfr->client, ISC_R_SUCCESS);
1630 xfrout_ctx_destroy(&xfr);
1634 static void
1635 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1636 xfr->shuttingdown = ISC_TRUE;
1637 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
1638 msg, isc_result_totext(result));
1639 xfrout_maybe_destroy(xfr);
1642 static void
1643 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1644 INSIST(xfr->shuttingdown == ISC_TRUE);
1645 if (xfr->sends > 0) {
1647 * If we are currently sending, cancel it and wait for
1648 * cancel event before destroying the context.
1650 isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
1651 ISC_SOCKCANCEL_SEND);
1652 } else {
1653 ns_client_next(xfr->client, ISC_R_CANCELED);
1654 xfrout_ctx_destroy(&xfr);
1658 static void
1659 xfrout_client_shutdown(void *arg, isc_result_t result) {
1660 xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
1661 xfrout_fail(xfr, result, "aborted");
1665 * Log outgoing zone transfer messages in a format like
1666 * <client>: transfer of <zone>: <message>
1669 static void
1670 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1671 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1672 ISC_FORMAT_PRINTF(5, 0);
1674 static void
1675 xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1676 dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1678 char msgbuf[2048];
1679 char namebuf[DNS_NAME_FORMATSIZE];
1680 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1682 dns_name_format(zonename, namebuf, sizeof(namebuf));
1683 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1684 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1685 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1686 NS_LOGMODULE_XFER_OUT, level,
1687 "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
1691 * Logging function for use when a xfrout_ctx_t has not yet been created.
1693 static void
1694 xfrout_log1(ns_client_t *client, dns_name_t *zonename,
1695 dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
1696 va_list ap;
1697 va_start(ap, fmt);
1698 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1699 va_end(ap);
1703 * Logging function for use when there is a xfrout_ctx_t.
1705 static void
1706 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
1707 va_list ap;
1708 va_start(ap, fmt);
1709 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
1710 va_end(ap);