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

📄 xfrout.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	isc_buffer_t *tsigbuf = NULL;	char *journalfile;	char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];	char keyname[DNS_NAME_FORMATSIZE];	isc_boolean_t is_poll = ISC_FALSE;#ifdef DLZ	isc_boolean_t is_dlz = ISC_FALSE;#endif	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)#ifdef DLZ	{		/*		 * Normal zone table does not have a match.  Try the DLZ database		 */	    	if (client->view->dlzdatabase != NULL) {			result = dns_dlzallowzonexfr(client->view,						     question_name, &client->peeraddr,						     &db);			if (result == ISC_R_NOPERM) {				char _buf1[DNS_NAME_FORMATSIZE];				char _buf2[DNS_RDATACLASS_FORMATSIZE];				result = DNS_R_REFUSED;				dns_name_format(question_name, _buf1,						sizeof(_buf1));				dns_rdataclass_format(question_class,						      _buf2, sizeof(_buf2));				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,					      NS_LOGMODULE_XFER_OUT,					      ISC_LOG_ERROR,					      "zone transfer '%s/%s' denied",					      _buf1, _buf2);				goto failure;			}			if (result != ISC_R_SUCCESS)#endif			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",				  question_name, question_class);#ifdef DLZ			is_dlz = ISC_TRUE;			/*			 * DLZ only support full zone transfer, not incremental			 */			if (reqtype != dns_rdatatype_axfr) {				mnemonic = "AXFR-style IXFR";				reqtype = dns_rdatatype_axfr;			}		} else {			/*		 	 * not DLZ and not in normal zone table, we are			 * not authoritative			 */			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",			      question_name, question_class);		}	} else {		/* zone table has a match */#endif		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);#ifdef DLZ	}#endif	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.	 */#ifdef DLZ	/*	 * if not a DLZ zone decide whether to allow this transfer.	 */	if (!is_dlz) {#endif		ns_client_aclmsg("zone transfer", question_name, reqtype,				 client->view->rdclass, msg, sizeof(msg));		CHECK(ns_client_checkacl(client, msg,					 dns_zone_getxfracl(zone), ISC_TRUE,					 ISC_LOG_ERROR));#ifdef DLZ	}#endif	/*	 * 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.	 */#ifdef DLZ	if (is_dlz)		dns_db_currentversion(db, &ver);#endif	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.	 */#ifdef DLZ	if (is_dlz) 		CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, 					reqtype, question_class, db, ver, quota, 					stream, dns_message_gettsigkey(request), 					tsigbuf, 					3600, 					3600, 					(format == dns_many_answers) ?  					ISC_TRUE : ISC_FALSE, 					&xfr)); 	else#endif 		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));	xfr->mnemonic = mnemonic;	stream = NULL;	quota = NULL;	CHECK(xfr->stream->methods->first(xfr->stream));	if (xfr->tsigkey != NULL) {		dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));	} else		keyname[0] = '\0';	if (is_poll)		xfrout_log1(client, question_name, question_class,			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);	else		xfrout_log1(client, question_name, question_class,			    ISC_LOG_INFO, "%s started%s%s", mnemonic,			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);	/*	 * 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 = NULL;	xfr->ver = NULL;	dns_db_attach(db, &xfr->db);	dns_db_attachversion(db, ver, &xfr->ver);	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;	xfr->mnemonic = NULL;	xfr->buf.base = NULL;	xfr->buf.length = 0;	xfr->txmem = NULL;	xfr->txmemlen = 0;	xfr->stream = NULL;	xfr->quota = NULL;	/*	 * 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.	 */

⌨️ 快捷键说明

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