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

📄 xfrout.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * These MUST be after the last "goto failure;" / CHECK to	 * prevent a double free by the caller.	 */	xfr->quota = quota;	xfr->stream = stream;	*xfrp = xfr;	return (ISC_R_SUCCESS);failure:	xfrout_ctx_destroy(&xfr);	return (result);}/* * Arrange to send as much as we can of "stream" without blocking. * * Requires: *	The stream iterator is initialized and points at an RR, *      or possiby at the end of the stream (that is, the *      _first method of the iterator has been called). */static voidsendstream(xfrout_ctx_t *xfr) {	dns_message_t *tcpmsg = NULL;	dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */	isc_result_t result;	isc_region_t used;	isc_region_t region;	dns_rdataset_t *qrdataset;	dns_name_t *msgname = NULL;	dns_rdata_t *msgrdata = NULL;	dns_rdatalist_t *msgrdl = NULL;	dns_rdataset_t *msgrds = NULL;	dns_compress_t cctx;	isc_boolean_t cleanup_cctx = ISC_FALSE;	int n_rrs;	isc_buffer_clear(&xfr->buf);	isc_buffer_clear(&xfr->txlenbuf);	isc_buffer_clear(&xfr->txbuf);	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {		/*		 * In the UDP case, we put the response data directly into		 * the client message.		 */		msg = xfr->client->message;		CHECK(dns_message_reply(msg, ISC_TRUE));	} else {		/*		 * TCP. Build a response dns_message_t, temporarily storing		 * the raw, uncompressed owner names and RR data contiguously		 * in xfr->buf.  We know that if the uncompressed data fits		 * in xfr->buf, the compressed data will surely fit in a TCP		 * message.		 */		CHECK(dns_message_create(xfr->mctx,					 DNS_MESSAGE_INTENTRENDER, &tcpmsg));		msg = tcpmsg;		msg->id = xfr->id;		msg->rcode = dns_rcode_noerror;		msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;		if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)			msg->flags |= DNS_MESSAGEFLAG_RA;		CHECK(dns_message_settsigkey(msg, xfr->tsigkey));		CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));		if (xfr->lasttsig != NULL)			isc_buffer_free(&xfr->lasttsig);		/*		 * Include a question section in the first message only.		 * BIND 8.2.1 will not recognize an IXFR if it does not		 * have a question section.		 */		if (xfr->nmsg == 0) {			dns_name_t *qname = NULL;			isc_region_t r;			/*			 * Reserve space for the 12-byte message header			 * and 4 bytes of question.			 */			isc_buffer_add(&xfr->buf, 12 + 4);			qrdataset = NULL;			result = dns_message_gettemprdataset(msg, &qrdataset);			if (result != ISC_R_SUCCESS)				goto failure;			dns_rdataset_init(qrdataset);			dns_rdataset_makequestion(qrdataset,					xfr->client->message->rdclass,					xfr->qtype);			result = dns_message_gettempname(msg, &qname);			if (result != ISC_R_SUCCESS)				goto failure;			dns_name_init(qname, NULL);			isc_buffer_availableregion(&xfr->buf, &r);			INSIST(r.length >= xfr->qname->length);			r.length = xfr->qname->length;			isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,					  xfr->qname->length);			dns_name_fromregion(qname, &r);			ISC_LIST_INIT(qname->list);			ISC_LIST_APPEND(qname->list, qrdataset, link);			dns_message_addname(msg, qname, DNS_SECTION_QUESTION);		}		else			msg->tcp_continuation = 1;	}	/*	 * Try to fit in as many RRs as possible, unless "one-answer"	 * format has been requested.	 */	for (n_rrs = 0; ; n_rrs++) {		dns_name_t *name = NULL;		isc_uint32_t ttl;		dns_rdata_t *rdata = NULL;		unsigned int size;		isc_region_t r;		msgname = NULL;		msgrdata = NULL;		msgrdl = NULL;		msgrds = NULL;		xfr->stream->methods->current(xfr->stream,					      &name, &ttl, &rdata);		size = name->length + 10 + rdata->length;		isc_buffer_availableregion(&xfr->buf, &r);		if (size >= r.length) {			/*			 * RR would not fit.  If there are other RRs in the			 * buffer, send them now and leave this RR to the			 * next message.  If this RR overflows the buffer			 * all by itself, fail.			 *			 * In theory some RRs might fit in a TCP message			 * when compressed even if they do not fit when			 * uncompressed, but surely we don't want			 * to send such monstrosities to an unsuspecting			 * slave.			 */			if (n_rrs == 0) {				xfrout_log(xfr, ISC_LOG_WARNING,					   "RR too large for zone transfer "					   "(%d bytes)", size);				/* XXX DNS_R_RRTOOLARGE? */				result = ISC_R_NOSPACE;				goto failure;			}			break;		}		if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))			log_rr(name, rdata, ttl); /* XXX */		result = dns_message_gettempname(msg, &msgname);		if (result != ISC_R_SUCCESS)			goto failure;		dns_name_init(msgname, NULL);		isc_buffer_availableregion(&xfr->buf, &r);		INSIST(r.length >= name->length);		r.length = name->length;		isc_buffer_putmem(&xfr->buf, name->ndata, name->length);		dns_name_fromregion(msgname, &r);		/* Reserve space for RR header. */		isc_buffer_add(&xfr->buf, 10);		result = dns_message_gettemprdata(msg, &msgrdata);		if (result != ISC_R_SUCCESS)			goto failure;		isc_buffer_availableregion(&xfr->buf, &r);		r.length = rdata->length;		isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);		dns_rdata_init(msgrdata);		dns_rdata_fromregion(msgrdata,				     rdata->rdclass, rdata->type, &r);		result = dns_message_gettemprdatalist(msg, &msgrdl);		if (result != ISC_R_SUCCESS)			goto failure;		msgrdl->type = rdata->type;		msgrdl->rdclass = rdata->rdclass;		msgrdl->ttl = ttl;		ISC_LINK_INIT(msgrdl, link);		ISC_LIST_INIT(msgrdl->rdata);		ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);		result = dns_message_gettemprdataset(msg, &msgrds);		if (result != ISC_R_SUCCESS)			goto failure;		dns_rdataset_init(msgrds);		result = dns_rdatalist_tordataset(msgrdl, msgrds);		INSIST(result == ISC_R_SUCCESS);		ISC_LIST_APPEND(msgname->list, msgrds, link);		dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);		msgname = NULL;		result = xfr->stream->methods->next(xfr->stream);		if (result == ISC_R_NOMORE) {			xfr->end_of_stream = ISC_TRUE;			break;		}		CHECK(result);		if (! xfr->many_answers)			break;	}	if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {		CHECK(dns_compress_init(&cctx, -1, xfr->mctx));		cleanup_cctx = ISC_TRUE;		CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));		CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));		CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));		CHECK(dns_message_renderend(msg));		dns_compress_invalidate(&cctx);		cleanup_cctx = ISC_FALSE;		isc_buffer_usedregion(&xfr->txbuf, &used);		isc_buffer_putuint16(&xfr->txlenbuf,				     (isc_uint16_t)used.length);		region.base = xfr->txlenbuf.base;		region.length = 2 + used.length;		xfrout_log(xfr, ISC_LOG_DEBUG(8),			   "sending TCP message of %d bytes",			   used.length);		CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */				      &region, xfr->client->task,				      xfrout_senddone,				      xfr));		xfr->sends++;	} else {		xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");		ns_client_send(xfr->client);		xfr->stream->methods->pause(xfr->stream);		xfrout_ctx_destroy(&xfr);		return;	}	/* Advance lasttsig to be the last TSIG generated */	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));	xfr->nmsg++; failure:	if (msgname != NULL) {		if (msgrds != NULL) {			if (dns_rdataset_isassociated(msgrds))				dns_rdataset_disassociate(msgrds);			dns_message_puttemprdataset(msg, &msgrds);		}		if (msgrdl != NULL) {			ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);			dns_message_puttemprdatalist(msg, &msgrdl);		}		if (msgrdata != NULL)			dns_message_puttemprdata(msg, &msgrdata);		dns_message_puttempname(msg, &msgname);	}	if (tcpmsg != NULL)		dns_message_destroy(&tcpmsg);	if (cleanup_cctx)		dns_compress_invalidate(&cctx);	/*	 * Make sure to release any locks held by database	 * iterators before returning from the event handler.	 */	xfr->stream->methods->pause(xfr->stream);		if (result == ISC_R_SUCCESS)		return;	xfrout_fail(xfr, result, "sending zone data");}static voidxfrout_ctx_destroy(xfrout_ctx_t **xfrp) {	xfrout_ctx_t *xfr = *xfrp;	INSIST(xfr->sends == 0);	xfr->client->shutdown = NULL;	xfr->client->shutdown_arg = NULL;	if (xfr->stream != NULL)		xfr->stream->methods->destroy(&xfr->stream);	if (xfr->buf.base != NULL)		isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);	if (xfr->txmem != NULL)		isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);	if (xfr->lasttsig != NULL)		isc_buffer_free(&xfr->lasttsig);	if (xfr->quota != NULL)		isc_quota_detach(&xfr->quota);	if (xfr->ver != NULL)		dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);	if (xfr->db != NULL)		dns_db_detach(&xfr->db);	ns_client_detach(&xfr->client);	isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));	*xfrp = NULL;}static voidxfrout_senddone(isc_task_t *task, isc_event_t *event) {	isc_socketevent_t *sev = (isc_socketevent_t *)event;	xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;	isc_result_t evresult = sev->result;	UNUSED(task);	INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);	isc_event_free(&event);	xfr->sends--;	INSIST(xfr->sends == 0);	(void)isc_timer_touch(xfr->client->timer);	if (xfr->shuttingdown == ISC_TRUE) {		xfrout_maybe_destroy(xfr);	} else if (evresult != ISC_R_SUCCESS) {		xfrout_fail(xfr, evresult, "send");	} else if (xfr->end_of_stream == ISC_FALSE) {		sendstream(xfr);	} else {		/* End of zone transfer stream. */		xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);		ns_client_next(xfr->client, ISC_R_SUCCESS);		xfrout_ctx_destroy(&xfr);	}}static voidxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {	xfr->shuttingdown = ISC_TRUE;	xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",		   msg, isc_result_totext(result));	xfrout_maybe_destroy(xfr);}static voidxfrout_maybe_destroy(xfrout_ctx_t *xfr) {	INSIST(xfr->shuttingdown == ISC_TRUE);	if (xfr->sends > 0) {		/*		 * If we are currently sending, cancel it and wait for		 * cancel event before destroying the context.		 */		isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,				  ISC_SOCKCANCEL_SEND);	} else {		ns_client_next(xfr->client, ISC_R_CANCELED);		xfrout_ctx_destroy(&xfr);	}}static voidxfrout_client_shutdown(void *arg, isc_result_t result) {	xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;	xfrout_fail(xfr, result, "aborted");}/* * Log outgoing zone transfer messages in a format like * <client>: transfer of <zone>: <message> */static voidxfrout_logv(ns_client_t *client, dns_name_t *zonename,	    dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)     ISC_FORMAT_PRINTF(5, 0);static voidxfrout_logv(ns_client_t *client, dns_name_t *zonename,	    dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap){	char msgbuf[2048];	char namebuf[DNS_NAME_FORMATSIZE];	char classbuf[DNS_RDATACLASS_FORMATSIZE];	dns_name_format(zonename, namebuf, sizeof(namebuf));	dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);	ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,		      NS_LOGMODULE_XFER_OUT, level,		      "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);}/* * Logging function for use when a xfrout_ctx_t has not yet been created. */static voidxfrout_log1(ns_client_t *client, dns_name_t *zonename,	    dns_rdataclass_t rdclass, int level, const char *fmt, ...) {	va_list ap;	va_start(ap, fmt);	xfrout_logv(client, zonename, rdclass, level, fmt, ap);	va_end(ap);}/* * Logging function for use when there is a xfrout_ctx_t. */static voidxfrout_log(xfrout_ctx_t *xfr, unsigned int level, const char *fmt, ...) {	va_list ap;	va_start(ap, fmt);	xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);	va_end(ap);}

⌨️ 快捷键说明

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