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

📄 adb.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
	dns_adbaddrinfo_t *ai;	ai = isc_mempool_get(adb->aimp);	if (ai == NULL)		return (NULL);	ai->magic = DNS_ADBADDRINFO_MAGIC;	ai->sockaddr = entry->sockaddr;	isc_sockaddr_setport(&ai->sockaddr, port);	ai->srtt = entry->srtt;	ai->flags = entry->flags;	ai->entry = entry;	ISC_LINK_INIT(ai, publink);	return (ai);}static inline voidfree_adbaddrinfo(dns_adb_t *adb, dns_adbaddrinfo_t **ainfo) {	dns_adbaddrinfo_t *ai;	INSIST(ainfo != NULL && DNS_ADBADDRINFO_VALID(*ainfo));	ai = *ainfo;	*ainfo = NULL;	INSIST(ai->entry == NULL);	INSIST(!ISC_LINK_LINKED(ai, publink));	ai->magic = 0;	isc_mempool_put(adb->aimp, ai);}/* * Search for the name.  NOTE:  The bucket is kept locked on both * success and failure, so it must always be unlocked by the caller! * * On the first call to this function, *bucketp must be set to * DNS_ADB_INVALIDBUCKET. */static inline dns_adbname_t *find_name_and_lock(dns_adb_t *adb, dns_name_t *name,		   unsigned int options, int *bucketp){	dns_adbname_t *adbname;	int bucket;	bucket = dns_name_fullhash(name, ISC_FALSE) % NBUCKETS;	if (*bucketp == DNS_ADB_INVALIDBUCKET) {		LOCK(&adb->namelocks[bucket]);		*bucketp = bucket;	} else if (*bucketp != bucket) {		UNLOCK(&adb->namelocks[*bucketp]);		LOCK(&adb->namelocks[bucket]);		*bucketp = bucket;	}	adbname = ISC_LIST_HEAD(adb->names[bucket]);	while (adbname != NULL) {		if (!NAME_DEAD(adbname)) {			if (dns_name_equal(name, &adbname->name)			    && GLUEHINT_OK(adbname, options)			    && STARTATZONE_MATCHES(adbname, options))				return (adbname);		}		adbname = ISC_LIST_NEXT(adbname, plink);	}	return (NULL);}/* * Search for the address.  NOTE:  The bucket is kept locked on both * success and failure, so it must always be unlocked by the caller. * * On the first call to this function, *bucketp must be set to * DNS_ADB_INVALIDBUCKET.  This will cause a lock to occur.  On * later calls (within the same "lock path") it can be left alone, so * if this function is called multiple times locking is only done if * the bucket changes. */static inline dns_adbentry_t *find_entry_and_lock(dns_adb_t *adb, isc_sockaddr_t *addr, int *bucketp) {	dns_adbentry_t *entry;	int bucket;	bucket = isc_sockaddr_hash(addr, ISC_TRUE) % NBUCKETS;	if (*bucketp == DNS_ADB_INVALIDBUCKET) {		LOCK(&adb->entrylocks[bucket]);		*bucketp = bucket;	} else if (*bucketp != bucket) {		UNLOCK(&adb->entrylocks[*bucketp]);		LOCK(&adb->entrylocks[bucket]);		*bucketp = bucket;	}	entry = ISC_LIST_HEAD(adb->entries[bucket]);	while (entry != NULL) {		if (isc_sockaddr_equal(addr, &entry->sockaddr))			return (entry);		entry = ISC_LIST_NEXT(entry, plink);	}	return (NULL);}/* * Entry bucket MUST be locked! */static isc_boolean_tentry_is_bad_for_zone(dns_adb_t *adb, dns_adbentry_t *entry, dns_name_t *zone,		      isc_stdtime_t now){	dns_adbzoneinfo_t *zi, *next_zi;	isc_boolean_t is_bad;	is_bad = ISC_FALSE;	zi = ISC_LIST_HEAD(entry->zoneinfo);	if (zi == NULL)		return (ISC_FALSE);	while (zi != NULL) {		next_zi = ISC_LIST_NEXT(zi, plink);		/*		 * Has the entry expired?		 */		if (zi->lame_timer < now) {			ISC_LIST_UNLINK(entry->zoneinfo, zi, plink);			free_adbzoneinfo(adb, &zi);		}		/*		 * Order tests from least to most expensive.		 */		if (zi != NULL && !is_bad) {			if (dns_name_equal(zone, &zi->zone))				is_bad = ISC_TRUE;		}		zi = next_zi;	}	return (is_bad);}static voidcopy_namehook_lists(dns_adb_t *adb, dns_adbfind_t *find, dns_name_t *zone,		    dns_adbname_t *name, isc_stdtime_t now){	dns_adbnamehook_t *namehook;	dns_adbaddrinfo_t *addrinfo;	dns_adbentry_t *entry;	int bucket;	bucket = DNS_ADB_INVALIDBUCKET;	if (find->options & DNS_ADBFIND_INET) {		namehook = ISC_LIST_HEAD(name->v4);		while (namehook != NULL) {			entry = namehook->entry;			bucket = entry->lock_bucket;			LOCK(&adb->entrylocks[bucket]);			if (!FIND_RETURNLAME(find)			    && entry_is_bad_for_zone(adb, entry, zone, now)) {				find->options |= DNS_ADBFIND_LAMEPRUNED;				goto nextv4;			}			addrinfo = new_adbaddrinfo(adb, entry, find->port);			if (addrinfo == NULL) {				find->partial_result |= DNS_ADBFIND_INET;				goto out;			}			/*			 * Found a valid entry.  Add it to the find's list.			 */			inc_entry_refcnt(adb, entry, ISC_FALSE);			ISC_LIST_APPEND(find->list, addrinfo, publink);			addrinfo = NULL;		nextv4:			UNLOCK(&adb->entrylocks[bucket]);			bucket = DNS_ADB_INVALIDBUCKET;			namehook = ISC_LIST_NEXT(namehook, plink);		}	}	if (find->options & DNS_ADBFIND_INET6) {		namehook = ISC_LIST_HEAD(name->v6);		while (namehook != NULL) {			entry = namehook->entry;			bucket = entry->lock_bucket;			LOCK(&adb->entrylocks[bucket]);			if (entry_is_bad_for_zone(adb, entry, zone, now))				goto nextv6;			addrinfo = new_adbaddrinfo(adb, entry, find->port);			if (addrinfo == NULL) {				find->partial_result |= DNS_ADBFIND_INET6;				goto out;			}			/*			 * Found a valid entry.  Add it to the find's list.			 */			inc_entry_refcnt(adb, entry, ISC_FALSE);			ISC_LIST_APPEND(find->list, addrinfo, publink);			addrinfo = NULL;		nextv6:			UNLOCK(&adb->entrylocks[bucket]);			bucket = DNS_ADB_INVALIDBUCKET;			namehook = ISC_LIST_NEXT(namehook, plink);		}	} out:	if (bucket != DNS_ADB_INVALIDBUCKET)		UNLOCK(&adb->entrylocks[bucket]);}static voidshutdown_task(isc_task_t *task, isc_event_t *ev) {	dns_adb_t *adb;	UNUSED(task);	adb = ev->ev_arg;	INSIST(DNS_ADB_VALID(adb));	/*	 * Kill the timer, and then the ADB itself.  Note that this implies	 * that this task was the one scheduled to get timer events.  If	 * this is not true (and it is unfortunate there is no way to INSIST()	 * this) badness will occur.	 */	LOCK(&adb->lock);	isc_timer_detach(&adb->timer);	UNLOCK(&adb->lock);	isc_event_free(&ev);	destroy(adb);}/* * Name bucket must be locked; adb may be locked; no other locks held. */static isc_boolean_tcheck_expire_name(dns_adbname_t **namep, isc_stdtime_t now) {	dns_adbname_t *name;	isc_result_t result = ISC_FALSE;	INSIST(namep != NULL && DNS_ADBNAME_VALID(*namep));	name = *namep;	if (NAME_HAS_V4(name) || NAME_HAS_V6(name))		return (result);	if (NAME_FETCH(name))		return (result);	if (!EXPIRE_OK(name->expire_v4, now))		return (result);	if (!EXPIRE_OK(name->expire_v6, now))		return (result);	if (!EXPIRE_OK(name->expire_target, now))		return (result);	/*	 * The name is empty.  Delete it.	 */	result = kill_name(&name, DNS_EVENT_ADBEXPIRED);	*namep = NULL;	/*	 * Our caller, or one of its callers, will be calling check_exit() at	 * some point, so we don't need to do it here.	 */	return (result);}/* * Entry bucket must be locked; adb may be locked; no other locks held. */static isc_boolean_tcheck_expire_entry(dns_adb_t *adb, dns_adbentry_t **entryp, isc_stdtime_t now){	dns_adbentry_t *entry;	isc_boolean_t expire;	isc_boolean_t result = ISC_FALSE;	INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));	entry = *entryp;	if (entry->refcnt != 0)		return (result);	if (adb->overmem) {		isc_uint32_t val;		isc_random_get(&val);		expire = ISC_TF((val % 4) == 0);	} else		expire = ISC_FALSE;	if (entry->expires == 0 || (! expire && entry->expires > now))		return (result);	/*	 * The entry is not in use.  Delete it.	 */	DP(DEF_LEVEL, "killing entry %p", entry);	INSIST(ISC_LINK_LINKED(entry, plink));	result = unlink_entry(adb, entry);	free_adbentry(adb, &entry);	if (result)		dec_adb_irefcnt(adb);	*entryp = NULL;	return (result);}/* * ADB must be locked, and no other locks held. */static isc_boolean_tcleanup_names(dns_adb_t *adb, int bucket, isc_stdtime_t now) {	dns_adbname_t *name;	dns_adbname_t *next_name;	isc_result_t result = ISC_FALSE;	DP(CLEAN_LEVEL, "cleaning name bucket %d", bucket);	LOCK(&adb->namelocks[bucket]);	if (adb->name_sd[bucket]) {		UNLOCK(&adb->namelocks[bucket]);		return (result);	}	name = ISC_LIST_HEAD(adb->names[bucket]);	while (name != NULL) {		next_name = ISC_LIST_NEXT(name, plink);		INSIST(result == ISC_FALSE);		result = check_expire_namehooks(name, now, adb->overmem);		if (!result)			result = check_expire_name(&name, now);		name = next_name;	}	UNLOCK(&adb->namelocks[bucket]);	return (result);}/* * ADB must be locked, and no other locks held. */static isc_boolean_tcleanup_entries(dns_adb_t *adb, int bucket, isc_stdtime_t now) {	dns_adbentry_t *entry, *next_entry;	isc_boolean_t result = ISC_FALSE;	DP(CLEAN_LEVEL, "cleaning entry bucket %d", bucket);	LOCK(&adb->entrylocks[bucket]);	entry = ISC_LIST_HEAD(adb->entries[bucket]);	while (entry != NULL) {		next_entry = ISC_LIST_NEXT(entry, plink);		INSIST(result == ISC_FALSE);		result = check_expire_entry(adb, &entry, now);		entry = next_entry;	}	UNLOCK(&adb->entrylocks[bucket]);	return (result);}static voidtimer_cleanup(isc_task_t *task, isc_event_t *ev) {	dns_adb_t *adb;	isc_stdtime_t now;	unsigned int i;	isc_interval_t interval;	UNUSED(task);	adb = ev->ev_arg;	INSIST(DNS_ADB_VALID(adb));	LOCK(&adb->lock);	isc_stdtime_get(&now);	for (i = 0; i < CLEAN_BUCKETS; i++) {		/*		 * Call our cleanup routines.		 */		RUNTIME_CHECK(cleanup_names(adb, adb->next_cleanbucket, now) ==			      ISC_FALSE);		RUNTIME_CHECK(cleanup_entries(adb, adb->next_cleanbucket, now)			      == ISC_FALSE);		/*		 * Set the next bucket to be cleaned.		 */		adb->next_cleanbucket++;		if (adb->next_cleanbucket >= NBUCKETS) {			adb->next_cleanbucket = 0;#ifdef DUMP_ADB_AFTER_CLEANING			dump_adb(adb, stdout, ISC_TRUE);#endif		}	}	/*	 * Reset the timer.	 * XXXDCL isc_timer_reset might return ISC_R_UNEXPECTED or	 * ISC_R_NOMEMORY, but it isn't clear what could be done here	 * if either one of those things happened.	 */	interval = adb->tick_interval;	if (adb->overmem)		isc_interval_set(&interval, 0, 1);	(void)isc_timer_reset(adb->timer, isc_timertype_once, NULL,			      &interval, ISC_FALSE);	UNLOCK(&adb->lock);	isc_event_free(&ev);}static voiddestroy(dns_adb_t *adb) {	adb->magic = 0;	/*	 * The timer is already dead, from the task's shutdown callback.	 */	isc_task_detach(&adb->task);	isc_mempool_destroy(&adb->nmp);	isc_mempool_destroy(&adb->nhmp);	isc_mempool_destroy(&adb->zimp);	isc_mempool_destroy(&adb->emp);	isc_mempool_destroy(&adb->ahmp);	isc_mempool_destroy(&adb->aimp);	isc_mempool_destroy(&adb->afmp);	DESTROYMUTEXBLOCK(adb->entrylocks, NBUCKETS);	DESTROYMUTEXBLOCK(adb->namelocks, NBUCKETS);	DESTROYLOCK(&adb->reflock);	DESTROYLOCK(&adb->lock);	DESTROYLOCK(&adb->mplock);	isc_mem_putanddetach(&adb->mctx, adb, sizeof(dns_adb_t));}/* * Public functions. */isc_result_tdns_adb_create(isc_mem_t *mem, dns_view_t *view, isc_timermgr_t *timermgr,	       isc_taskmgr_t *taskmgr, dns_adb_t **newadb){	dns_adb_t *adb;	isc_result_t result;	int i;	REQUIRE(mem != NULL);	REQUIRE(view != NULL);	REQUIRE(timermgr != NULL);	REQUIRE(taskmgr != NULL);	REQUIRE(newadb != NULL && *newadb == NULL);	adb = isc_mem_get(mem, sizeof(dns_adb_t));	if (adb == NULL)		return (ISC_R_NOMEMORY);	/*	 * Initialize things here that cannot fail, and especially things	 * that must be NULL for the error return to work properly.	 */	adb->magic = 0;	adb->erefcnt = 1;	adb->irefcnt = 0;	adb->nmp = NULL;	adb->nhmp = NULL;	adb->zimp = NULL;	adb->emp = NULL;	adb->ahmp = NULL;	adb->aimp = NULL;	adb->afmp = NULL;	adb->task = NULL;	adb->timer = NULL;	adb->mctx = NULL;	adb->view = view;	adb->timermgr = timermgr;	adb->taskmgr = taskmgr;	adb->next_cleanbucket = 0;	ISC_EVENT_INIT(&adb->cevent, sizeof(adb->cevent), 0, NULL,		       DNS_EVENT_ADBCONTROL, shutdown_task, adb,		       adb, NULL, NULL);	adb->cevent_sent = ISC_FALSE;	adb->shutting_down = ISC_FALSE;	adb->overmem = ISC_FALSE;	ISC_LIST_INIT(adb->whenshutdown);	isc_mem_attach(mem, &adb->mctx);	result = isc_mutex_init(&adb->lock);	if (result != ISC_R_SUCCESS)		goto fail0b;	result = isc_mutex_init(&adb->mplock);	if (result != ISC_R_SUCCESS)

⌨️ 快捷键说明

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