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

📄 adb.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	f->fetch = NULL;	f->namehook = new_adbnamehook(adb, NULL);	if (f->namehook == NULL)		goto err;	f->entry = new_adbentry(adb);	if (f->entry == NULL)		goto err;	dns_rdataset_init(&f->rdataset);	f->magic = DNS_ADBFETCH_MAGIC;	return (f); err:	if (f->namehook != NULL)		free_adbnamehook(adb, &f->namehook);	if (f->entry != NULL)		free_adbentry(adb, &f->entry);	isc_mempool_put(adb->afmp, f);	return (NULL);}static inline voidfree_adbfetch(dns_adb_t *adb, dns_adbfetch_t **fetch) {	dns_adbfetch_t *f;	INSIST(fetch != NULL && DNS_ADBFETCH_VALID(*fetch));	f = *fetch;	*fetch = NULL;	f->magic = 0;	if (f->namehook != NULL)		free_adbnamehook(adb, &f->namehook);	if (f->entry != NULL)		free_adbentry(adb, &f->entry);	if (dns_rdataset_isassociated(&f->rdataset))		dns_rdataset_disassociate(&f->rdataset);	isc_mempool_put(adb->afmp, f);}/* * Caller must be holding the name lock. */static isc_result_ta6find(void *arg, dns_name_t *a6name, dns_rdatatype_t type, isc_stdtime_t now,       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	dns_adbname_t *name;	dns_adb_t *adb;	isc_result_t result;	name = arg;	INSIST(DNS_ADBNAME_VALID(name));	adb = name->adb;	INSIST(DNS_ADB_VALID(adb));	result = dns_view_simplefind(adb->view, a6name, type, now,				     DNS_DBFIND_GLUEOK, ISC_FALSE,				     rdataset, sigrdataset);	if (result == DNS_R_GLUE)		result = ISC_R_SUCCESS;	return (result);}/* * Caller must be holding the name lock. */static voida6missing(dns_a6context_t *a6ctx, dns_name_t *a6name) {	dns_adbname_t *name;	dns_adb_t *adb;	dns_adbfetch6_t *fetch;	isc_result_t result;	name = a6ctx->arg;	INSIST(DNS_ADBNAME_VALID(name));	adb = name->adb;	INSIST(DNS_ADB_VALID(adb));	fetch = new_adbfetch6(adb, name, a6ctx);	if (fetch == NULL) {		name->partial_result |= DNS_ADBFIND_INET6;		return;	}	result = dns_resolver_createfetch(adb->view->resolver, a6name,					  dns_rdatatype_a6,					  NULL, NULL, NULL, 0,					  adb->task, fetch_callback_a6,					  name, &fetch->rdataset, NULL,					  &fetch->fetch);	if (result != ISC_R_SUCCESS)		goto cleanup;	name->chains = a6ctx->chains;	ISC_LIST_APPEND(name->fetches_a6, fetch, plink); cleanup:	if (result != ISC_R_SUCCESS) {		free_adbfetch6(adb, &fetch);		name->partial_result |= DNS_ADBFIND_INET6;	}}static inline dns_adbfetch6_t *new_adbfetch6(dns_adb_t *adb, dns_adbname_t *name, dns_a6context_t *a6ctx) {	dns_adbfetch6_t *f;	f = isc_mempool_get(adb->af6mp);	if (f == NULL)		return (NULL);	f->magic = 0;	f->namehook = NULL;	f->entry = NULL;	f->fetch = NULL;	f->flags = 0;	f->namehook = new_adbnamehook(adb, NULL);	if (f->namehook == NULL)		goto err;	f->entry = new_adbentry(adb);	if (f->entry == NULL)		goto err;	dns_rdataset_init(&f->rdataset);	dns_a6_init(&f->a6ctx, a6find, NULL, import_a6,		    a6missing, name);	if (a6ctx != NULL)		dns_a6_copy(a6ctx, &f->a6ctx);	ISC_LINK_INIT(f, plink);	f->magic = DNS_ADBFETCH6_MAGIC;	return (f); err:	if (f->namehook != NULL)		free_adbnamehook(adb, &f->namehook);	if (f->entry != NULL)		free_adbentry(adb, &f->entry);	isc_mempool_put(adb->af6mp, f);	return (NULL);}static inline voidfree_adbfetch6(dns_adb_t *adb, dns_adbfetch6_t **fetch) {	dns_adbfetch6_t *f;	INSIST(fetch != NULL && DNS_ADBFETCH6_VALID(*fetch));	f = *fetch;	*fetch = NULL;	f->magic = 0;	if (f->namehook != NULL)		free_adbnamehook(adb, &f->namehook);	if (f->entry != NULL)		free_adbentry(adb, &f->entry);	if (dns_rdataset_isassociated(&f->rdataset))		dns_rdataset_disassociate(&f->rdataset);	isc_mempool_put(adb->af6mp, f);}static inline isc_boolean_tfree_adbfind(dns_adb_t *adb, dns_adbfind_t **findp) {	dns_adbfind_t *find;	INSIST(findp != NULL && DNS_ADBFIND_VALID(*findp));	find = *findp;	*findp = NULL;	INSIST(!FIND_HAS_ADDRS(find));	INSIST(!ISC_LINK_LINKED(find, publink));	INSIST(!ISC_LINK_LINKED(find, plink));	INSIST(find->name_bucket == DNS_ADB_INVALIDBUCKET);	INSIST(find->adbname == NULL);	find->magic = 0;	DESTROYLOCK(&find->lock);	isc_mempool_put(adb->ahmp, find);	return (dec_adb_irefcnt(adb));}/* * Copy bits from the entry into the newly allocated addrinfo.  The entry * must be locked, and the reference count must be bumped up by one * if this function returns a valid pointer. */static inline dns_adbaddrinfo_t *new_adbaddrinfo(dns_adb_t *adb, dns_adbentry_t *entry, in_port_t port) {	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_fullname_hash(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 result = ISC_FALSE;	INSIST(entryp != NULL && DNS_ADBENTRY_VALID(*entryp));	entry = *entryp;	if (entry->refcnt != 0)		return (result);	if (entry->expires == 0 || 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) {

⌨️ 快捷键说明

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