xfrout.c revision 135446
1/*
2 * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003  Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* $Id: xfrout.c,v 1.101.2.5.2.10 2004/04/02 06:08:17 marka Exp $ */
19
20#include <config.h>
21
22#include <isc/formatcheck.h>
23#include <isc/mem.h>
24#include <isc/timer.h>
25#include <isc/print.h>
26#include <isc/util.h>
27
28#include <dns/db.h>
29#include <dns/dbiterator.h>
30#include <dns/fixedname.h>
31#include <dns/journal.h>
32#include <dns/message.h>
33#include <dns/peer.h>
34#include <dns/rdataclass.h>
35#include <dns/rdatalist.h>
36#include <dns/rdataset.h>
37#include <dns/rdatasetiter.h>
38#include <dns/result.h>
39#include <dns/soa.h>
40#include <dns/timer.h>
41#include <dns/tsig.h>
42#include <dns/view.h>
43#include <dns/zone.h>
44#include <dns/zt.h>
45
46#include <named/client.h>
47#include <named/log.h>
48#include <named/server.h>
49#include <named/xfrout.h>
50
51/*
52 * Outgoing AXFR and IXFR.
53 */
54
55/*
56 * TODO:
57 *  - IXFR over UDP
58 */
59
60#define XFROUT_COMMON_LOGARGS \
61	ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
62
63#define XFROUT_PROTOCOL_LOGARGS \
64	XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
65
66#define XFROUT_DEBUG_LOGARGS(n) \
67	XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
68
69#define XFROUT_RR_LOGARGS \
70	XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
71
72#define XFROUT_RR_LOGLEVEL	ISC_LOG_DEBUG(8)
73
74/*
75 * Fail unconditionally and log as a client error.
76 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
77 * from complaining about "end-of-loop code not reached".
78 */
79#define FAILC(code, msg) \
80	do {							\
81		result = (code);				\
82		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
83			   NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
84			   "bad zone transfer request: %s (%s)", \
85		      	   msg, isc_result_totext(code));	\
86		if (result != ISC_R_SUCCESS) goto failure;	\
87	} while (0)
88
89#define FAILQ(code, msg, question, rdclass) \
90	do {							\
91		char _buf1[DNS_NAME_FORMATSIZE];		\
92		char _buf2[DNS_RDATACLASS_FORMATSIZE]; 		\
93		result = (code);				\
94		dns_name_format(question, _buf1, sizeof(_buf1));  \
95		dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
96		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
97			   NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
98			   "bad zone transfer request: '%s/%s': %s (%s)", \
99		      	   _buf1, _buf2, msg, isc_result_totext(code));	\
100		if (result != ISC_R_SUCCESS) goto failure;	\
101	} while (0)
102
103#define CHECK(op) \
104     	do { result = (op); 					\
105		if (result != ISC_R_SUCCESS) goto failure; 	\
106	} while (0)
107
108/**************************************************************************/
109/*
110 * A db_rr_iterator_t is an iterator that iterates over an entire database,
111 * returning one RR at a time, in some arbitrary order.
112 */
113
114typedef struct db_rr_iterator db_rr_iterator_t;
115
116struct db_rr_iterator {
117	isc_result_t		result;
118	dns_db_t		*db;
119    	dns_dbiterator_t 	*dbit;
120	dns_dbversion_t 	*ver;
121	isc_stdtime_t		now;
122	dns_dbnode_t		*node;
123	dns_fixedname_t		fixedname;
124    	dns_rdatasetiter_t 	*rdatasetit;
125	dns_rdataset_t 		rdataset;
126	dns_rdata_t		rdata;
127};
128
129static isc_result_t
130db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
131		    isc_stdtime_t now);
132
133static isc_result_t
134db_rr_iterator_first(db_rr_iterator_t *it);
135
136static isc_result_t
137db_rr_iterator_next(db_rr_iterator_t *it);
138
139static void
140db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
141		       isc_uint32_t *ttl, dns_rdata_t **rdata);
142
143static void
144db_rr_iterator_destroy(db_rr_iterator_t *it);
145
146static isc_result_t
147db_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
148		    isc_stdtime_t now)
149{
150	isc_result_t result;
151	it->db = db;
152	it->dbit = NULL;
153	it->ver = ver;
154	it->now = now;
155	it->node = NULL;
156	result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit);
157	if (result != ISC_R_SUCCESS)
158		return (result);
159	it->rdatasetit = NULL;
160	dns_rdata_init(&it->rdata);
161	dns_rdataset_init(&it->rdataset);
162	dns_fixedname_init(&it->fixedname);
163	INSIST(! dns_rdataset_isassociated(&it->rdataset));
164	it->result = ISC_R_SUCCESS;
165	return (it->result);
166}
167
168static isc_result_t
169db_rr_iterator_first(db_rr_iterator_t *it) {
170	it->result = dns_dbiterator_first(it->dbit);
171	/*
172	 * The top node may be empty when out of zone glue exists.
173	 * Walk the tree to find the first node with data.
174	 */
175	while (it->result == ISC_R_SUCCESS) {
176		it->result = dns_dbiterator_current(it->dbit, &it->node,
177				    dns_fixedname_name(&it->fixedname));
178		if (it->result != ISC_R_SUCCESS)
179			return (it->result);
180
181		it->result = dns_db_allrdatasets(it->db, it->node,
182						 it->ver, it->now,
183						 &it->rdatasetit);
184		if (it->result != ISC_R_SUCCESS)
185			return (it->result);
186
187		it->result = dns_rdatasetiter_first(it->rdatasetit);
188		if (it->result != ISC_R_SUCCESS) {
189			/*
190			 * This node is empty. Try next node.
191			 */
192			dns_rdatasetiter_destroy(&it->rdatasetit);
193			dns_db_detachnode(it->db, &it->node);
194			it->result = dns_dbiterator_next(it->dbit);
195			continue;
196		}
197		dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
198
199		it->result = dns_rdataset_first(&it->rdataset);
200		return (it->result);
201	}
202	return (it->result);
203}
204
205
206static isc_result_t
207db_rr_iterator_next(db_rr_iterator_t *it) {
208	if (it->result != ISC_R_SUCCESS)
209		return (it->result);
210
211	INSIST(it->dbit != NULL);
212	INSIST(it->node != NULL);
213	INSIST(it->rdatasetit != NULL);
214
215	it->result = dns_rdataset_next(&it->rdataset);
216	if (it->result == ISC_R_NOMORE) {
217		dns_rdataset_disassociate(&it->rdataset);
218		it->result = dns_rdatasetiter_next(it->rdatasetit);
219		/*
220		 * The while loop body is executed more than once
221		 * only when an empty dbnode needs to be skipped.
222		 */
223		while (it->result == ISC_R_NOMORE) {
224			dns_rdatasetiter_destroy(&it->rdatasetit);
225			dns_db_detachnode(it->db, &it->node);
226			it->result = dns_dbiterator_next(it->dbit);
227			if (it->result == ISC_R_NOMORE) {
228				/* We are at the end of the entire database. */
229				return (it->result);
230			}
231			if (it->result != ISC_R_SUCCESS)
232				return (it->result);
233			it->result = dns_dbiterator_current(it->dbit,
234				    &it->node,
235				    dns_fixedname_name(&it->fixedname));
236			if (it->result != ISC_R_SUCCESS)
237				return (it->result);
238			it->result = dns_db_allrdatasets(it->db, it->node,
239					 it->ver, it->now,
240					 &it->rdatasetit);
241			if (it->result != ISC_R_SUCCESS)
242				return (it->result);
243			it->result = dns_rdatasetiter_first(it->rdatasetit);
244		}
245		if (it->result != ISC_R_SUCCESS)
246			return (it->result);
247		dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
248		it->result = dns_rdataset_first(&it->rdataset);
249		if (it->result != ISC_R_SUCCESS)
250			return (it->result);
251	}
252	return (it->result);
253}
254
255static void
256db_rr_iterator_pause(db_rr_iterator_t *it) {
257	RUNTIME_CHECK(dns_dbiterator_pause(it->dbit) == ISC_R_SUCCESS);
258}
259
260static void
261db_rr_iterator_destroy(db_rr_iterator_t *it) {
262	if (dns_rdataset_isassociated(&it->rdataset))
263		dns_rdataset_disassociate(&it->rdataset);
264	if (it->rdatasetit != NULL)
265		dns_rdatasetiter_destroy(&it->rdatasetit);
266	if (it->node != NULL)
267		dns_db_detachnode(it->db, &it->node);
268	dns_dbiterator_destroy(&it->dbit);
269}
270
271static void
272db_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
273		      isc_uint32_t *ttl, dns_rdata_t **rdata)
274{
275	REQUIRE(name != NULL && *name == NULL);
276	REQUIRE(it->result == ISC_R_SUCCESS);
277	*name = dns_fixedname_name(&it->fixedname);
278	*ttl = it->rdataset.ttl;
279	dns_rdata_reset(&it->rdata);
280	dns_rdataset_current(&it->rdataset, &it->rdata);
281	*rdata = &it->rdata;
282}
283
284/**************************************************************************/
285
286/* Log an RR (for debugging) */
287
288static void
289log_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
290	isc_result_t result;
291	isc_buffer_t buf;
292	char mem[2000];
293	dns_rdatalist_t rdl;
294	dns_rdataset_t rds;
295	dns_rdata_t rd = DNS_RDATA_INIT;
296
297	rdl.type = rdata->type;
298	rdl.rdclass = rdata->rdclass;
299	rdl.ttl = ttl;
300	ISC_LIST_INIT(rdl.rdata);
301	ISC_LINK_INIT(&rdl, link);
302	dns_rdataset_init(&rds);
303	dns_rdata_init(&rd);
304	dns_rdata_clone(rdata, &rd);
305	ISC_LIST_APPEND(rdl.rdata, &rd, link);
306	RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
307
308	isc_buffer_init(&buf, mem, sizeof(mem));
309	result = dns_rdataset_totext(&rds, name,
310				     ISC_FALSE, ISC_FALSE, &buf);
311
312	/*
313	 * We could use xfrout_log(), but that would produce
314	 * very long lines with a repetitive prefix.
315	 */
316	if (result == ISC_R_SUCCESS) {
317		/*
318		 * Get rid of final newline.
319		 */
320		INSIST(buf.used >= 1 &&
321		       ((char *) buf.base)[buf.used - 1] == '\n');
322		buf.used--;
323
324		isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
325			      (int)isc_buffer_usedlength(&buf),
326			      (char *)isc_buffer_base(&buf));
327	} else {
328		isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
329	}
330}
331
332/**************************************************************************/
333/*
334 * An 'rrstream_t' is a polymorphic iterator that returns
335 * a stream of resource records.  There are multiple implementations,
336 * e.g. for generating AXFR and IXFR records streams.
337 */
338
339typedef struct rrstream_methods rrstream_methods_t;
340
341typedef struct rrstream {
342	isc_mem_t 		*mctx;
343	rrstream_methods_t	*methods;
344} rrstream_t;
345
346struct rrstream_methods {
347	isc_result_t 		(*first)(rrstream_t *);
348	isc_result_t 		(*next)(rrstream_t *);
349	void			(*current)(rrstream_t *,
350					   dns_name_t **,
351					   isc_uint32_t *,
352					   dns_rdata_t **);
353	void	 		(*pause)(rrstream_t *);
354	void 			(*destroy)(rrstream_t **);
355};
356
357static void
358rrstream_noop_pause(rrstream_t *rs) {
359	UNUSED(rs);
360}
361
362/**************************************************************************/
363/*
364 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
365 * an IXFR-like RR stream from a journal file.
366 *
367 * The SOA at the beginning of each sequence of additions
368 * or deletions are included in the stream, but the extra
369 * SOAs at the beginning and end of the entire transfer are
370 * not included.
371 */
372
373typedef struct ixfr_rrstream {
374	rrstream_t		common;
375	dns_journal_t 		*journal;
376} ixfr_rrstream_t;
377
378/* Forward declarations. */
379static void
380ixfr_rrstream_destroy(rrstream_t **sp);
381
382static rrstream_methods_t ixfr_rrstream_methods;
383
384/*
385 * Returns: anything dns_journal_open() or dns_journal_iter_init()
386 * may return.
387 */
388
389static isc_result_t
390ixfr_rrstream_create(isc_mem_t *mctx,
391		     const char *journal_filename,
392		     isc_uint32_t begin_serial,
393		     isc_uint32_t end_serial,
394		     rrstream_t **sp)
395{
396	ixfr_rrstream_t *s;
397	isc_result_t result;
398
399	INSIST(sp != NULL && *sp == NULL);
400
401	s = isc_mem_get(mctx, sizeof(*s));
402	if (s == NULL)
403		return (ISC_R_NOMEMORY);
404	s->common.mctx = mctx;
405	s->common.methods = &ixfr_rrstream_methods;
406	s->journal = NULL;
407
408	CHECK(dns_journal_open(mctx, journal_filename,
409			       ISC_FALSE, &s->journal));
410	CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
411
412	*sp = (rrstream_t *) s;
413	return (ISC_R_SUCCESS);
414
415 failure:
416	ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
417	return (result);
418}
419
420static isc_result_t
421ixfr_rrstream_first(rrstream_t *rs) {
422	ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
423	return (dns_journal_first_rr(s->journal));
424}
425
426static isc_result_t
427ixfr_rrstream_next(rrstream_t *rs) {
428	ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
429	return (dns_journal_next_rr(s->journal));
430}
431
432static void
433ixfr_rrstream_current(rrstream_t *rs,
434		       dns_name_t **name, isc_uint32_t *ttl,
435		       dns_rdata_t **rdata)
436{
437	ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
438	dns_journal_current_rr(s->journal, name, ttl, rdata);
439}
440
441static void
442ixfr_rrstream_destroy(rrstream_t **rsp) {
443	ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
444	if (s->journal != 0)
445		dns_journal_destroy(&s->journal);
446	isc_mem_put(s->common.mctx, s, sizeof(*s));
447}
448
449static rrstream_methods_t ixfr_rrstream_methods = {
450	ixfr_rrstream_first,
451	ixfr_rrstream_next,
452	ixfr_rrstream_current,
453	rrstream_noop_pause,
454	ixfr_rrstream_destroy
455};
456
457/**************************************************************************/
458/*
459 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
460 * an AXFR-like RR stream from a database.
461 *
462 * The SOAs at the beginning and end of the transfer are
463 * not included in the stream.
464 */
465
466typedef struct axfr_rrstream {
467	rrstream_t		common;
468	db_rr_iterator_t	it;
469	isc_boolean_t		it_valid;
470} axfr_rrstream_t;
471
472/*
473 * Forward declarations.
474 */
475static void
476axfr_rrstream_destroy(rrstream_t **rsp);
477
478static rrstream_methods_t axfr_rrstream_methods;
479
480static isc_result_t
481axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
482		     rrstream_t **sp)
483{
484	axfr_rrstream_t *s;
485	isc_result_t result;
486
487	INSIST(sp != NULL && *sp == NULL);
488
489	s = isc_mem_get(mctx, sizeof(*s));
490	if (s == NULL)
491		return (ISC_R_NOMEMORY);
492	s->common.mctx = mctx;
493	s->common.methods = &axfr_rrstream_methods;
494	s->it_valid = ISC_FALSE;
495
496	CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
497	s->it_valid = ISC_TRUE;
498
499	*sp = (rrstream_t *) s;
500	return (ISC_R_SUCCESS);
501
502 failure:
503	axfr_rrstream_destroy((rrstream_t **) (void *)&s);
504	return (result);
505}
506
507static isc_result_t
508axfr_rrstream_first(rrstream_t *rs) {
509	axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
510	isc_result_t result;
511	result = db_rr_iterator_first(&s->it);
512	if (result != ISC_R_SUCCESS)
513		return (result);
514	/* Skip SOA records. */
515	for (;;) {
516		dns_name_t *name_dummy = NULL;
517		isc_uint32_t ttl_dummy;
518		dns_rdata_t *rdata = NULL;
519		db_rr_iterator_current(&s->it, &name_dummy,
520				      &ttl_dummy, &rdata);
521		if (rdata->type != dns_rdatatype_soa)
522			break;
523		result = db_rr_iterator_next(&s->it);
524		if (result != ISC_R_SUCCESS)
525			break;
526	}
527	return (result);
528}
529
530static isc_result_t
531axfr_rrstream_next(rrstream_t *rs) {
532	axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
533	isc_result_t result;
534
535	/* Skip SOA records. */
536	for (;;) {
537		dns_name_t *name_dummy = NULL;
538		isc_uint32_t ttl_dummy;
539		dns_rdata_t *rdata = NULL;
540		result = db_rr_iterator_next(&s->it);
541		if (result != ISC_R_SUCCESS)
542			break;
543		db_rr_iterator_current(&s->it, &name_dummy,
544				      &ttl_dummy, &rdata);
545		if (rdata->type != dns_rdatatype_soa)
546			break;
547	}
548	return (result);
549}
550
551static void
552axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
553		      dns_rdata_t **rdata)
554{
555	axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
556	db_rr_iterator_current(&s->it, name, ttl, rdata);
557}
558
559static void
560axfr_rrstream_pause(rrstream_t *rs) {
561	axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
562	db_rr_iterator_pause(&s->it);
563}
564
565static void
566axfr_rrstream_destroy(rrstream_t **rsp) {
567	axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
568	if (s->it_valid)
569		db_rr_iterator_destroy(&s->it);
570	isc_mem_put(s->common.mctx, s, sizeof(*s));
571}
572
573static rrstream_methods_t axfr_rrstream_methods = {
574	axfr_rrstream_first,
575	axfr_rrstream_next,
576	axfr_rrstream_current,
577	axfr_rrstream_pause,
578	axfr_rrstream_destroy
579};
580
581/**************************************************************************/
582/*
583 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
584 * a single SOA record.
585 */
586
587typedef struct soa_rrstream {
588	rrstream_t		common;
589	dns_difftuple_t 	*soa_tuple;
590} soa_rrstream_t;
591
592/*
593 * Forward declarations.
594 */
595static void
596soa_rrstream_destroy(rrstream_t **rsp);
597
598static rrstream_methods_t soa_rrstream_methods;
599
600static isc_result_t
601soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
602		    rrstream_t **sp)
603{
604	soa_rrstream_t *s;
605	isc_result_t result;
606
607	INSIST(sp != NULL && *sp == NULL);
608
609	s = isc_mem_get(mctx, sizeof(*s));
610	if (s == NULL)
611		return (ISC_R_NOMEMORY);
612	s->common.mctx = mctx;
613	s->common.methods = &soa_rrstream_methods;
614	s->soa_tuple = NULL;
615
616	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
617				    &s->soa_tuple));
618
619	*sp = (rrstream_t *) s;
620	return (ISC_R_SUCCESS);
621
622 failure:
623	soa_rrstream_destroy((rrstream_t **) (void *)&s);
624	return (result);
625}
626
627static isc_result_t
628soa_rrstream_first(rrstream_t *rs) {
629	UNUSED(rs);
630	return (ISC_R_SUCCESS);
631}
632
633static isc_result_t
634soa_rrstream_next(rrstream_t *rs) {
635	UNUSED(rs);
636	return (ISC_R_NOMORE);
637}
638
639static void
640soa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
641		     dns_rdata_t **rdata)
642{
643	soa_rrstream_t *s = (soa_rrstream_t *) rs;
644	*name = &s->soa_tuple->name;
645	*ttl = s->soa_tuple->ttl;
646	*rdata = &s->soa_tuple->rdata;
647}
648
649static void
650soa_rrstream_destroy(rrstream_t **rsp) {
651	soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
652	if (s->soa_tuple != NULL)
653		dns_difftuple_free(&s->soa_tuple);
654	isc_mem_put(s->common.mctx, s, sizeof(*s));
655}
656
657static rrstream_methods_t soa_rrstream_methods = {
658	soa_rrstream_first,
659	soa_rrstream_next,
660	soa_rrstream_current,
661	rrstream_noop_pause,
662	soa_rrstream_destroy
663};
664
665/**************************************************************************/
666/*
667 * A 'compound_rrstream_t' objects owns a soa_rrstream
668 * and another rrstream, the "data stream".  It returns
669 * a concatenated stream consisting of the soa_rrstream, then
670 * the data stream, then the soa_rrstream again.
671 *
672 * The component streams are owned by the compound_rrstream_t
673 * and are destroyed with it.
674 */
675
676typedef struct compound_rrstream {
677	rrstream_t		common;
678	rrstream_t		*components[3];
679	int			state;
680	isc_result_t		result;
681} compound_rrstream_t;
682
683/*
684 * Forward declarations.
685 */
686static void
687compound_rrstream_destroy(rrstream_t **rsp);
688
689static isc_result_t
690compound_rrstream_next(rrstream_t *rs);
691
692static rrstream_methods_t compound_rrstream_methods;
693
694/*
695 * Requires:
696 *	soa_stream != NULL && *soa_stream != NULL
697 *	data_stream != NULL && *data_stream != NULL
698 *	sp != NULL && *sp == NULL
699 *
700 * Ensures:
701 *	*soa_stream == NULL
702 *	*data_stream == NULL
703 *	*sp points to a valid compound_rrstream_t
704 *	The soa and data streams will be destroyed
705 *	when the compound_rrstream_t is destroyed.
706 */
707static isc_result_t
708compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
709			 rrstream_t **data_stream, rrstream_t **sp)
710{
711	compound_rrstream_t *s;
712
713	INSIST(sp != NULL && *sp == NULL);
714
715	s = isc_mem_get(mctx, sizeof(*s));
716	if (s == NULL)
717		return (ISC_R_NOMEMORY);
718	s->common.mctx = mctx;
719	s->common.methods = &compound_rrstream_methods;
720	s->components[0] = *soa_stream;
721	s->components[1] = *data_stream;
722	s->components[2] = *soa_stream;
723	s->state = -1;
724	s->result = ISC_R_FAILURE;
725
726	*soa_stream = NULL;
727	*data_stream = NULL;
728	*sp = (rrstream_t *) s;
729	return (ISC_R_SUCCESS);
730}
731
732static isc_result_t
733compound_rrstream_first(rrstream_t *rs) {
734	compound_rrstream_t *s = (compound_rrstream_t *) rs;
735	s->state = 0;
736	do {
737		rrstream_t *curstream = s->components[s->state];
738		s->result = curstream->methods->first(curstream);
739	} while (s->result == ISC_R_NOMORE && s->state < 2);
740	return (s->result);
741}
742
743static isc_result_t
744compound_rrstream_next(rrstream_t *rs) {
745	compound_rrstream_t *s = (compound_rrstream_t *) rs;
746	rrstream_t *curstream = s->components[s->state];
747	s->result = curstream->methods->next(curstream);
748	while (s->result == ISC_R_NOMORE) {
749		/*
750		 * Make sure locks held by the current stream
751		 * are released before we switch streams.
752		 */
753		curstream->methods->pause(curstream);
754		if (s->state == 2)
755			return (ISC_R_NOMORE);
756		s->state++;
757		curstream = s->components[s->state];
758		s->result = curstream->methods->first(curstream);
759	}
760	return (s->result);
761}
762
763static void
764compound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
765			  dns_rdata_t **rdata)
766{
767	compound_rrstream_t *s = (compound_rrstream_t *) rs;
768	rrstream_t *curstream;
769	INSIST(0 <= s->state && s->state < 3);
770	INSIST(s->result == ISC_R_SUCCESS);
771	curstream = s->components[s->state];
772	curstream->methods->current(curstream, name, ttl, rdata);
773}
774
775static void
776compound_rrstream_pause(rrstream_t *rs)
777{
778	compound_rrstream_t *s = (compound_rrstream_t *) rs;
779	rrstream_t *curstream;
780	INSIST(0 <= s->state && s->state < 3);
781	curstream = s->components[s->state];
782	curstream->methods->pause(curstream);
783}
784
785static void
786compound_rrstream_destroy(rrstream_t **rsp) {
787	compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
788	s->components[0]->methods->destroy(&s->components[0]);
789	s->components[1]->methods->destroy(&s->components[1]);
790	s->components[2] = NULL; /* Copy of components[0]. */
791	isc_mem_put(s->common.mctx, s, sizeof(*s));
792}
793
794static rrstream_methods_t compound_rrstream_methods = {
795	compound_rrstream_first,
796	compound_rrstream_next,
797	compound_rrstream_current,
798	compound_rrstream_pause,
799	compound_rrstream_destroy
800};
801
802/**************************************************************************/
803/*
804 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
805 * in progress.
806 */
807
808typedef struct {
809	isc_mem_t 		*mctx;
810	ns_client_t		*client;
811	unsigned int 		id;		/* ID of request */
812	dns_name_t		*qname;		/* Question name of request */
813	dns_rdatatype_t		qtype;		/* dns_rdatatype_{a,i}xfr */
814	dns_rdataclass_t	qclass;
815	dns_db_t 		*db;
816	dns_dbversion_t 	*ver;
817	isc_quota_t		*quota;
818	rrstream_t 		*stream;	/* The XFR RR stream */
819	isc_boolean_t		end_of_stream;	/* EOS has been reached */
820	isc_buffer_t 		buf;		/* Buffer for message owner
821						   names and rdatas */
822	isc_buffer_t 		txlenbuf;	/* Transmit length buffer */
823	isc_buffer_t		txbuf;		/* Transmit message buffer */
824	void 			*txmem;
825	unsigned int 		txmemlen;
826	unsigned int		nmsg;		/* Number of messages sent */
827	dns_tsigkey_t		*tsigkey;	/* Key used to create TSIG */
828	isc_buffer_t		*lasttsig;	/* the last TSIG */
829	isc_boolean_t		many_answers;
830	int			sends;		/* Send in progress */
831	isc_boolean_t		shuttingdown;
832	const char		*mnemonic;	/* Style of transfer */
833} xfrout_ctx_t;
834
835static isc_result_t
836xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
837		  unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
838		  dns_rdataclass_t qclass,
839		  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
840		  rrstream_t *stream, dns_tsigkey_t *tsigkey,
841		  isc_buffer_t *lasttsig,
842		  unsigned int maxtime,
843		  unsigned int idletime,
844		  isc_boolean_t many_answers,
845		  xfrout_ctx_t **xfrp);
846
847static void
848sendstream(xfrout_ctx_t *xfr);
849
850static void
851xfrout_senddone(isc_task_t *task, isc_event_t *event);
852
853static void
854xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
855
856static void
857xfrout_maybe_destroy(xfrout_ctx_t *xfr);
858
859static void
860xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
861
862static void
863xfrout_client_shutdown(void *arg, isc_result_t result);
864
865static void
866xfrout_log1(ns_client_t *client, dns_name_t *zonename,
867	    dns_rdataclass_t rdclass, int level,
868	    const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
869
870static void
871xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...)
872	   ISC_FORMAT_PRINTF(3, 4);
873
874/**************************************************************************/
875
876void
877ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
878	isc_result_t result;
879	dns_name_t *question_name;
880	dns_rdataset_t *question_rdataset;
881	dns_zone_t *zone = NULL;
882	dns_db_t *db = NULL;
883	dns_dbversion_t *ver = NULL;
884	dns_rdataclass_t question_class;
885	rrstream_t *soa_stream = NULL;
886	rrstream_t *data_stream = NULL;
887	rrstream_t *stream = NULL;
888	dns_difftuple_t *current_soa_tuple = NULL;
889	dns_name_t *soa_name;
890	dns_rdataset_t *soa_rdataset;
891	dns_rdata_t soa_rdata = DNS_RDATA_INIT;
892	isc_boolean_t have_soa = ISC_FALSE;
893	const char *mnemonic = NULL;
894	isc_mem_t *mctx = client->mctx;
895	dns_message_t *request = client->message;
896	xfrout_ctx_t *xfr = NULL;
897	isc_quota_t *quota = NULL;
898	dns_transfer_format_t format = client->view->transfer_format;
899	isc_netaddr_t na;
900	dns_peer_t *peer = NULL;
901	isc_buffer_t *tsigbuf = NULL;
902	char *journalfile;
903	char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
904	char keyname[DNS_NAME_FORMATSIZE];
905	isc_boolean_t is_poll = ISC_FALSE;
906
907	switch (reqtype) {
908	case dns_rdatatype_axfr:
909		mnemonic = "AXFR";
910		break;
911	case dns_rdatatype_ixfr:
912		mnemonic = "IXFR";
913		break;
914	default:
915		INSIST(0);
916		break;
917	}
918
919	ns_client_log(client,
920		      DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
921		      ISC_LOG_DEBUG(6), "%s request", mnemonic);
922	/*
923	 * Apply quota.
924	 */
925	result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
926	if (result != ISC_R_SUCCESS) {
927		isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
928			      "%s request denied: %s", mnemonic,
929			      isc_result_totext(result));
930		goto failure;
931	}
932
933	/*
934	 * Interpret the question section.
935	 */
936	result = dns_message_firstname(request, DNS_SECTION_QUESTION);
937	INSIST(result == ISC_R_SUCCESS);
938
939	/*
940	 * The question section must contain exactly one question, and
941	 * it must be for AXFR/IXFR as appropriate.
942	 */
943	question_name = NULL;
944	dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
945	question_rdataset = ISC_LIST_HEAD(question_name->list);
946	question_class = question_rdataset->rdclass;
947	INSIST(question_rdataset->type == reqtype);
948	if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
949		FAILC(DNS_R_FORMERR, "multiple questions");
950	result = dns_message_nextname(request, DNS_SECTION_QUESTION);
951	if (result != ISC_R_NOMORE)
952		FAILC(DNS_R_FORMERR, "multiple questions");
953
954	result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
955			     &zone);
956	if (result != ISC_R_SUCCESS)
957		FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
958		      question_name, question_class);
959	switch(dns_zone_gettype(zone)) {
960	case dns_zone_master:
961	case dns_zone_slave:
962		break;	/* Master and slave zones are OK for transfer. */
963	default:
964		FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
965		      question_name, question_class);
966	}
967	CHECK(dns_zone_getdb(zone, &db));
968	dns_db_currentversion(db, &ver);
969
970	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
971		    "%s question section OK", mnemonic);
972
973	/*
974	 * Check the authority section.  Look for a SOA record with
975	 * the same name and class as the question.
976	 */
977	for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
978	     result == ISC_R_SUCCESS;
979	     result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
980	{
981		soa_name = NULL;
982		dns_message_currentname(request, DNS_SECTION_AUTHORITY,
983					&soa_name);
984
985		/*
986		 * Ignore data whose owner name is not the zone apex.
987		 */
988		if (! dns_name_equal(soa_name, question_name))
989			continue;
990
991		for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
992		     soa_rdataset != NULL;
993		     soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
994		{
995			/*
996			 * Ignore non-SOA data.
997			 */
998			if (soa_rdataset->type != dns_rdatatype_soa)
999				continue;
1000			if (soa_rdataset->rdclass != question_class)
1001				continue;
1002
1003			CHECK(dns_rdataset_first(soa_rdataset));
1004			dns_rdataset_current(soa_rdataset, &soa_rdata);
1005			result = dns_rdataset_next(soa_rdataset);
1006			if (result == ISC_R_SUCCESS)
1007				FAILC(DNS_R_FORMERR,
1008				      "IXFR authority section "
1009				      "has multiple SOAs");
1010			have_soa = ISC_TRUE;
1011			goto got_soa;
1012		}
1013	}
1014 got_soa:
1015	if (result != ISC_R_NOMORE)
1016		CHECK(result);
1017
1018	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
1019		    "%s authority section OK", mnemonic);
1020
1021	/*
1022	 * Decide whether to allow this transfer.
1023	 */
1024	ns_client_aclmsg("zone transfer", question_name, reqtype,
1025			 client->view->rdclass, msg, sizeof(msg));
1026	CHECK(ns_client_checkacl(client, msg,
1027				 dns_zone_getxfracl(zone), ISC_TRUE,
1028				 ISC_LOG_ERROR));
1029
1030	/*
1031	 * AXFR over UDP is not possible.
1032	 */
1033	if (reqtype == dns_rdatatype_axfr &&
1034	    (client->attributes & NS_CLIENTATTR_TCP) == 0)
1035		FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
1036
1037	/*
1038	 * Look up the requesting server in the peer table.
1039	 */
1040	isc_netaddr_fromsockaddr(&na, &client->peeraddr);
1041	(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
1042
1043	/*
1044	 * Decide on the transfer format (one-answer or many-answers).
1045	 */
1046	if (peer != NULL)
1047		(void)dns_peer_gettransferformat(peer, &format);
1048
1049	/*
1050	 * Get a dynamically allocated copy of the current SOA.
1051	 */
1052	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
1053				    &current_soa_tuple));
1054
1055	if (reqtype == dns_rdatatype_ixfr) {
1056		isc_uint32_t begin_serial, current_serial;
1057		isc_boolean_t provide_ixfr;
1058
1059		/*
1060		 * Outgoing IXFR may have been disabled for this peer
1061		 * or globally.
1062		 */
1063		provide_ixfr = client->view->provideixfr;
1064		if (peer != NULL)
1065			(void) dns_peer_getprovideixfr(peer, &provide_ixfr);
1066		if (provide_ixfr == ISC_FALSE)
1067			goto axfr_fallback;
1068
1069		if (! have_soa)
1070			FAILC(DNS_R_FORMERR,
1071			      "IXFR request missing SOA");
1072
1073		begin_serial = dns_soa_getserial(&soa_rdata);
1074		current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
1075
1076		/*
1077		 * RFC1995 says "If an IXFR query with the same or
1078		 * newer version number than that of the server
1079		 * is received, it is replied to with a single SOA
1080		 * record of the server's current version, just as
1081		 * in AXFR".  The claim about AXFR is incorrect,
1082		 * but other than that, we do as the RFC says.
1083		 *
1084		 * Sending a single SOA record is also how we refuse
1085		 * IXFR over UDP (currently, we always do).
1086		 */
1087		if (DNS_SERIAL_GE(begin_serial, current_serial) ||
1088		    (client->attributes & NS_CLIENTATTR_TCP) == 0)
1089		{
1090			CHECK(soa_rrstream_create(mctx, db, ver, &stream));
1091			is_poll = ISC_TRUE;
1092			goto have_stream;
1093		}
1094		journalfile = dns_zone_getjournal(zone);
1095		if (journalfile != NULL)
1096			result = ixfr_rrstream_create(mctx,
1097						      journalfile,
1098						      begin_serial,
1099						      current_serial,
1100						      &data_stream);
1101		else
1102			result = ISC_R_NOTFOUND;
1103		if (result == ISC_R_NOTFOUND ||
1104		    result == ISC_R_RANGE) {
1105			xfrout_log1(client, question_name, question_class,
1106				    ISC_LOG_DEBUG(4),
1107				    "IXFR version not in journal, "
1108				    "falling back to AXFR");
1109			mnemonic = "AXFR-style IXFR";
1110			goto axfr_fallback;
1111		}
1112		CHECK(result);
1113	} else {
1114	axfr_fallback:
1115		CHECK(axfr_rrstream_create(mctx, db, ver,
1116					   &data_stream));
1117	}
1118
1119	/*
1120	 * Bracket the the data stream with SOAs.
1121	 */
1122	CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1123	CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1124				       &stream));
1125	soa_stream = NULL;
1126	data_stream = NULL;
1127
1128 have_stream:
1129	CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1130	/*
1131	 * Create the xfrout context object.  This transfers the ownership
1132	 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1133	 */
1134	CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,
1135				reqtype, question_class, db, ver, quota,
1136				stream, dns_message_gettsigkey(request),
1137				tsigbuf,
1138				dns_zone_getmaxxfrout(zone),
1139				dns_zone_getidleout(zone),
1140				(format == dns_many_answers) ?
1141					ISC_TRUE : ISC_FALSE,
1142				&xfr));
1143	xfr->mnemonic = mnemonic;
1144	stream = NULL;
1145	quota = NULL;
1146
1147	CHECK(xfr->stream->methods->first(xfr->stream));
1148
1149	if (xfr->tsigkey != NULL) {
1150		dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
1151	} else
1152		keyname[0] = '\0';
1153	if (is_poll)
1154		xfrout_log1(client, question_name, question_class,
1155			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
1156			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1157	else
1158		xfrout_log1(client, question_name, question_class,
1159			    ISC_LOG_INFO, "%s started%s%s", mnemonic,
1160			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1161
1162	/*
1163	 * Hand the context over to sendstream().  Set xfr to NULL;
1164	 * sendstream() is responsible for either passing the
1165	 * context on to a later event handler or destroying it.
1166	 */
1167	sendstream(xfr);
1168	xfr = NULL;
1169
1170	result = ISC_R_SUCCESS;
1171
1172 failure:
1173	if (quota != NULL)
1174		isc_quota_detach(&quota);
1175	if (current_soa_tuple != NULL)
1176		dns_difftuple_free(&current_soa_tuple);
1177	if (stream != NULL)
1178		stream->methods->destroy(&stream);
1179	if (soa_stream != NULL)
1180		soa_stream->methods->destroy(&soa_stream);
1181	if (data_stream != NULL)
1182		data_stream->methods->destroy(&data_stream);
1183	if (ver != NULL)
1184		dns_db_closeversion(db, &ver, ISC_FALSE);
1185	if (db != NULL)
1186		dns_db_detach(&db);
1187	if (zone != NULL)
1188		dns_zone_detach(&zone);
1189	/* XXX kludge */
1190	if (xfr != NULL) {
1191		xfrout_fail(xfr, result, "setting up zone transfer");
1192	} else if (result != ISC_R_SUCCESS) {
1193		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1194			      NS_LOGMODULE_XFER_OUT,
1195			      ISC_LOG_DEBUG(3), "zone transfer setup failed");
1196		ns_client_error(client, result);
1197	}
1198}
1199
1200static isc_result_t
1201xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1202		  dns_name_t *qname, dns_rdatatype_t qtype,
1203		  dns_rdataclass_t qclass,
1204		  dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
1205		  rrstream_t *stream, dns_tsigkey_t *tsigkey,
1206		  isc_buffer_t *lasttsig, unsigned int maxtime,
1207		  unsigned int idletime, isc_boolean_t many_answers,
1208		  xfrout_ctx_t **xfrp)
1209{
1210	xfrout_ctx_t *xfr;
1211	isc_result_t result;
1212	unsigned int len;
1213	void *mem;
1214
1215	INSIST(xfrp != NULL && *xfrp == NULL);
1216	xfr = isc_mem_get(mctx, sizeof(*xfr));
1217	if (xfr == NULL)
1218		return (ISC_R_NOMEMORY);
1219	xfr->mctx = mctx;
1220	xfr->client = NULL;
1221	ns_client_attach(client, &xfr->client);
1222	xfr->id = id;
1223	xfr->qname = qname;
1224	xfr->qtype = qtype;
1225	xfr->qclass = qclass;
1226	xfr->db = NULL;
1227	xfr->ver = NULL;
1228	dns_db_attach(db, &xfr->db);
1229	dns_db_attachversion(db, ver, &xfr->ver);
1230	xfr->end_of_stream = ISC_FALSE;
1231	xfr->tsigkey = tsigkey;
1232	xfr->lasttsig = lasttsig;
1233	xfr->txmem = NULL;
1234	xfr->txmemlen = 0;
1235	xfr->nmsg = 0;
1236	xfr->many_answers = many_answers,
1237	xfr->sends = 0;
1238	xfr->shuttingdown = ISC_FALSE;
1239	xfr->mnemonic = NULL;
1240	xfr->buf.base = NULL;
1241	xfr->buf.length = 0;
1242	xfr->txmem = NULL;
1243	xfr->txmemlen = 0;
1244	xfr->stream = NULL;
1245	xfr->quota = NULL;
1246
1247	/*
1248	 * Allocate a temporary buffer for the uncompressed response
1249	 * message data.  The size should be no more than 65535 bytes
1250	 * so that the compressed data will fit in a TCP message,
1251	 * and no less than 65535 bytes so that an almost maximum-sized
1252	 * RR will fit.  Note that although 65535-byte RRs are allowed
1253	 * in principle, they cannot be zone-transferred (at least not
1254	 * if uncompressible), because the message and RR headers would
1255	 * push the size of the TCP message over the 65536 byte limit.
1256	 */
1257	len = 65535;
1258	mem = isc_mem_get(mctx, len);
1259	if (mem == NULL) {
1260		result = ISC_R_NOMEMORY;
1261		goto failure;
1262	}
1263	isc_buffer_init(&xfr->buf, mem, len);
1264
1265	/*
1266	 * Allocate another temporary buffer for the compressed
1267	 * response message and its TCP length prefix.
1268	 */
1269	len = 2 + 65535;
1270	mem = isc_mem_get(mctx, len);
1271	if (mem == NULL) {
1272		result = ISC_R_NOMEMORY;
1273		goto failure;
1274	}
1275	isc_buffer_init(&xfr->txlenbuf, mem, 2);
1276	isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
1277	xfr->txmem = mem;
1278	xfr->txmemlen = len;
1279
1280	CHECK(dns_timer_setidle(xfr->client->timer,
1281				maxtime, idletime, ISC_FALSE));
1282
1283	/*
1284	 * Register a shutdown callback with the client, so that we
1285	 * can stop the transfer immediately when the client task
1286	 * gets a shutdown event.
1287	 */
1288	xfr->client->shutdown = xfrout_client_shutdown;
1289	xfr->client->shutdown_arg = xfr;
1290	/*
1291	 * These MUST be after the last "goto failure;" / CHECK to
1292	 * prevent a double free by the caller.
1293	 */
1294	xfr->quota = quota;
1295	xfr->stream = stream;
1296
1297	*xfrp = xfr;
1298	return (ISC_R_SUCCESS);
1299
1300failure:
1301	xfrout_ctx_destroy(&xfr);
1302	return (result);
1303}
1304
1305
1306/*
1307 * Arrange to send as much as we can of "stream" without blocking.
1308 *
1309 * Requires:
1310 *	The stream iterator is initialized and points at an RR,
1311 *      or possiby at the end of the stream (that is, the
1312 *      _first method of the iterator has been called).
1313 */
1314static void
1315sendstream(xfrout_ctx_t *xfr) {
1316	dns_message_t *tcpmsg = NULL;
1317	dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1318	isc_result_t result;
1319	isc_region_t used;
1320	isc_region_t region;
1321	dns_rdataset_t *qrdataset;
1322	dns_name_t *msgname = NULL;
1323	dns_rdata_t *msgrdata = NULL;
1324	dns_rdatalist_t *msgrdl = NULL;
1325	dns_rdataset_t *msgrds = NULL;
1326	dns_compress_t cctx;
1327	isc_boolean_t cleanup_cctx = ISC_FALSE;
1328
1329	int n_rrs;
1330
1331	isc_buffer_clear(&xfr->buf);
1332	isc_buffer_clear(&xfr->txlenbuf);
1333	isc_buffer_clear(&xfr->txbuf);
1334
1335	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
1336		/*
1337		 * In the UDP case, we put the response data directly into
1338		 * the client message.
1339		 */
1340		msg = xfr->client->message;
1341		CHECK(dns_message_reply(msg, ISC_TRUE));
1342	} else {
1343		/*
1344		 * TCP. Build a response dns_message_t, temporarily storing
1345		 * the raw, uncompressed owner names and RR data contiguously
1346		 * in xfr->buf.  We know that if the uncompressed data fits
1347		 * in xfr->buf, the compressed data will surely fit in a TCP
1348		 * message.
1349		 */
1350
1351		CHECK(dns_message_create(xfr->mctx,
1352					 DNS_MESSAGE_INTENTRENDER, &tcpmsg));
1353		msg = tcpmsg;
1354
1355		msg->id = xfr->id;
1356		msg->rcode = dns_rcode_noerror;
1357		msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1358		if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
1359			msg->flags |= DNS_MESSAGEFLAG_RA;
1360		CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1361		CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1362		if (xfr->lasttsig != NULL)
1363			isc_buffer_free(&xfr->lasttsig);
1364
1365		/*
1366		 * Include a question section in the first message only.
1367		 * BIND 8.2.1 will not recognize an IXFR if it does not
1368		 * have a question section.
1369		 */
1370		if (xfr->nmsg == 0) {
1371			dns_name_t *qname = NULL;
1372			isc_region_t r;
1373
1374			/*
1375			 * Reserve space for the 12-byte message header
1376			 * and 4 bytes of question.
1377			 */
1378			isc_buffer_add(&xfr->buf, 12 + 4);
1379
1380			qrdataset = NULL;
1381			result = dns_message_gettemprdataset(msg, &qrdataset);
1382			if (result != ISC_R_SUCCESS)
1383				goto failure;
1384			dns_rdataset_init(qrdataset);
1385			dns_rdataset_makequestion(qrdataset,
1386					xfr->client->message->rdclass,
1387					xfr->qtype);
1388
1389			result = dns_message_gettempname(msg, &qname);
1390			if (result != ISC_R_SUCCESS)
1391				goto failure;
1392			dns_name_init(qname, NULL);
1393			isc_buffer_availableregion(&xfr->buf, &r);
1394			INSIST(r.length >= xfr->qname->length);
1395			r.length = xfr->qname->length;
1396			isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1397					  xfr->qname->length);
1398			dns_name_fromregion(qname, &r);
1399			ISC_LIST_INIT(qname->list);
1400			ISC_LIST_APPEND(qname->list, qrdataset, link);
1401
1402			dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1403		}
1404		else
1405			msg->tcp_continuation = 1;
1406	}
1407
1408	/*
1409	 * Try to fit in as many RRs as possible, unless "one-answer"
1410	 * format has been requested.
1411	 */
1412	for (n_rrs = 0; ; n_rrs++) {
1413		dns_name_t *name = NULL;
1414		isc_uint32_t ttl;
1415		dns_rdata_t *rdata = NULL;
1416
1417		unsigned int size;
1418		isc_region_t r;
1419
1420		msgname = NULL;
1421		msgrdata = NULL;
1422		msgrdl = NULL;
1423		msgrds = NULL;
1424
1425		xfr->stream->methods->current(xfr->stream,
1426					      &name, &ttl, &rdata);
1427		size = name->length + 10 + rdata->length;
1428		isc_buffer_availableregion(&xfr->buf, &r);
1429		if (size >= r.length) {
1430			/*
1431			 * RR would not fit.  If there are other RRs in the
1432			 * buffer, send them now and leave this RR to the
1433			 * next message.  If this RR overflows the buffer
1434			 * all by itself, fail.
1435			 *
1436			 * In theory some RRs might fit in a TCP message
1437			 * when compressed even if they do not fit when
1438			 * uncompressed, but surely we don't want
1439			 * to send such monstrosities to an unsuspecting
1440			 * slave.
1441			 */
1442			if (n_rrs == 0) {
1443				xfrout_log(xfr, ISC_LOG_WARNING,
1444					   "RR too large for zone transfer "
1445					   "(%d bytes)", size);
1446				/* XXX DNS_R_RRTOOLARGE? */
1447				result = ISC_R_NOSPACE;
1448				goto failure;
1449			}
1450			break;
1451		}
1452
1453		if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
1454			log_rr(name, rdata, ttl); /* XXX */
1455
1456		result = dns_message_gettempname(msg, &msgname);
1457		if (result != ISC_R_SUCCESS)
1458			goto failure;
1459		dns_name_init(msgname, NULL);
1460		isc_buffer_availableregion(&xfr->buf, &r);
1461		INSIST(r.length >= name->length);
1462		r.length = name->length;
1463		isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1464		dns_name_fromregion(msgname, &r);
1465
1466		/* Reserve space for RR header. */
1467		isc_buffer_add(&xfr->buf, 10);
1468
1469		result = dns_message_gettemprdata(msg, &msgrdata);
1470		if (result != ISC_R_SUCCESS)
1471			goto failure;
1472		isc_buffer_availableregion(&xfr->buf, &r);
1473		r.length = rdata->length;
1474		isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1475		dns_rdata_init(msgrdata);
1476		dns_rdata_fromregion(msgrdata,
1477				     rdata->rdclass, rdata->type, &r);
1478
1479		result = dns_message_gettemprdatalist(msg, &msgrdl);
1480		if (result != ISC_R_SUCCESS)
1481			goto failure;
1482		msgrdl->type = rdata->type;
1483		msgrdl->rdclass = rdata->rdclass;
1484		msgrdl->ttl = ttl;
1485		ISC_LINK_INIT(msgrdl, link);
1486		ISC_LIST_INIT(msgrdl->rdata);
1487		ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1488
1489		result = dns_message_gettemprdataset(msg, &msgrds);
1490		if (result != ISC_R_SUCCESS)
1491			goto failure;
1492		dns_rdataset_init(msgrds);
1493		result = dns_rdatalist_tordataset(msgrdl, msgrds);
1494		INSIST(result == ISC_R_SUCCESS);
1495
1496		ISC_LIST_APPEND(msgname->list, msgrds, link);
1497
1498		dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1499		msgname = NULL;
1500
1501		result = xfr->stream->methods->next(xfr->stream);
1502		if (result == ISC_R_NOMORE) {
1503			xfr->end_of_stream = ISC_TRUE;
1504			break;
1505		}
1506		CHECK(result);
1507
1508		if (! xfr->many_answers)
1509			break;
1510	}
1511
1512	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
1513		CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1514		cleanup_cctx = ISC_TRUE;
1515		CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1516		CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1517		CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1518		CHECK(dns_message_renderend(msg));
1519		dns_compress_invalidate(&cctx);
1520		cleanup_cctx = ISC_FALSE;
1521
1522		isc_buffer_usedregion(&xfr->txbuf, &used);
1523		isc_buffer_putuint16(&xfr->txlenbuf,
1524				     (isc_uint16_t)used.length);
1525		region.base = xfr->txlenbuf.base;
1526		region.length = 2 + used.length;
1527		xfrout_log(xfr, ISC_LOG_DEBUG(8),
1528			   "sending TCP message of %d bytes",
1529			   used.length);
1530		CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
1531				      &region, xfr->client->task,
1532				      xfrout_senddone,
1533				      xfr));
1534		xfr->sends++;
1535	} else {
1536		xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1537		ns_client_send(xfr->client);
1538		xfr->stream->methods->pause(xfr->stream);
1539		xfrout_ctx_destroy(&xfr);
1540		return;
1541	}
1542
1543	/* Advance lasttsig to be the last TSIG generated */
1544	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1545
1546	xfr->nmsg++;
1547
1548 failure:
1549	if (msgname != NULL) {
1550		if (msgrds != NULL) {
1551			if (dns_rdataset_isassociated(msgrds))
1552				dns_rdataset_disassociate(msgrds);
1553			dns_message_puttemprdataset(msg, &msgrds);
1554		}
1555		if (msgrdl != NULL) {
1556			ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1557			dns_message_puttemprdatalist(msg, &msgrdl);
1558		}
1559		if (msgrdata != NULL)
1560			dns_message_puttemprdata(msg, &msgrdata);
1561		dns_message_puttempname(msg, &msgname);
1562	}
1563
1564	if (tcpmsg != NULL)
1565		dns_message_destroy(&tcpmsg);
1566
1567	if (cleanup_cctx)
1568		dns_compress_invalidate(&cctx);
1569	/*
1570	 * Make sure to release any locks held by database
1571	 * iterators before returning from the event handler.
1572	 */
1573	xfr->stream->methods->pause(xfr->stream);
1574
1575	if (result == ISC_R_SUCCESS)
1576		return;
1577
1578	xfrout_fail(xfr, result, "sending zone data");
1579}
1580
1581static void
1582xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1583	xfrout_ctx_t *xfr = *xfrp;
1584
1585	INSIST(xfr->sends == 0);
1586
1587	xfr->client->shutdown = NULL;
1588	xfr->client->shutdown_arg = NULL;
1589
1590	if (xfr->stream != NULL)
1591		xfr->stream->methods->destroy(&xfr->stream);
1592	if (xfr->buf.base != NULL)
1593		isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1594	if (xfr->txmem != NULL)
1595		isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1596	if (xfr->lasttsig != NULL)
1597		isc_buffer_free(&xfr->lasttsig);
1598	if (xfr->quota != NULL)
1599		isc_quota_detach(&xfr->quota);
1600	if (xfr->ver != NULL)
1601		dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1602	if (xfr->db != NULL)
1603		dns_db_detach(&xfr->db);
1604
1605	ns_client_detach(&xfr->client);
1606
1607	isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1608
1609	*xfrp = NULL;
1610}
1611
1612static void
1613xfrout_senddone(isc_task_t *task, isc_event_t *event) {
1614	isc_socketevent_t *sev = (isc_socketevent_t *)event;
1615	xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
1616	isc_result_t evresult = sev->result;
1617
1618	UNUSED(task);
1619
1620	INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1621
1622	isc_event_free(&event);
1623	xfr->sends--;
1624	INSIST(xfr->sends == 0);
1625
1626	(void)isc_timer_touch(xfr->client->timer);
1627	if (xfr->shuttingdown == ISC_TRUE) {
1628		xfrout_maybe_destroy(xfr);
1629	} else if (evresult != ISC_R_SUCCESS) {
1630		xfrout_fail(xfr, evresult, "send");
1631	} else if (xfr->end_of_stream == ISC_FALSE) {
1632		sendstream(xfr);
1633	} else {
1634		/* End of zone transfer stream. */
1635		xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
1636		ns_client_next(xfr->client, ISC_R_SUCCESS);
1637		xfrout_ctx_destroy(&xfr);
1638	}
1639}
1640
1641static void
1642xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1643	xfr->shuttingdown = ISC_TRUE;
1644	xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
1645		   msg, isc_result_totext(result));
1646	xfrout_maybe_destroy(xfr);
1647}
1648
1649static void
1650xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1651	INSIST(xfr->shuttingdown == ISC_TRUE);
1652	if (xfr->sends > 0) {
1653		/*
1654		 * If we are currently sending, cancel it and wait for
1655		 * cancel event before destroying the context.
1656		 */
1657		isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
1658				  ISC_SOCKCANCEL_SEND);
1659	} else {
1660		ns_client_next(xfr->client, ISC_R_CANCELED);
1661		xfrout_ctx_destroy(&xfr);
1662	}
1663}
1664
1665static void
1666xfrout_client_shutdown(void *arg, isc_result_t result) {
1667	xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
1668	xfrout_fail(xfr, result, "aborted");
1669}
1670
1671/*
1672 * Log outgoing zone transfer messages in a format like
1673 * <client>: transfer of <zone>: <message>
1674 */
1675
1676static void
1677xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1678	    dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1679     ISC_FORMAT_PRINTF(5, 0);
1680
1681static void
1682xfrout_logv(ns_client_t *client, dns_name_t *zonename,
1683	    dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
1684{
1685	char msgbuf[2048];
1686	char namebuf[DNS_NAME_FORMATSIZE];
1687	char classbuf[DNS_RDATACLASS_FORMATSIZE];
1688
1689	dns_name_format(zonename, namebuf, sizeof(namebuf));
1690	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1691	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1692	ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1693		      NS_LOGMODULE_XFER_OUT, level,
1694		      "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
1695}
1696
1697/*
1698 * Logging function for use when a xfrout_ctx_t has not yet been created.
1699 */
1700static void
1701xfrout_log1(ns_client_t *client, dns_name_t *zonename,
1702	    dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
1703	va_list ap;
1704	va_start(ap, fmt);
1705	xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1706	va_end(ap);
1707}
1708
1709/*
1710 * Logging function for use when there is a xfrout_ctx_t.
1711 */
1712static void
1713xfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) {
1714	va_list ap;
1715	va_start(ap, fmt);
1716	xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
1717	va_end(ap);
1718}
1719