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

📄 adb.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: adb.c,v 1.181.2.11.2.19 2004/09/01 05:19:57 marka Exp $ *//* * Implementation notes * -------------------- * * In finds, if task == NULL, no events will be generated, and no events * have been sent.  If task != NULL but taskaction == NULL, an event has been * posted but not yet freed.  If neither are NULL, no event was posted. * *//* * After we have cleaned all buckets, dump the database contents. */#if 0#define DUMP_ADB_AFTER_CLEANING#endif#include <config.h>#include <limits.h>#include <isc/mutexblock.h>#include <isc/netaddr.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/adb.h>#include <dns/db.h>#include <dns/events.h>#include <dns/log.h>#include <dns/rdata.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/resolver.h>#include <dns/result.h>#define DNS_ADB_MAGIC		  ISC_MAGIC('D', 'a', 'd', 'b')#define DNS_ADB_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADB_MAGIC)#define DNS_ADBNAME_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'N')#define DNS_ADBNAME_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBNAME_MAGIC)#define DNS_ADBNAMEHOOK_MAGIC	  ISC_MAGIC('a', 'd', 'N', 'H')#define DNS_ADBNAMEHOOK_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBNAMEHOOK_MAGIC)#define DNS_ADBZONEINFO_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'Z')#define DNS_ADBZONEINFO_VALID(x)  ISC_MAGIC_VALID(x, DNS_ADBZONEINFO_MAGIC)#define DNS_ADBENTRY_MAGIC	  ISC_MAGIC('a', 'd', 'b', 'E')#define DNS_ADBENTRY_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBENTRY_MAGIC)#define DNS_ADBFETCH_MAGIC	  ISC_MAGIC('a', 'd', 'F', '4')#define DNS_ADBFETCH_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH_MAGIC)#define DNS_ADBFETCH6_MAGIC	  ISC_MAGIC('a', 'd', 'F', '6')#define DNS_ADBFETCH6_VALID(x)	  ISC_MAGIC_VALID(x, DNS_ADBFETCH6_MAGIC)/* * The number of buckets needs to be a prime (for good hashing). * * XXXRTH  How many buckets do we need? */#define NBUCKETS	       1009	/* how many buckets for names/addrs *//* * For type 3 negative cache entries, we will remember that the address is * broken for this long.  XXXMLG This is also used for actual addresses, too. * The intent is to keep us from constantly asking about A/AAAA records * if the zone has extremely low TTLs. */#define ADB_CACHE_MINIMUM	10	/* seconds */#define ADB_CACHE_MAXIMUM	86400	/* seconds (86400 = 24 hours) */#define ADB_ENTRY_WINDOW	1800	/* seconds *//* * Wake up every CLEAN_SECONDS and clean CLEAN_BUCKETS buckets, so that all * buckets are cleaned in CLEAN_PERIOD seconds. */#define CLEAN_PERIOD		3600#define CLEAN_SECONDS		30#define CLEAN_BUCKETS		((NBUCKETS * CLEAN_SECONDS) / CLEAN_PERIOD)#define FREE_ITEMS		64	/* free count for memory pools */#define FILL_COUNT		16	/* fill count for memory pools */#define DNS_ADB_INVALIDBUCKET (-1)	/* invalid bucket address */#define DNS_ADB_MINADBSIZE	(1024*1024)	/* 1 Megabyte */typedef ISC_LIST(dns_adbname_t) dns_adbnamelist_t;typedef struct dns_adbnamehook dns_adbnamehook_t;typedef ISC_LIST(dns_adbnamehook_t) dns_adbnamehooklist_t;typedef struct dns_adbzoneinfo dns_adbzoneinfo_t;typedef ISC_LIST(dns_adbentry_t) dns_adbentrylist_t;typedef struct dns_adbfetch dns_adbfetch_t;typedef struct dns_adbfetch6 dns_adbfetch6_t;struct dns_adb {	unsigned int			magic;	isc_mutex_t			lock;	isc_mutex_t			reflock; /* Covers irefcnt, erefcnt */	isc_mem_t		       *mctx;	dns_view_t		       *view;	isc_timermgr_t		       *timermgr;	isc_timer_t		       *timer;	isc_taskmgr_t		       *taskmgr;	isc_task_t		       *task;	isc_boolean_t			overmem;	isc_interval_t			tick_interval;	int				next_cleanbucket;	unsigned int			irefcnt;	unsigned int			erefcnt;	isc_mutex_t			mplock;	isc_mempool_t		       *nmp;	/* dns_adbname_t */	isc_mempool_t		       *nhmp;	/* dns_adbnamehook_t */	isc_mempool_t		       *zimp;	/* dns_adbzoneinfo_t */	isc_mempool_t		       *emp;	/* dns_adbentry_t */	isc_mempool_t		       *ahmp;	/* dns_adbfind_t */	isc_mempool_t		       *aimp;	/* dns_adbaddrinfo_t */	isc_mempool_t		       *afmp;	/* dns_adbfetch_t */	/*	 * Bucketized locks and lists for names.	 *	 * XXXRTH  Have a per-bucket structure that contains all of these?	 */	dns_adbnamelist_t		names[NBUCKETS];	isc_mutex_t			namelocks[NBUCKETS];	isc_boolean_t			name_sd[NBUCKETS];	unsigned int			name_refcnt[NBUCKETS];	/*	 * Bucketized locks for entries.	 *	 * XXXRTH  Have a per-bucket structure that contains all of these?	 */	dns_adbentrylist_t		entries[NBUCKETS];	isc_mutex_t			entrylocks[NBUCKETS];	isc_boolean_t			entry_sd[NBUCKETS]; /* shutting down */	unsigned int			entry_refcnt[NBUCKETS];	isc_event_t			cevent;	isc_boolean_t			cevent_sent;	isc_boolean_t			shutting_down;	isc_eventlist_t			whenshutdown;};/* * XXXMLG  Document these structures. */struct dns_adbname {	unsigned int			magic;	dns_name_t			name;	dns_adb_t		       *adb;	unsigned int			partial_result;	unsigned int			flags;	int				lock_bucket;	dns_name_t			target;	isc_stdtime_t			expire_target;	isc_stdtime_t			expire_v4;	isc_stdtime_t			expire_v6;	unsigned int			chains;	dns_adbnamehooklist_t		v4;	dns_adbnamehooklist_t		v6;	dns_adbfetch_t		       *fetch_a;	dns_adbfetch_t		       *fetch_aaaa;	unsigned int			fetch_err;	unsigned int			fetch6_err;	dns_adbfindlist_t		finds;	ISC_LINK(dns_adbname_t)		plink;};struct dns_adbfetch {	unsigned int			magic;	dns_adbnamehook_t	       *namehook;	dns_adbentry_t		       *entry;	dns_fetch_t		       *fetch;	dns_rdataset_t			rdataset;};/* * dns_adbnamehook_t * * This is a small widget that dangles off a dns_adbname_t.  It contains a * pointer to the address information about this host, and a link to the next * namehook that will contain the next address this host has. */struct dns_adbnamehook {	unsigned int			magic;	dns_adbentry_t		       *entry;	ISC_LINK(dns_adbnamehook_t)	plink;};/* * dns_adbzoneinfo_t * * This is a small widget that holds zone-specific information about an * address.  Currently limited to lameness, but could just as easily be * extended to other types of information about zones. */struct dns_adbzoneinfo {	unsigned int			magic;	dns_name_t			zone;	isc_stdtime_t			lame_timer;	ISC_LINK(dns_adbzoneinfo_t)	plink;};/* * An address entry.  It holds quite a bit of information about addresses, * including edns state (in "flags"), rtt, and of course the address of * the host. */struct dns_adbentry {	unsigned int			magic;	int				lock_bucket;	unsigned int			refcnt;	unsigned int			flags;	unsigned int			srtt;	isc_sockaddr_t			sockaddr;	isc_stdtime_t			expires;	/*	 * A nonzero 'expires' field indicates that the entry should	 * persist until that time.  This allows entries found	 * using dns_adb_findaddrinfo() to persist for a limited time	 * even though they are not necessarily associated with a	 * name.	 */	ISC_LIST(dns_adbzoneinfo_t)	zoneinfo;	ISC_LINK(dns_adbentry_t)	plink;};/* * Internal functions (and prototypes). */static inline dns_adbname_t *new_adbname(dns_adb_t *, dns_name_t *);static inline void free_adbname(dns_adb_t *, dns_adbname_t **);static inline dns_adbnamehook_t *new_adbnamehook(dns_adb_t *,						 dns_adbentry_t *);static inline void free_adbnamehook(dns_adb_t *, dns_adbnamehook_t **);static inline dns_adbzoneinfo_t *new_adbzoneinfo(dns_adb_t *, dns_name_t *);static inline void free_adbzoneinfo(dns_adb_t *, dns_adbzoneinfo_t **);static inline dns_adbentry_t *new_adbentry(dns_adb_t *);static inline void free_adbentry(dns_adb_t *, dns_adbentry_t **);static inline dns_adbfind_t *new_adbfind(dns_adb_t *);static inline isc_boolean_t free_adbfind(dns_adb_t *, dns_adbfind_t **);static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *, dns_adbentry_t *,						 in_port_t);static inline dns_adbfetch_t *new_adbfetch(dns_adb_t *);static inline void free_adbfetch(dns_adb_t *, dns_adbfetch_t **);static inline dns_adbname_t *find_name_and_lock(dns_adb_t *, dns_name_t *,						unsigned int, int *);static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *,						  isc_sockaddr_t *, int *);static void dump_adb(dns_adb_t *, FILE *, isc_boolean_t debug);static void print_dns_name(FILE *, dns_name_t *);static void print_namehook_list(FILE *, const char *legend,				dns_adbnamehooklist_t *list,				isc_boolean_t debug,				isc_stdtime_t now);static void print_find_list(FILE *, dns_adbname_t *);static void print_fetch_list(FILE *, dns_adbname_t *);static inline isc_boolean_t dec_adb_irefcnt(dns_adb_t *);static inline void inc_adb_irefcnt(dns_adb_t *);static inline void inc_adb_erefcnt(dns_adb_t *);static inline void inc_entry_refcnt(dns_adb_t *, dns_adbentry_t *,				    isc_boolean_t);static inline isc_boolean_t dec_entry_refcnt(dns_adb_t *, dns_adbentry_t *,					     isc_boolean_t);static inline void violate_locking_hierarchy(isc_mutex_t *, isc_mutex_t *);static isc_boolean_t clean_namehooks(dns_adb_t *, dns_adbnamehooklist_t *);static void clean_target(dns_adb_t *, dns_name_t *);static void clean_finds_at_name(dns_adbname_t *, isc_eventtype_t,				unsigned int);static isc_boolean_t check_expire_namehooks(dns_adbname_t *, isc_stdtime_t,					    isc_boolean_t);static void cancel_fetches_at_name(dns_adbname_t *);static isc_result_t dbfind_name(dns_adbname_t *, isc_stdtime_t,				dns_rdatatype_t);static isc_result_t fetch_name(dns_adbname_t *, isc_boolean_t,			       dns_rdatatype_t);static inline void check_exit(dns_adb_t *);static void timer_cleanup(isc_task_t *, isc_event_t *);static void destroy(dns_adb_t *);static isc_boolean_t shutdown_names(dns_adb_t *);static isc_boolean_t shutdown_entries(dns_adb_t *);static inline void link_name(dns_adb_t *, int, dns_adbname_t *);static inline isc_boolean_t unlink_name(dns_adb_t *, dns_adbname_t *);static inline void link_entry(dns_adb_t *, int, dns_adbentry_t *);static inline isc_boolean_t unlink_entry(dns_adb_t *, dns_adbentry_t *);static isc_boolean_t kill_name(dns_adbname_t **, isc_eventtype_t);static void water(void *arg, int mark);/* * MUST NOT overlap DNS_ADBFIND_* flags! */#define FIND_EVENT_SENT		0x40000000#define FIND_EVENT_FREED	0x80000000#define FIND_EVENTSENT(h)	(((h)->flags & FIND_EVENT_SENT) != 0)#define FIND_EVENTFREED(h)	(((h)->flags & FIND_EVENT_FREED) != 0)#define NAME_NEEDS_POKE		0x80000000#define NAME_IS_DEAD		0x40000000#define NAME_HINT_OK		DNS_ADBFIND_HINTOK#define NAME_GLUE_OK		DNS_ADBFIND_GLUEOK#define NAME_STARTATZONE	DNS_ADBFIND_STARTATZONE#define NAME_DEAD(n)		(((n)->flags & NAME_IS_DEAD) != 0)#define NAME_NEEDSPOKE(n)	(((n)->flags & NAME_NEEDS_POKE) != 0)#define NAME_GLUEOK(n)		(((n)->flags & NAME_GLUE_OK) != 0)#define NAME_HINTOK(n)		(((n)->flags & NAME_HINT_OK) != 0)/* * To the name, address classes are all that really exist.  If it has a * V6 address it doesn't care if it came from a AAAA query. */#define NAME_HAS_V4(n)		(!ISC_LIST_EMPTY((n)->v4))#define NAME_HAS_V6(n)		(!ISC_LIST_EMPTY((n)->v6))#define NAME_HAS_ADDRS(n)	(NAME_HAS_V4(n) || NAME_HAS_V6(n))/* * Fetches are broken out into A and AAAA types.  In some cases, * however, it makes more sense to test for a particular class of fetches, * like V4 or V6 above. * Note: since we have removed the support of A6 in adb, FETCH_A and FETCH_AAAA * are now equal to FETCH_V4 and FETCH_V6, respectively. */#define NAME_FETCH_A(n)		((n)->fetch_a != NULL)#define NAME_FETCH_AAAA(n)	((n)->fetch_aaaa != NULL)#define NAME_FETCH_V4(n)	(NAME_FETCH_A(n))#define NAME_FETCH_V6(n)	(NAME_FETCH_AAAA(n))#define NAME_FETCH(n)		(NAME_FETCH_V4(n) || NAME_FETCH_V6(n))/* * Find options and tests to see if there are addresses on the list. */#define FIND_WANTEVENT(fn)	(((fn)->options & DNS_ADBFIND_WANTEVENT) != 0)#define FIND_WANTEMPTYEVENT(fn)	(((fn)->options & DNS_ADBFIND_EMPTYEVENT) != 0)#define FIND_AVOIDFETCHES(fn)	(((fn)->options & DNS_ADBFIND_AVOIDFETCHES) \				 != 0)#define FIND_STARTATZONE(fn)	(((fn)->options & DNS_ADBFIND_STARTATZONE) \				 != 0)#define FIND_HINTOK(fn)		(((fn)->options & DNS_ADBFIND_HINTOK) != 0)#define FIND_GLUEOK(fn)		(((fn)->options & DNS_ADBFIND_GLUEOK) != 0)#define FIND_HAS_ADDRS(fn)	(!ISC_LIST_EMPTY((fn)->list))#define FIND_RETURNLAME(fn)	(((fn)->options & DNS_ADBFIND_RETURNLAME) != 0)/* * These are currently used on simple unsigned ints, so they are * not really associated with any particular type. */#define WANT_INET(x)		(((x) & DNS_ADBFIND_INET) != 0)#define WANT_INET6(x)		(((x) & DNS_ADBFIND_INET6) != 0)#define EXPIRE_OK(exp, now)	((exp == INT_MAX) || (exp < now))/* * Find out if the flags on a name (nf) indicate if it is a hint or * glue, and compare this to the appropriate bits set in o, to see if * this is ok. */#define GLUE_OK(nf, o) (!NAME_GLUEOK(nf) || (((o) & DNS_ADBFIND_GLUEOK) != 0))#define HINT_OK(nf, o) (!NAME_HINTOK(nf) || (((o) & DNS_ADBFIND_HINTOK) != 0))#define GLUEHINT_OK(nf, o) (GLUE_OK(nf, o) || HINT_OK(nf, o))#define STARTATZONE_MATCHES(nf, o) (((nf)->flags & NAME_STARTATZONE) == \				    ((o) & DNS_ADBFIND_STARTATZONE))#define ENTER_LEVEL		ISC_LOG_DEBUG(50)#define EXIT_LEVEL		ENTER_LEVEL#define CLEAN_LEVEL		ISC_LOG_DEBUG(100)#define DEF_LEVEL		ISC_LOG_DEBUG(5)#define NCACHE_LEVEL		ISC_LOG_DEBUG(20)#define NCACHE_RESULT(r)	((r) == DNS_R_NCACHENXDOMAIN || \				 (r) == DNS_R_NCACHENXRRSET)#define AUTH_NX(r)		((r) == DNS_R_NXDOMAIN || \				 (r) == DNS_R_NXRRSET)#define NXDOMAIN_RESULT(r)	((r) == DNS_R_NXDOMAIN || \				 (r) == DNS_R_NCACHENXDOMAIN)#define NXRRSET_RESULT(r)	((r) == DNS_R_NCACHENXRRSET || \				 (r) == DNS_R_NXRRSET || \				 (r) == DNS_R_HINTNXRRSET)/* * Error state rankings. */#define FIND_ERR_SUCCESS		0  /* highest rank */#define FIND_ERR_CANCELED		1#define FIND_ERR_FAILURE		2#define FIND_ERR_NXDOMAIN		3#define FIND_ERR_NXRRSET		4#define FIND_ERR_UNEXPECTED		5#define FIND_ERR_NOTFOUND		6#define FIND_ERR_MAX			7static const char *errnames[] = {	"success",	"canceled",	"failure",	"nxdomain",	"nxrrset",	"unexpected",	"not_found"};#define NEWERR(old, new)	(ISC_MIN((old), (new)))static isc_result_t find_err_map[FIND_ERR_MAX] = {	ISC_R_SUCCESS,	ISC_R_CANCELED,	ISC_R_FAILURE,	DNS_R_NXDOMAIN,	DNS_R_NXRRSET,	ISC_R_UNEXPECTED,	ISC_R_NOTFOUND		/* not YET found */};static voidDP(int level, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);static voidDP(int level, const char *format, ...) {	va_list args;	va_start(args, format);	isc_log_vwrite(dns_lctx,		       DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_ADB,		       level, format, args);	va_end(args);}static inline dns_ttl_tttlclamp(dns_ttl_t ttl) {	if (ttl < ADB_CACHE_MINIMUM)		ttl = ADB_CACHE_MINIMUM;	if (ttl > ADB_CACHE_MAXIMUM)		ttl = ADB_CACHE_MAXIMUM;	return (ttl);}/* * Requires the adbname bucket be locked and that no entry buckets be locked. * * This code handles A and AAAA rdatasets only. */static isc_result_timport_rdataset(dns_adbname_t *adbname, dns_rdataset_t *rdataset,		isc_stdtime_t now){	isc_result_t result;	dns_adb_t *adb;	dns_adbnamehook_t *nh;	dns_adbnamehook_t *anh;	dns_rdata_t rdata = DNS_RDATA_INIT;	struct in_addr ina;	struct in6_addr in6a;	isc_sockaddr_t sockaddr;	dns_adbentry_t *foundentry;  /* NO CLEAN UP! */	int addr_bucket;	isc_boolean_t new_addresses_added;	dns_rdatatype_t rdtype;	unsigned int findoptions;	INSIST(DNS_ADBNAME_VALID(adbname));	adb = adbname->adb;	INSIST(DNS_ADB_VALID(adb));	rdtype = rdataset->type;	INSIST((rdtype == dns_rdatatype_a) || (rdtype == dns_rdatatype_aaaa));	if (rdtype == dns_rdatatype_a)		findoptions = DNS_ADBFIND_INET;	else		findoptions = DNS_ADBFIND_INET6;	addr_bucket = DNS_ADB_INVALIDBUCKET;	new_addresses_added = ISC_FALSE;	nh = NULL;	result = dns_rdataset_first(rdataset);	while (result == ISC_R_SUCCESS) {		dns_rdata_reset(&rdata);		dns_rdataset_current(rdataset, &rdata);		if (rdtype == dns_rdatatype_a) {			INSIST(rdata.length == 4);			memcpy(&ina.s_addr, rdata.data, 4);

⌨️ 快捷键说明

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