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

📄 xfrin.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003  Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: xfrin.c,v 1.124.2.4.2.7 2004/03/08 09:04:33 marka Exp $ */#include <config.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/random.h>#include <isc/string.h>		/* Required for HP/UX (and others?) */#include <isc/task.h>#include <isc/timer.h>#include <isc/util.h>#include <dns/db.h>#include <dns/diff.h>#include <dns/events.h>#include <dns/journal.h>#include <dns/log.h>#include <dns/message.h>#include <dns/rdataclass.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/result.h>#include <dns/soa.h>#include <dns/tcpmsg.h>#include <dns/timer.h>#include <dns/tsig.h>#include <dns/view.h>#include <dns/xfrin.h>#include <dns/zone.h>#include <dst/dst.h>/* * Incoming AXFR and IXFR. *//* * It would be non-sensical (or at least obtuse) to use FAIL() with an * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */#define FAIL(code) \	do { result = (code);					\		if (result != ISC_R_SUCCESS) goto failure;	\	} while (0)#define CHECK(op) \	do { result = (op);					\		if (result != ISC_R_SUCCESS) goto failure;	\	} while (0)/* * The states of the *XFR state machine.  We handle both IXFR and AXFR * with a single integrated state machine because they cannot be distinguished * immediately - an AXFR response to an IXFR request can only be detected * when the first two (2) response RRs have already been received. */typedef enum {	XFRST_INITIALSOA,	XFRST_FIRSTDATA,	XFRST_IXFR_DELSOA,	XFRST_IXFR_DEL,	XFRST_IXFR_ADDSOA,	XFRST_IXFR_ADD,	XFRST_AXFR,	XFRST_END} xfrin_state_t;/* * Incoming zone transfer context. */struct dns_xfrin_ctx {	unsigned int		magic;	isc_mem_t		*mctx;	dns_zone_t		*zone;	int			refcount;	isc_task_t 		*task;	isc_timer_t		*timer;	isc_socketmgr_t 	*socketmgr;	int			connects; 	/* Connect in progress */	int			sends;		/* Send in progress */	int			recvs;	  	/* Receive in progress */	isc_boolean_t		shuttingdown;	dns_name_t 		name; 		/* Name of zone to transfer */	dns_rdataclass_t 	rdclass;	isc_boolean_t		checkid;	dns_messageid_t		id;	/*	 * Requested transfer type (dns_rdatatype_axfr or	 * dns_rdatatype_ixfr).  The actual transfer type	 * may differ due to IXFR->AXFR fallback.	 */	dns_rdatatype_t 	reqtype;	isc_sockaddr_t 		masteraddr;	isc_sockaddr_t		sourceaddr;	isc_socket_t 		*socket;	/* Buffer for IXFR/AXFR request message */	isc_buffer_t 		qbuffer;	unsigned char 		qbuffer_data[512];	/* Incoming reply TCP message */	dns_tcpmsg_t		tcpmsg;	isc_boolean_t		tcpmsg_valid;	dns_db_t 		*db;	dns_dbversion_t 	*ver;	dns_diff_t 		diff;		/* Pending database changes */	int 			difflen;	/* Number of pending tuples */	xfrin_state_t 		state;	isc_uint32_t 		end_serial;	isc_boolean_t 		is_ixfr;	unsigned int		nmsg;		/* Number of messages recvd */	dns_tsigkey_t		*tsigkey;	/* Key used to create TSIG */	isc_buffer_t		*lasttsig;	/* The last TSIG */	dst_context_t		*tsigctx;	/* TSIG verification context */	unsigned int		sincetsig;	/* recvd since the last TSIG */	dns_xfrindone_t		done;	/*	 * AXFR- and IXFR-specific data.  Only one is used at a time	 * according to the is_ixfr flag, so this could be a union,	 * but keeping them separate makes it a bit simpler to clean	 * things up when destroying the context.	 */	struct {		dns_addrdatasetfunc_t add_func;		dns_dbload_t	      *add_private;	} axfr;	struct {		isc_uint32_t 	request_serial;		isc_uint32_t 	current_serial;		dns_journal_t	*journal;	} ixfr;};#define XFRIN_MAGIC		  ISC_MAGIC('X', 'f', 'r', 'I')#define VALID_XFRIN(x)		  ISC_MAGIC_VALID(x, XFRIN_MAGIC)/**************************************************************************//* * Forward declarations. */static isc_result_txfrin_create(isc_mem_t *mctx,	     dns_zone_t *zone,	     dns_db_t *db,	     isc_task_t *task,	     isc_timermgr_t *timermgr,	     isc_socketmgr_t *socketmgr,	     dns_name_t *zonename,	     dns_rdataclass_t rdclass,	     dns_rdatatype_t reqtype,	     isc_sockaddr_t *masteraddr,	     isc_sockaddr_t *sourceaddr,	     dns_tsigkey_t *tsigkey,	     dns_xfrin_ctx_t **xfrp);static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,				   dns_name_t *name, dns_ttl_t ttl,				   dns_rdata_t *rdata);static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,				 dns_name_t *name, dns_ttl_t ttl,				 dns_rdata_t *rdata);static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,			   isc_uint32_t ttl, dns_rdata_t *rdata);static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);static void xfrin_send_done(isc_task_t *task, isc_event_t *event);static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);static void xfrin_timeout(isc_task_t *task, isc_event_t *event);static void maybe_free(dns_xfrin_ctx_t *xfr);static voidxfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);static isc_result_trender(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);static voidxfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,	   isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)     ISC_FORMAT_PRINTF(5, 0);static voidxfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,	   isc_sockaddr_t *masteraddr, const char *fmt, ...)     ISC_FORMAT_PRINTF(5, 6);static voidxfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)     ISC_FORMAT_PRINTF(3, 4);/**************************************************************************//* * AXFR handling */static isc_result_taxfr_init(dns_xfrin_ctx_t *xfr) {	isc_result_t result; 	xfr->is_ixfr = ISC_FALSE;	if (xfr->db != NULL)		dns_db_detach(&xfr->db);	CHECK(axfr_makedb(xfr, &xfr->db));	CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,			       &xfr->axfr.add_private));	result = ISC_R_SUCCESS; failure:	return (result);}static isc_result_taxfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {	return (dns_db_create(xfr->mctx, /* XXX */			      "rbt", /* XXX guess */			      &xfr->name,			      dns_dbtype_zone,			      xfr->rdclass,			      0, NULL, /* XXX guess */			      dbp));}static isc_result_taxfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,	     dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata){	isc_result_t result;	dns_difftuple_t *tuple = NULL;	CHECK(dns_zone_checknames(xfr->zone, name, rdata));	CHECK(dns_difftuple_create(xfr->diff.mctx, op,				   name, ttl, rdata, &tuple));	dns_diff_append(&xfr->diff, &tuple);	if (++xfr->difflen > 100)		CHECK(axfr_apply(xfr));	result = ISC_R_SUCCESS; failure:	return (result);}/* * Store a set of AXFR RRs in the database. */static isc_result_taxfr_apply(dns_xfrin_ctx_t *xfr) {	isc_result_t result;	CHECK(dns_diff_load(&xfr->diff,			    xfr->axfr.add_func, xfr->axfr.add_private));	xfr->difflen = 0;	dns_diff_clear(&xfr->diff);	result = ISC_R_SUCCESS; failure:	return (result);}static isc_result_taxfr_commit(dns_xfrin_ctx_t *xfr) {	isc_result_t result;	CHECK(axfr_apply(xfr));	CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));	CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));	result = ISC_R_SUCCESS; failure:	return (result);}/**************************************************************************//* * IXFR handling */static isc_result_tixfr_init(dns_xfrin_ctx_t *xfr) {	isc_result_t result;	char *journalfile;	if (xfr->reqtype != dns_rdatatype_ixfr) {		xfrin_log(xfr, ISC_LOG_ERROR,			  "got incremental response to AXFR request");		return (DNS_R_FORMERR);	}	xfr->is_ixfr = ISC_TRUE;	INSIST(xfr->db != NULL);	xfr->difflen = 0;	journalfile = dns_zone_getjournal(xfr->zone);	if (journalfile != NULL)		CHECK(dns_journal_open(xfr->mctx, journalfile,				       ISC_TRUE, &xfr->ixfr.journal));	result = ISC_R_SUCCESS; failure:	return (result);}static isc_result_tixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,	     dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata){	isc_result_t result;	dns_difftuple_t *tuple = NULL;	if (op == DNS_DIFFOP_ADD)		CHECK(dns_zone_checknames(xfr->zone, name, rdata));	CHECK(dns_difftuple_create(xfr->diff.mctx, op,				   name, ttl, rdata, &tuple));	dns_diff_append(&xfr->diff, &tuple);	if (++xfr->difflen > 100)		CHECK(ixfr_apply(xfr));	result = ISC_R_SUCCESS; failure:	return (result);}/* * Apply a set of IXFR changes to the database. */static isc_result_tixfr_apply(dns_xfrin_ctx_t *xfr) {	isc_result_t result;	if (xfr->ver == NULL) {		CHECK(dns_db_newversion(xfr->db, &xfr->ver));		if (xfr->ixfr.journal != NULL)			CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));	}	CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));	if (xfr->ixfr.journal != NULL) {		result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);		if (result != ISC_R_SUCCESS)			goto failure;	}	dns_diff_clear(&xfr->diff);	xfr->difflen = 0;	result = ISC_R_SUCCESS; failure:	return (result);}static isc_result_tixfr_commit(dns_xfrin_ctx_t *xfr) {	isc_result_t result;	CHECK(ixfr_apply(xfr));	if (xfr->ver != NULL) {		/* XXX enter ready-to-commit state here */		if (xfr->ixfr.journal != NULL)			CHECK(dns_journal_commit(xfr->ixfr.journal));		dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);		dns_zone_markdirty(xfr->zone);	}	result = ISC_R_SUCCESS; failure:	return (result);}/**************************************************************************//* * Common AXFR/IXFR protocol code *//* * Handle a single incoming resource record according to the current * state. */static isc_result_txfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,       dns_rdata_t *rdata){	isc_result_t result; redo:	switch (xfr->state) {	case XFRST_INITIALSOA:		if (rdata->type != dns_rdatatype_soa) {			xfrin_log(xfr, ISC_LOG_ERROR,				  "first RR in zone transfer must be SOA");			FAIL(DNS_R_FORMERR);		}		/*		 * Remember the serial number in the intial SOA.		 * We need it to recognize the end of an IXFR.		 */		xfr->end_serial = dns_soa_getserial(rdata);		if (xfr->reqtype == dns_rdatatype_ixfr &&		    ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)		    && !dns_zone_isforced(xfr->zone))		{			/*			 * This must be the single SOA record that is			 * sent when the current version on the master			 * is not newer than the version in the request.			 */			xfrin_log(xfr, ISC_LOG_DEBUG(3),				  "requested serial %u, "				  "master has %u, not updating",				  xfr->ixfr.request_serial, xfr->end_serial);			FAIL(DNS_R_UPTODATE);		}		if (xfr->reqtype == dns_rdatatype_axfr)			xfr->checkid = ISC_FALSE;		xfr->state = XFRST_FIRSTDATA;		break;	case XFRST_FIRSTDATA:		/*		 * If the transfer begins with one SOA record, it is an AXFR,		 * if it begins with two SOAs, it is an IXFR.		 */		if (xfr->reqtype == dns_rdatatype_ixfr &&		    rdata->type == dns_rdatatype_soa &&		    xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {			xfrin_log(xfr, ISC_LOG_DEBUG(3),				  "got incremental response");			CHECK(ixfr_init(xfr));

⌨️ 快捷键说明

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