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