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

📄 update.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * 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: update.c,v 1.88.2.5.2.23 2004/07/23 02:56:52 marka Exp $ */#include <config.h>#include <isc/print.h>#include <isc/string.h>#include <isc/taskpool.h>#include <isc/util.h>#include <dns/db.h>#include <dns/dbiterator.h>#include <dns/diff.h>#include <dns/dnssec.h>#include <dns/events.h>#include <dns/fixedname.h>#include <dns/journal.h>#include <dns/message.h>#include <dns/nsec.h>#include <dns/rdataclass.h>#include <dns/rdataset.h>#include <dns/rdatasetiter.h>#include <dns/rdatatype.h>#include <dns/soa.h>#include <dns/ssu.h>#include <dns/view.h>#include <dns/zone.h>#include <dns/zt.h>#include <named/client.h>#include <named/log.h>#include <named/update.h>/* * This module implements dynamic update as in RFC2136. *//*  XXX TODO:  - document strict minimality*//**************************************************************************//* * Log level for tracing dynamic update protocol requests. */#define LOGLEVEL_PROTOCOL	ISC_LOG_INFO/* * Log level for low-level debug tracing. */#define LOGLEVEL_DEBUG 		ISC_LOG_DEBUG(8)/* * Check an operation for failure.  These macros all assume that * the function using them has a 'result' variable and a 'failure' * label. */#define CHECK(op) \	do { result = (op); 				  	 \	       if (result != ISC_R_SUCCESS) goto failure; 	 \	} while (0)/* * Fail unconditionally with result 'code', which must not * be ISC_R_SUCCESS.  The reason for failure presumably has * been logged already. * * The test against ISC_R_SUCCESS 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)/* * Fail unconditionally and log as a client error. * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */#define FAILC(code, msg) \	do {							\		const char *_what = "failed";			\		result = (code);				\		switch (result) {				\		case DNS_R_NXDOMAIN:				\		case DNS_R_YXDOMAIN:				\		case DNS_R_YXRRSET:				\		case DNS_R_NXRRSET:				\			_what = "unsuccessful";			\		}						\		update_log(client, zone, LOGLEVEL_PROTOCOL,   	\			      "update %s: %s (%s)", _what,	\		      	      msg, isc_result_totext(result));	\		if (result != ISC_R_SUCCESS) goto failure;	\	} while (0)#define FAILN(code, name, msg) \	do {								\		const char *_what = "failed";				\		result = (code);					\		switch (result) {					\		case DNS_R_NXDOMAIN:					\		case DNS_R_YXDOMAIN:					\		case DNS_R_YXRRSET:					\		case DNS_R_NXRRSET:					\			_what = "unsuccessful";				\		}							\		if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) {	\			char _nbuf[DNS_NAME_FORMATSIZE];		\			dns_name_format(name, _nbuf, sizeof(_nbuf));	\			update_log(client, zone, LOGLEVEL_PROTOCOL,   	\				   "update %s: %s: %s (%s)", _what, _nbuf, \				   msg, isc_result_totext(result));	\		}							\		if (result != ISC_R_SUCCESS) goto failure;		\	} while (0)#define FAILNT(code, name, type, msg) \	do {								\		const char *_what = "failed";				\		result = (code);					\		switch (result) {					\		case DNS_R_NXDOMAIN:					\		case DNS_R_YXDOMAIN:					\		case DNS_R_YXRRSET:					\		case DNS_R_NXRRSET:					\			_what = "unsuccessful";				\		}							\		if (isc_log_wouldlog(ns_g_lctx, LOGLEVEL_PROTOCOL)) {	\			char _nbuf[DNS_NAME_FORMATSIZE];		\			char _tbuf[DNS_RDATATYPE_FORMATSIZE];		\			dns_name_format(name, _nbuf, sizeof(_nbuf));	\			dns_rdatatype_format(type, _tbuf, sizeof(_tbuf)); \			update_log(client, zone, LOGLEVEL_PROTOCOL,   	\				   "update %s: %s/%s: %s (%s)",		\				   _what, _nbuf, _tbuf, msg,		\				   isc_result_totext(result));		\		}							\		if (result != ISC_R_SUCCESS) goto failure;		\	} while (0)/* * Fail unconditionally and log as a server error. * The test against ISC_R_SUCCESS is there to keep the Solaris compiler * from complaining about "end-of-loop code not reached". */#define FAILS(code, msg) \	do {							\		result = (code);				\		update_log(client, zone, LOGLEVEL_PROTOCOL,	\			      "error: %s: %s", 			\			      msg, isc_result_totext(result));	\		if (result != ISC_R_SUCCESS) goto failure;	\	} while (0)/**************************************************************************/typedef struct rr rr_t;struct rr {	/* dns_name_t name; */	isc_uint32_t 		ttl;	dns_rdata_t 		rdata;};typedef struct update_event update_event_t;struct update_event {	ISC_EVENT_COMMON(update_event_t);	dns_zone_t 		*zone;	isc_result_t		result;	dns_message_t		*answer;};/**************************************************************************//* * Forward declarations. */static void update_action(isc_task_t *task, isc_event_t *event);static void updatedone_action(isc_task_t *task, isc_event_t *event);static isc_result_t send_forward_event(ns_client_t *client, dns_zone_t *zone);static void forward_done(isc_task_t *task, isc_event_t *event);/**************************************************************************/static voidupdate_log(ns_client_t *client, dns_zone_t *zone,	   int level, const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);static voidupdate_log(ns_client_t *client, dns_zone_t *zone,	   int level, const char *fmt, ...){	va_list ap;	char message[4096];	char namebuf[DNS_NAME_FORMATSIZE];	char classbuf[DNS_RDATACLASS_FORMATSIZE];	if (client == NULL || zone == NULL)		return;	if (isc_log_wouldlog(ns_g_lctx, level) == ISC_FALSE)		return;	dns_name_format(dns_zone_getorigin(zone), namebuf,			sizeof(namebuf));	dns_rdataclass_format(dns_zone_getclass(zone), classbuf,			      sizeof(classbuf));	va_start(ap, fmt);	vsnprintf(message, sizeof(message), fmt, ap);	va_end(ap);	ns_client_log(client, NS_LOGCATEGORY_UPDATE, NS_LOGMODULE_UPDATE,		      level, "updating zone '%s/%s': %s",		      namebuf, classbuf, message);}static isc_result_tcheckupdateacl(ns_client_t *client, dns_acl_t *acl, const char *message,	       dns_name_t *zonename, isc_boolean_t slave){	char namebuf[DNS_NAME_FORMATSIZE];	char classbuf[DNS_RDATACLASS_FORMATSIZE];	int level = ISC_LOG_ERROR;	const char *msg = "denied";	isc_result_t result;	if (slave && acl == NULL) {		result = DNS_R_NOTIMP;		level = ISC_LOG_DEBUG(3);		msg = "disabled";	} else		result = ns_client_checkaclsilent(client, acl, ISC_FALSE);	if (result == ISC_R_SUCCESS) {		level = ISC_LOG_DEBUG(3);		msg = "approved";	}	dns_name_format(zonename, namebuf, sizeof(namebuf));	dns_rdataclass_format(client->view->rdclass, classbuf,			      sizeof(classbuf));	ns_client_log(client, NS_LOGCATEGORY_UPDATE_SECURITY,			      NS_LOGMODULE_UPDATE, level, "%s '%s/%s' %s",			      message, namebuf, classbuf, msg);	return (result);}/* * Update a single RR in version 'ver' of 'db' and log the * update in 'diff'. * * Ensures: *   '*tuple' == NULL.  Either the tuple is freed, or its *         ownership has been transferred to the diff. */static isc_result_tdo_one_tuple(dns_difftuple_t **tuple,	     dns_db_t *db, dns_dbversion_t *ver,	     dns_diff_t *diff){	dns_diff_t temp_diff;	isc_result_t result;	/*	 * Create a singleton diff.	 */	dns_diff_init(diff->mctx, &temp_diff);	ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);	/*	 * Apply it to the database.	 */	result = dns_diff_apply(&temp_diff, db, ver);	ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);	if (result != ISC_R_SUCCESS) {		dns_difftuple_free(tuple);		return (result);	}	/*	 * Merge it into the current pending journal entry.	 */	dns_diff_appendminimal(diff, tuple);	/*	 * Do not clear temp_diff.	 */	return (ISC_R_SUCCESS);}/* * Perform the updates in 'updates' in version 'ver' of 'db' and log the * update in 'diff'. * * Ensures: *   'updates' is empty. */static isc_result_tdo_diff(dns_diff_t *updates, dns_db_t *db, dns_dbversion_t *ver,	dns_diff_t *diff){	isc_result_t result;	while (! ISC_LIST_EMPTY(updates->tuples)) {		dns_difftuple_t *t = ISC_LIST_HEAD(updates->tuples);		ISC_LIST_UNLINK(updates->tuples, t, link);		CHECK(do_one_tuple(&t, db, ver, diff));	}	return (ISC_R_SUCCESS); failure:	dns_diff_clear(diff);	return (result);}static isc_result_tupdate_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,	      dns_diffop_t op, dns_name_t *name,	      dns_ttl_t ttl, dns_rdata_t *rdata){	dns_difftuple_t *tuple = NULL;	isc_result_t result;	result = dns_difftuple_create(diff->mctx, op,				      name, ttl, rdata, &tuple);	if (result != ISC_R_SUCCESS)		return (result);	return (do_one_tuple(&tuple, db, ver, diff));}/**************************************************************************//* * Callback-style iteration over rdatasets and rdatas. * * foreach_rrset() can be used to iterate over the RRsets * of a name and call a callback function with each * one.  Similarly, foreach_rr() can be used to iterate * over the individual RRs at name, optionally restricted * to RRs of a given type. * * The callback functions are called "actions" and take * two arguments: a void pointer for passing arbitrary * context information, and a pointer to the current RRset * or RR.  By convention, their names end in "_action". *//* * XXXRTH  We might want to make this public somewhere in libdns. *//* * Function type for foreach_rrset() iterator actions. */typedef isc_result_t rrset_func(void *data, dns_rdataset_t *rrset);/* * Function type for foreach_rr() iterator actions. */typedef isc_result_t rr_func(void *data, rr_t *rr);/* * Internal context struct for foreach_node_rr(). */typedef struct {	rr_func *	rr_action;	void *		rr_action_data;} foreach_node_rr_ctx_t;/* * Internal helper function for foreach_node_rr(). */static isc_result_tforeach_node_rr_action(void *data, dns_rdataset_t *rdataset) {	isc_result_t result;	foreach_node_rr_ctx_t *ctx = data;	for (result = dns_rdataset_first(rdataset);	     result == ISC_R_SUCCESS;	     result = dns_rdataset_next(rdataset))	{		rr_t rr = { 0, DNS_RDATA_INIT };				dns_rdataset_current(rdataset, &rr.rdata);		rr.ttl = rdataset->ttl;		result = (*ctx->rr_action)(ctx->rr_action_data, &rr);		if (result != ISC_R_SUCCESS)			return (result);	}	if (result != ISC_R_NOMORE)		return (result);	return (ISC_R_SUCCESS);}/* * For each rdataset of 'name' in 'ver' of 'db', call 'action' * with the rdataset and 'action_data' as arguments.  If the name * does not exist, do nothing. * * If 'action' returns an error, abort iteration and return the error. */static isc_result_tforeach_rrset(dns_db_t *db,	      dns_dbversion_t *ver,	      dns_name_t *name,	      rrset_func *action,	      void *action_data){	isc_result_t result;	dns_dbnode_t *node;	dns_rdatasetiter_t *iter;	node = NULL;	result = dns_db_findnode(db, name, ISC_FALSE, &node);	if (result == ISC_R_NOTFOUND)		return (ISC_R_SUCCESS);	if (result != ISC_R_SUCCESS)		return (result);	iter = NULL;	result = dns_db_allrdatasets(db, node, ver,				     (isc_stdtime_t) 0, &iter);	if (result != ISC_R_SUCCESS)		goto cleanup_node;	for (result = dns_rdatasetiter_first(iter);	     result == ISC_R_SUCCESS;	     result = dns_rdatasetiter_next(iter))	{		dns_rdataset_t rdataset;		dns_rdataset_init(&rdataset);		dns_rdatasetiter_current(iter, &rdataset);		result = (*action)(action_data, &rdataset);		dns_rdataset_disassociate(&rdataset);		if (result != ISC_R_SUCCESS)			goto cleanup_iterator;	}	if (result == ISC_R_NOMORE)		result = ISC_R_SUCCESS; cleanup_iterator:	dns_rdatasetiter_destroy(&iter); cleanup_node:	dns_db_detachnode(db, &node);	return (result);}/* * For each RR of 'name' in 'ver' of 'db', call 'action' * with the RR and 'action_data' as arguments.  If the name * does not exist, do nothing. * * If 'action' returns an error, abort iteration * and return the error.

⌨️ 快捷键说明

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