⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xfrout.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 4 页
字号:
static voidxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);static voidxfrout_maybe_destroy(xfrout_ctx_t *xfr);static voidxfrout_ctx_destroy(xfrout_ctx_t **xfrp);static voidxfrout_client_shutdown(void *arg, isc_result_t result);static voidxfrout_log1(ns_client_t *client, dns_name_t *zonename,	    dns_rdataclass_t rdclass, int level,	    const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);static voidxfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...)	   ISC_FORMAT_PRINTF(3, 4);/**************************************************************************/voidns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {	isc_result_t result;	dns_name_t *question_name;	dns_rdataset_t *question_rdataset;	dns_zone_t *zone = NULL;	dns_db_t *db = NULL;	dns_dbversion_t *ver = NULL;	dns_rdataclass_t question_class;	rrstream_t *soa_stream = NULL;	rrstream_t *data_stream = NULL;	rrstream_t *stream = NULL;	dns_difftuple_t *current_soa_tuple = NULL;	dns_name_t *soa_name;	dns_rdataset_t *soa_rdataset;	dns_rdata_t soa_rdata = DNS_RDATA_INIT;	isc_boolean_t have_soa = ISC_FALSE;	const char *mnemonic = NULL;	isc_mem_t *mctx = client->mctx;	dns_message_t *request = client->message;	xfrout_ctx_t *xfr = NULL;	isc_quota_t *quota = NULL;	dns_transfer_format_t format = client->view->transfer_format;	isc_netaddr_t na;	dns_peer_t *peer = NULL;	isc_buffer_t *tsigbuf = NULL;	char *journalfile;	char msg[DNS_RDATACLASS_FORMATSIZE + DNS_NAME_FORMATSIZE		 + sizeof("zone transfer '/'")];	isc_boolean_t is_poll = ISC_FALSE;	switch (reqtype) {	case dns_rdatatype_axfr:		mnemonic = "AXFR";		break;	case dns_rdatatype_ixfr:		mnemonic = "IXFR";		break;	default:		INSIST(0);		break;	}	ns_client_log(client,		      DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,		      ISC_LOG_DEBUG(6), "%s request", mnemonic);	/*	 * Apply quota.	 */	result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);	if (result != ISC_R_SUCCESS) {		isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,			      "%s request denied: %s", mnemonic,			      isc_result_totext(result));		goto failure;	}	/*	 * Interpret the question section.	 */	result = dns_message_firstname(request, DNS_SECTION_QUESTION);	INSIST(result == ISC_R_SUCCESS);	/*	 * The question section must contain exactly one question, and	 * it must be for AXFR/IXFR as appropriate.	 */	question_name = NULL;	dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);	question_rdataset = ISC_LIST_HEAD(question_name->list);	question_class = question_rdataset->rdclass;	INSIST(question_rdataset->type == reqtype);	if (ISC_LIST_NEXT(question_rdataset, link) != NULL)		FAILC(DNS_R_FORMERR, "multiple questions");	result = dns_message_nextname(request, DNS_SECTION_QUESTION);	if (result != ISC_R_NOMORE)		FAILC(DNS_R_FORMERR, "multiple questions");	result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,			     &zone);	if (result != ISC_R_SUCCESS)		FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",		      question_name, question_class);	switch(dns_zone_gettype(zone)) {	case dns_zone_master:	case dns_zone_slave:		break;	/* Master and slave zones are OK for transfer. */	default:		FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",		      question_name, question_class);	}	CHECK(dns_zone_getdb(zone, &db));	dns_db_currentversion(db, &ver);	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),		    "%s question section OK", mnemonic);	/*	 * Check the authority section.  Look for a SOA record with	 * the same name and class as the question.	 */	for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);	     result == ISC_R_SUCCESS;	     result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))	{		soa_name = NULL;		dns_message_currentname(request, DNS_SECTION_AUTHORITY,					&soa_name);		/*		 * Ignore data whose owner name is not the zone apex.		 */		if (! dns_name_equal(soa_name, question_name))			continue;		for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);		     soa_rdataset != NULL;		     soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))		{			/*			 * Ignore non-SOA data.			 */			if (soa_rdataset->type != dns_rdatatype_soa)				continue;			if (soa_rdataset->rdclass != question_class)				continue;			CHECK(dns_rdataset_first(soa_rdataset));			dns_rdataset_current(soa_rdataset, &soa_rdata);			result = dns_rdataset_next(soa_rdataset);			if (result == ISC_R_SUCCESS)				FAILC(DNS_R_FORMERR,				      "IXFR authority section "				      "has multiple SOAs");			have_soa = ISC_TRUE;			goto got_soa;		}	} got_soa:	if (result != ISC_R_NOMORE)		CHECK(result);	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),		    "%s authority section OK", mnemonic);	/*	 * Decide whether to allow this transfer.	 */	ns_client_aclmsg("zone transfer", question_name,			 client->view->rdclass, msg, sizeof(msg));	CHECK(ns_client_checkacl(client, msg,				 dns_zone_getxfracl(zone), ISC_TRUE,				 ISC_LOG_ERROR));	/*	 * AXFR over UDP is not possible.	 */	if (reqtype == dns_rdatatype_axfr &&	    (client->attributes & NS_CLIENTATTR_TCP) == 0)		FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");	/*	 * Look up the requesting server in the peer table.	 */	isc_netaddr_fromsockaddr(&na, &client->peeraddr);	(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);	/*	 * Decide on the transfer format (one-answer or many-answers).	 */	if (peer != NULL)		(void)dns_peer_gettransferformat(peer, &format);	/*	 * Get a dynamically allocated copy of the current SOA.	 */	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,				    &current_soa_tuple));	if (reqtype == dns_rdatatype_ixfr) {		isc_uint32_t begin_serial, current_serial;		isc_boolean_t provide_ixfr;		/*		 * Outgoing IXFR may have been disabled for this peer		 * or globally.		 */		provide_ixfr = client->view->provideixfr;		if (peer != NULL)			(void) dns_peer_getprovideixfr(peer, &provide_ixfr);		if (provide_ixfr == ISC_FALSE)			goto axfr_fallback;		if (! have_soa)			FAILC(DNS_R_FORMERR,			      "IXFR request missing SOA");		begin_serial = dns_soa_getserial(&soa_rdata);		current_serial = dns_soa_getserial(&current_soa_tuple->rdata);		/*		 * RFC1995 says "If an IXFR query with the same or		 * newer version number than that of the server		 * is received, it is replied to with a single SOA		 * record of the server's current version, just as		 * in AXFR".  The claim about AXFR is incorrect,		 * but other than that, we do as the RFC says.		 *		 * Sending a single SOA record is also how we refuse		 * IXFR over UDP (currently, we always do).		 */		if (DNS_SERIAL_GE(begin_serial, current_serial) ||		    (client->attributes & NS_CLIENTATTR_TCP) == 0)		{			CHECK(soa_rrstream_create(mctx, db, ver, &stream));			is_poll = ISC_TRUE;			goto have_stream;		}		journalfile = dns_zone_getjournal(zone);		if (journalfile != NULL)			result = ixfr_rrstream_create(mctx,						      journalfile,						      begin_serial,						      current_serial,						      &data_stream);		else			result = ISC_R_NOTFOUND;		if (result == ISC_R_NOTFOUND ||		    result == ISC_R_RANGE) {			xfrout_log1(client, question_name, question_class,				    ISC_LOG_DEBUG(4),				    "IXFR version not in journal, "				    "falling back to AXFR");			mnemonic = "AXFR-style IXFR";			goto axfr_fallback;		}		CHECK(result);	} else {	axfr_fallback:		CHECK(axfr_rrstream_create(mctx, db, ver,					   &data_stream));	}	/*	 * Bracket the the data stream with SOAs.	 */	CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));	CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,				       &stream));	soa_stream = NULL;	data_stream = NULL; have_stream:	CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));	/*	 * Create the xfrout context object.  This transfers the ownership	 * of "stream", "db", "ver", and "quota" to the xfrout context object.	 */	CHECK(xfrout_ctx_create(mctx, client, request->id, question_name,				reqtype, question_class, db, ver, quota,				stream, dns_message_gettsigkey(request),				tsigbuf,				dns_zone_getmaxxfrout(zone),				dns_zone_getidleout(zone),				(format == dns_many_answers) ?					ISC_TRUE : ISC_FALSE,				&xfr));	stream = NULL;	db = NULL;	ver = NULL;	quota = NULL;	CHECK(xfr->stream->methods->first(xfr->stream));	if (is_poll)		xfrout_log1(client, question_name, question_class,			    ISC_LOG_DEBUG(1), "IXFR poll up to date");	else		xfrout_log1(client, question_name, question_class,			    ISC_LOG_INFO, "%s started", mnemonic);	/*	 * Hand the context over to sendstream().  Set xfr to NULL;	 * sendstream() is responsible for either passing the	 * context on to a later event handler or destroying it.	 */	sendstream(xfr);	xfr = NULL;	result = ISC_R_SUCCESS; failure:	if (quota != NULL)		isc_quota_detach(&quota);	if (current_soa_tuple != NULL)		dns_difftuple_free(&current_soa_tuple);	if (stream != NULL)		stream->methods->destroy(&stream);	if (soa_stream != NULL)		soa_stream->methods->destroy(&soa_stream);	if (data_stream != NULL)		data_stream->methods->destroy(&data_stream);	if (ver != NULL)		dns_db_closeversion(db, &ver, ISC_FALSE);	if (db != NULL)		dns_db_detach(&db);	if (zone != NULL)		dns_zone_detach(&zone);	/* XXX kludge */	if (xfr != NULL) {		xfrout_fail(xfr, result, "setting up zone transfer");	} else if (result != ISC_R_SUCCESS) {		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,			      NS_LOGMODULE_XFER_OUT,			      ISC_LOG_DEBUG(3), "zone transfer setup failed");		ns_client_error(client, result);	}}static isc_result_txfrout_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_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,		  rrstream_t *stream, dns_tsigkey_t *tsigkey,		  isc_buffer_t *lasttsig, unsigned int maxtime,		  unsigned int idletime, isc_boolean_t many_answers,		  xfrout_ctx_t **xfrp){	xfrout_ctx_t *xfr;	isc_result_t result;	unsigned int len;	void *mem;	INSIST(xfrp != NULL && *xfrp == NULL);	xfr = isc_mem_get(mctx, sizeof(*xfr));	if (xfr == NULL)		return (ISC_R_NOMEMORY);	xfr->mctx = mctx;	xfr->client = NULL;	ns_client_attach(client, &xfr->client);	xfr->id = id;	xfr->qname = qname;	xfr->qtype = qtype;	xfr->qclass = qclass;	xfr->db = db;	xfr->ver = ver;	xfr->quota = quota;	xfr->stream = stream;	xfr->end_of_stream = ISC_FALSE;	xfr->tsigkey = tsigkey;	xfr->lasttsig = lasttsig;	xfr->txmem = NULL;	xfr->txmemlen = 0;	xfr->nmsg = 0;	xfr->many_answers = many_answers,	xfr->sends = 0;	xfr->shuttingdown = ISC_FALSE;	/*	 * Allocate a temporary buffer for the uncompressed response	 * message data.  The size should be no more than 65535 bytes	 * so that the compressed data will fit in a TCP message,	 * and no less than 65535 bytes so that an almost maximum-sized	 * RR will fit.  Note that although 65535-byte RRs are allowed	 * in principle, they cannot be zone-transferred (at least not	 * if uncompressible), because the message and RR headers would	 * push the size of the TCP message over the 65536 byte limit.	 */	len = 65535;	mem = isc_mem_get(mctx, len);	if (mem == NULL) {		result = ISC_R_NOMEMORY;		goto failure;	}	isc_buffer_init(&xfr->buf, mem, len);	/*	 * Allocate another temporary buffer for the compressed	 * response message and its TCP length prefix.	 */	len = 2 + 65535;	mem = isc_mem_get(mctx, len);	if (mem == NULL) {		result = ISC_R_NOMEMORY;		goto failure;	}	isc_buffer_init(&xfr->txlenbuf, mem, 2);	isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);	xfr->txmem = mem;	xfr->txmemlen = len;	CHECK(dns_timer_setidle(xfr->client->timer,				maxtime, idletime, ISC_FALSE));	/*	 * Register a shutdown callback with the client, so that we	 * can stop the transfer immediately when the client task	 * gets a shutdown event.	 */	xfr->client->shutdown = xfrout_client_shutdown;	xfr->client->shutdown_arg = xfr;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -