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