PageRenderTime 101ms CodeModel.GetById 17ms app.highlight 72ms RepoModel.GetById 1ms app.codeStats 1ms

/contrib/bind9/bin/named/xfrout.c

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