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

📄 rbtdb.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2004-2006  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: rbtdb.c,v 1.196.18.41 2006/10/26 06:04:29 marka Exp $ *//*! \file *//* * Principal Author: Bob Halley */#include <config.h>#include <isc/event.h>#include <isc/mem.h>#include <isc/print.h>#include <isc/mutex.h>#include <isc/random.h>#include <isc/refcount.h>#include <isc/rwlock.h>#include <isc/string.h>#include <isc/task.h>#include <isc/time.h>#include <isc/util.h>#include <dns/acache.h>#include <dns/db.h>#include <dns/dbiterator.h>#include <dns/events.h>#include <dns/fixedname.h>#include <dns/lib.h>#include <dns/log.h>#include <dns/masterdump.h>#include <dns/rbt.h>#include <dns/rdata.h>#include <dns/rdataset.h>#include <dns/rdatasetiter.h>#include <dns/rdataslab.h>#include <dns/result.h>#include <dns/view.h>#include <dns/zone.h>#include <dns/zonekey.h>#ifdef DNS_RBTDB_VERSION64#include "rbtdb64.h"#else#include "rbtdb.h"#endif#ifdef DNS_RBTDB_VERSION64#define RBTDB_MAGIC			ISC_MAGIC('R', 'B', 'D', '8')#else#define RBTDB_MAGIC			ISC_MAGIC('R', 'B', 'D', '4')#endif/*% * Note that "impmagic" is not the first four bytes of the struct, so * ISC_MAGIC_VALID cannot be used. */#define VALID_RBTDB(rbtdb)	((rbtdb) != NULL && \				 (rbtdb)->common.impmagic == RBTDB_MAGIC)#ifdef DNS_RBTDB_VERSION64typedef isc_uint64_t			rbtdb_serial_t;/*% * Make casting easier in symbolic debuggers by using different names * for the 64 bit version. */#define dns_rbtdb_t dns_rbtdb64_t#define rdatasetheader_t rdatasetheader64_t#define rbtdb_version_t rbtdb_version64_t#elsetypedef isc_uint32_t			rbtdb_serial_t;#endiftypedef isc_uint32_t			rbtdb_rdatatype_t;#define RBTDB_RDATATYPE_BASE(type)	((dns_rdatatype_t)((type) & 0xFFFF))#define RBTDB_RDATATYPE_EXT(type)	((dns_rdatatype_t)((type) >> 16))#define RBTDB_RDATATYPE_VALUE(b, e)	(((e) << 16) | (b))#define RBTDB_RDATATYPE_SIGNSEC \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_nsec)#define RBTDB_RDATATYPE_SIGNS \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_ns)#define RBTDB_RDATATYPE_SIGCNAME \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_cname)#define RBTDB_RDATATYPE_SIGDNAME \		RBTDB_RDATATYPE_VALUE(dns_rdatatype_rrsig, dns_rdatatype_dname)#define RBTDB_RDATATYPE_NCACHEANY \		RBTDB_RDATATYPE_VALUE(0, dns_rdatatype_any)/* * We use rwlock for DB lock only when ISC_RWLOCK_USEATOMIC is non 0. * Using rwlock is effective with regard to lookup performance only when * it is implemented in an efficient way. * Otherwise, it is generally wise to stick to the simple locking since rwlock * would require more memory or can even make lookups slower due to its own * overhead (when it internally calls mutex locks). */#ifdef ISC_RWLOCK_USEATOMIC#define DNS_RBTDB_USERWLOCK 1#else#define DNS_RBTDB_USERWLOCK 0#endif#if DNS_RBTDB_USERWLOCK#define RBTDB_INITLOCK(l)	isc_rwlock_init((l), 0, 0)#define RBTDB_DESTROYLOCK(l)	isc_rwlock_destroy(l)#define RBTDB_LOCK(l, t)	RWLOCK((l), (t))#define RBTDB_UNLOCK(l, t)	RWUNLOCK((l), (t))#else#define RBTDB_INITLOCK(l)	isc_mutex_init(l)#define RBTDB_DESTROYLOCK(l)	DESTROYLOCK(l)#define RBTDB_LOCK(l, t)	LOCK(l)#define RBTDB_UNLOCK(l, t)	UNLOCK(l)#endif/* * Since node locking is sensitive to both performance and memory footprint, * we need some trick here.  If we have both high-performance rwlock and * high performance and small-memory reference counters, we use rwlock for * node lock and isc_refcount for node references.  In this case, we don't have * to protect the access to the counters by locks. * Otherwise, we simply use ordinary mutex lock for node locking, and use * simple integers as reference counters which is protected by the lock. * In most cases, we can simply use wrapper macros such as NODE_LOCK and * NODE_UNLOCK.  In some other cases, however, we need to protect reference * counters first and then protect other parts of a node as read-only data. * Special additional macros, NODE_STRONGLOCK(), NODE_WEAKLOCK(), etc, are also * provided for these special cases.  When we can use the efficient backend * routines, we should only protect the "other members" by NODE_WEAKLOCK(read). * Otherwise, we should use NODE_STRONGLOCK() to protect the entire critical * section including the access to the reference counter. * Note that we cannot use NODE_LOCK()/NODE_UNLOCK() wherever the protected * section is also protected by NODE_STRONGLOCK(). */#if defined(ISC_RWLOCK_USEATOMIC) && defined(DNS_RBT_USEISCREFCOUNT)typedef isc_rwlock_t nodelock_t;#define NODE_INITLOCK(l)	isc_rwlock_init((l), 0, 0)#define NODE_DESTROYLOCK(l)	isc_rwlock_destroy(l)#define NODE_LOCK(l, t)		RWLOCK((l), (t))#define NODE_UNLOCK(l, t)	RWUNLOCK((l), (t))#define NODE_TRYUPGRADE(l)	isc_rwlock_tryupgrade(l)#define NODE_STRONGLOCK(l)	((void)0)#define NODE_STRONGUNLOCK(l)	((void)0)#define NODE_WEAKLOCK(l, t)	NODE_LOCK(l, t)#define NODE_WEAKUNLOCK(l, t)	NODE_UNLOCK(l, t)#define NODE_WEAKDOWNGRADE(l)	isc_rwlock_downgrade(l)#elsetypedef isc_mutex_t nodelock_t;#define NODE_INITLOCK(l)	isc_mutex_init(l)#define NODE_DESTROYLOCK(l)	DESTROYLOCK(l)#define NODE_LOCK(l, t)		LOCK(l)#define NODE_UNLOCK(l, t)	UNLOCK(l)#define NODE_TRYUPGRADE(l)	ISC_R_SUCCESS#define NODE_STRONGLOCK(l)	LOCK(l)#define NODE_STRONGUNLOCK(l)	UNLOCK(l)#define NODE_WEAKLOCK(l, t)	((void)0)#define NODE_WEAKUNLOCK(l, t)	((void)0)#define NODE_WEAKDOWNGRADE(l)	((void)0)#endif/* * Allow clients with a virtual time of upto 5 minutes in the past to see * records that would have otherwise have expired. */#define RBTDB_VIRTUAL 300struct noqname {	dns_name_t name;	void *	   nsec;	void *	   nsecsig;};typedef struct acachectl acachectl_t;  typedef struct rdatasetheader {	/*%	 * Locked by the owning node's lock.	 */	rbtdb_serial_t			serial;	dns_ttl_t			ttl;	rbtdb_rdatatype_t		type;	isc_uint16_t			attributes;	dns_trust_t			trust;	struct noqname			*noqname;	/*%<	 * We don't use the LIST macros, because the LIST structure has	 * both head and tail pointers, and is doubly linked.	 */	struct rdatasetheader		*next;	/*%<	 * If this is the top header for an rdataset, 'next' points	 * to the top header for the next rdataset (i.e., the next type).	 * Otherwise, it points up to the header whose down pointer points	 * at this header.	 */	  	struct rdatasetheader		*down;	/*%<	 * Points to the header for the next older version of	 * this rdataset.	 */	isc_uint32_t			count;	/*%<	 * Monotonously increased every time this rdataset is bound so that	 * it is used as the base of the starting point in DNS responses	 * when the "cyclic" rrset-order is required.  Since the ordering	 * should not be so crucial, no lock is set for the counter for	 * performance reasons.	 */	acachectl_t			*additional_auth;	acachectl_t			*additional_glue;} rdatasetheader_t;#define RDATASET_ATTR_NONEXISTENT	0x0001#define RDATASET_ATTR_STALE		0x0002#define RDATASET_ATTR_IGNORE		0x0004#define RDATASET_ATTR_RETAIN		0x0008#define RDATASET_ATTR_NXDOMAIN		0x0010typedef struct acache_cbarg {	dns_rdatasetadditional_t	type;	unsigned int			count;	dns_db_t			*db;	dns_dbnode_t			*node;	rdatasetheader_t		*header;} acache_cbarg_t;struct acachectl {	dns_acacheentry_t		*entry;	acache_cbarg_t			*cbarg;};/* * XXX * When the cache will pre-expire data (due to memory low or other * situations) before the rdataset's TTL has expired, it MUST * respect the RETAIN bit and not expire the data until its TTL is * expired. */#undef IGNORE			/* WIN32 winbase.h defines this. */#define EXISTS(header) \	(((header)->attributes & RDATASET_ATTR_NONEXISTENT) == 0)#define NONEXISTENT(header) \	(((header)->attributes & RDATASET_ATTR_NONEXISTENT) != 0)#define IGNORE(header) \	(((header)->attributes & RDATASET_ATTR_IGNORE) != 0)#define RETAIN(header) \	(((header)->attributes & RDATASET_ATTR_RETAIN) != 0)#define NXDOMAIN(header) \	(((header)->attributes & RDATASET_ATTR_NXDOMAIN) != 0)#define DEFAULT_NODE_LOCK_COUNT		7	/*%< Should be prime. */#define DEFAULT_CACHE_NODE_LOCK_COUNT	1009	/*%< Should be prime. */typedef struct {	nodelock_t			lock;	/* Protected in the refcount routines. */	isc_refcount_t			references;	/* Locked by lock. */	isc_boolean_t			exiting;} rbtdb_nodelock_t;typedef struct rbtdb_changed {	dns_rbtnode_t *			node;	isc_boolean_t			dirty;	ISC_LINK(struct rbtdb_changed)	link;} rbtdb_changed_t;typedef ISC_LIST(rbtdb_changed_t)	rbtdb_changedlist_t;typedef struct rbtdb_version {	/* Not locked */	rbtdb_serial_t			serial;	/*	 * Protected in the refcount routines.	 * XXXJT: should we change the lock policy based on the refcount	 * performance?	 */	isc_refcount_t			references;	/* Locked by database lock. */	isc_boolean_t			writer;	isc_boolean_t			commit_ok;	rbtdb_changedlist_t		changed_list;	ISC_LINK(struct rbtdb_version)	link;} rbtdb_version_t;typedef ISC_LIST(rbtdb_version_t)	rbtdb_versionlist_t;typedef struct {	/* Unlocked. */	dns_db_t			common;#if DNS_RBTDB_USERWLOCK	isc_rwlock_t			lock;#else	isc_mutex_t			lock;#endif	isc_rwlock_t			tree_lock;	unsigned int			node_lock_count;	rbtdb_nodelock_t *	       	node_locks;	dns_rbtnode_t *			origin_node;	/* Locked by lock. */	unsigned int			active;	isc_refcount_t			references;	unsigned int			attributes;	rbtdb_serial_t			current_serial;	rbtdb_serial_t			least_serial;	rbtdb_serial_t			next_serial;	rbtdb_version_t *		current_version;	rbtdb_version_t *		future_version;	rbtdb_versionlist_t		open_versions;	isc_boolean_t			overmem;	isc_task_t *			task;	dns_dbnode_t			*soanode;	dns_dbnode_t			*nsnode;	/* Locked by tree_lock. */	dns_rbt_t *			tree;	isc_boolean_t			secure;	/* Unlocked */	unsigned int			quantum;} dns_rbtdb_t;#define RBTDB_ATTR_LOADED		0x01#define RBTDB_ATTR_LOADING		0x02/*% * Search Context */typedef struct {	dns_rbtdb_t *		rbtdb;	rbtdb_version_t *	rbtversion;	rbtdb_serial_t		serial;	unsigned int		options;	dns_rbtnodechain_t	chain;	isc_boolean_t		copy_name;	isc_boolean_t		need_cleanup;	isc_boolean_t		wild;	dns_rbtnode_t *	       	zonecut;	rdatasetheader_t *	zonecut_rdataset;	rdatasetheader_t *	zonecut_sigrdataset;	dns_fixedname_t		zonecut_name;	isc_stdtime_t		now;} rbtdb_search_t;/*% * Load Context */typedef struct {	dns_rbtdb_t *		rbtdb;	isc_stdtime_t		now;} rbtdb_load_t;static void rdataset_disassociate(dns_rdataset_t *rdataset);static isc_result_t rdataset_first(dns_rdataset_t *rdataset);static isc_result_t rdataset_next(dns_rdataset_t *rdataset);static void rdataset_current(dns_rdataset_t *rdataset, dns_rdata_t *rdata);static void rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target);static unsigned int rdataset_count(dns_rdataset_t *rdataset);static isc_result_t rdataset_getnoqname(dns_rdataset_t *rdataset,				        dns_name_t *name,					dns_rdataset_t *nsec,					dns_rdataset_t *nsecsig);static isc_result_t rdataset_getadditional(dns_rdataset_t *rdataset,					   dns_rdatasetadditional_t type,					   dns_rdatatype_t qtype,					   dns_acache_t *acache,					   dns_zone_t **zonep,					   dns_db_t **dbp,					   dns_dbversion_t **versionp,					   dns_dbnode_t **nodep,					   dns_name_t *fname,					   dns_message_t *msg,					   isc_stdtime_t now);static isc_result_t rdataset_setadditional(dns_rdataset_t *rdataset,					   dns_rdatasetadditional_t type,					   dns_rdatatype_t qtype,					   dns_acache_t *acache,					   dns_zone_t *zone,					   dns_db_t *db,					   dns_dbversion_t *version,					   dns_dbnode_t *node,					   dns_name_t *fname);static isc_result_t rdataset_putadditional(dns_acache_t *acache,					   dns_rdataset_t *rdataset,					   dns_rdatasetadditional_t type,					   dns_rdatatype_t qtype);static dns_rdatasetmethods_t rdataset_methods = {	rdataset_disassociate,	rdataset_first,	rdataset_next,	rdataset_current,	rdataset_clone,	rdataset_count,	NULL,	rdataset_getnoqname,	rdataset_getadditional,	rdataset_setadditional,	rdataset_putadditional};static void rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator);static isc_result_t rdatasetiter_next(dns_rdatasetiter_t *iterator);static void rdatasetiter_current(dns_rdatasetiter_t *iterator,				 dns_rdataset_t *rdataset);static dns_rdatasetitermethods_t rdatasetiter_methods = {	rdatasetiter_destroy,	rdatasetiter_first,	rdatasetiter_next,	rdatasetiter_current};typedef struct rbtdb_rdatasetiter {	dns_rdatasetiter_t		common;	rdatasetheader_t *		current;} rbtdb_rdatasetiter_t;static void		dbiterator_destroy(dns_dbiterator_t **iteratorp);static isc_result_t	dbiterator_first(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_last(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_seek(dns_dbiterator_t *iterator,					dns_name_t *name);static isc_result_t	dbiterator_prev(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_next(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_current(dns_dbiterator_t *iterator,					   dns_dbnode_t **nodep,					   dns_name_t *name);static isc_result_t	dbiterator_pause(dns_dbiterator_t *iterator);static isc_result_t	dbiterator_origin(dns_dbiterator_t *iterator,					  dns_name_t *name);static dns_dbiteratormethods_t dbiterator_methods = {	dbiterator_destroy,	dbiterator_first,	dbiterator_last,	dbiterator_seek,	dbiterator_prev,	dbiterator_next,	dbiterator_current,	dbiterator_pause,	dbiterator_origin};#define DELETION_BATCH_MAX 64/* * If 'paused' is ISC_TRUE, then the tree lock is not being held. */typedef struct rbtdb_dbiterator {	dns_dbiterator_t		common;

⌨️ 快捷键说明

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