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

📄 rbtdb.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
				cleanup_nondirty(version, &cleanup_list);			}			/*			 * If the (soon to be former) current version			 * isn't being used by anyone, we can clean			 * it up.			 */			if (cur_ref == 0) {				cleanup_version = cur_version;				APPENDLIST(version->changed_list,					   cleanup_version->changed_list,					   link);			}			/*			 * Become the current version.			 */			version->writer = ISC_FALSE;			rbtdb->current_version = version;			rbtdb->current_serial = version->serial;			rbtdb->future_version = NULL;			/*			 * Keep the current version in the open list, and			 * gain a reference for the DB itself (see the DB			 * creation function below).  This must be the only			 * case where we need to increment the counter from			 * zero and need to use isc_refcount_increment0().			 */			isc_refcount_increment0(&version->references,						&cur_ref);			INSIST(cur_ref == 1);			PREPEND(rbtdb->open_versions,				rbtdb->current_version, link);		} else {			/*			 * We're rolling back this transaction.			 */			cleanup_list = version->changed_list;			ISC_LIST_INIT(version->changed_list);			rollback = ISC_TRUE;			cleanup_version = version;			rbtdb->future_version = NULL;		}	} else {		if (version != rbtdb->current_version) {			/*			 * There are no external or internal references			 * to this version and it can be cleaned up.			 */			cleanup_version = version;			/*			 * Find the version with the least serial			 * number greater than ours.			 */			least_greater = PREV(version, link);			if (least_greater == NULL)				least_greater = rbtdb->current_version;			INSIST(version->serial < least_greater->serial);			/*			 * Is this the least open version?			 */			if (version->serial == rbtdb->least_serial) {				/*				 * Yes.  Install the new least open				 * version.				 */				make_least_version(rbtdb,						   least_greater,						   &cleanup_list);			} else {				/*				 * Add any unexecuted cleanups to				 * those of the least greater version.				 */				APPENDLIST(least_greater->changed_list,					   version->changed_list,					   link);			}		} else if (version->serial == rbtdb->least_serial)			INSIST(EMPTY(version->changed_list));		UNLINK(rbtdb->open_versions, version, link);	}	least_serial = rbtdb->least_serial;	RBTDB_UNLOCK(&rbtdb->lock, isc_rwlocktype_write);	/*	 * Update the zone's secure status.	 */	if (version->writer && commit && !IS_CACHE(rbtdb))		rbtdb->secure = iszonesecure(db, rbtdb->origin_node);	if (cleanup_version != NULL) {		INSIST(EMPTY(cleanup_version->changed_list));		isc_mem_put(rbtdb->common.mctx, cleanup_version,			    sizeof(*cleanup_version));	}	if (!EMPTY(cleanup_list)) {		for (changed = HEAD(cleanup_list);		     changed != NULL;		     changed = next_changed) {			nodelock_t *lock;			next_changed = NEXT(changed, link);			rbtnode = changed->node;			lock = &rbtdb->node_locks[rbtnode->locknum].lock;			NODE_LOCK(lock, isc_rwlocktype_write);			if (rollback)				rollback_node(rbtnode, serial);			decrement_reference(rbtdb, rbtnode, least_serial,					    isc_rwlocktype_write,					    isc_rwlocktype_none);			NODE_UNLOCK(lock, isc_rwlocktype_write);			isc_mem_put(rbtdb->common.mctx, changed,				    sizeof(*changed));		}	}  end:	*versionp = NULL;}/* * Add the necessary magic for the wildcard name 'name' * to be found in 'rbtdb'. * * In order for wildcard matching to work correctly in * zone_find(), we must ensure that a node for the wildcarding * level exists in the database, and has its 'find_callback' * and 'wild' bits set. * * E.g. if the wildcard name is "*.sub.example." then we * must ensure that "sub.example." exists and is marked as * a wildcard level. */static isc_result_tadd_wildcard_magic(dns_rbtdb_t *rbtdb, dns_name_t *name) {	isc_result_t result;	dns_name_t foundname;	dns_offsets_t offsets;	unsigned int n;	dns_rbtnode_t *node = NULL;	dns_name_init(&foundname, offsets);	n = dns_name_countlabels(name);	INSIST(n >= 2);	n--;	dns_name_getlabelsequence(name, 1, n, &foundname);	result = dns_rbt_addnode(rbtdb->tree, &foundname, &node);	if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)		return (result);	node->find_callback = 1;	node->wild = 1;	return (ISC_R_SUCCESS);}static isc_result_tadd_empty_wildcards(dns_rbtdb_t *rbtdb, dns_name_t *name) {	isc_result_t result;	dns_name_t foundname;	dns_offsets_t offsets;	unsigned int n, l, i;	dns_name_init(&foundname, offsets);	n = dns_name_countlabels(name);	l = dns_name_countlabels(&rbtdb->common.origin);	i = l + 1;	while (i < n) {		dns_rbtnode_t *node = NULL;	/* dummy */		dns_name_getlabelsequence(name, n - i, i, &foundname);		if (dns_name_iswildcard(&foundname)) {			result = add_wildcard_magic(rbtdb, &foundname);			if (result != ISC_R_SUCCESS)				return (result);			result = dns_rbt_addnode(rbtdb->tree, &foundname,						 &node);			if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS)				return (result);		}		i++;	}	return (ISC_R_SUCCESS);}static isc_result_tfindnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,	 dns_dbnode_t **nodep){	dns_rbtdb_t *rbtdb = (dns_rbtdb_t *)db;	dns_rbtnode_t *node = NULL;	dns_name_t nodename;	isc_result_t result;	isc_rwlocktype_t locktype = isc_rwlocktype_read;	REQUIRE(VALID_RBTDB(rbtdb));	dns_name_init(&nodename, NULL);	RWLOCK(&rbtdb->tree_lock, locktype);	result = dns_rbt_findnode(rbtdb->tree, name, NULL, &node, NULL,				  DNS_RBTFIND_EMPTYDATA, NULL, NULL);	if (result != ISC_R_SUCCESS) {		RWUNLOCK(&rbtdb->tree_lock, locktype);		if (!create) {			if (result == DNS_R_PARTIALMATCH)				result = ISC_R_NOTFOUND;			return (result);		}		/*		 * It would be nice to try to upgrade the lock instead of		 * unlocking then relocking.		 */		locktype = isc_rwlocktype_write;		RWLOCK(&rbtdb->tree_lock, locktype);		node = NULL;		result = dns_rbt_addnode(rbtdb->tree, name, &node);		if (result == ISC_R_SUCCESS) {			dns_rbt_namefromnode(node, &nodename);#ifdef DNS_RBT_USEHASH			node->locknum = node->hashval % rbtdb->node_lock_count;#else			node->locknum = dns_name_hash(&nodename, ISC_TRUE) %				rbtdb->node_lock_count;#endif			add_empty_wildcards(rbtdb, name);			if (dns_name_iswildcard(name)) {				result = add_wildcard_magic(rbtdb, name);				if (result != ISC_R_SUCCESS) {					RWUNLOCK(&rbtdb->tree_lock, locktype);					return (result);				}			}		} else if (result != ISC_R_EXISTS) {			RWUNLOCK(&rbtdb->tree_lock, locktype);			return (result);		}	}	NODE_STRONGLOCK(&rbtdb->node_locks[node->locknum].lock);	new_reference(rbtdb, node);	NODE_STRONGUNLOCK(&rbtdb->node_locks[node->locknum].lock);	RWUNLOCK(&rbtdb->tree_lock, locktype);	*nodep = (dns_dbnode_t *)node;	return (ISC_R_SUCCESS);}static isc_result_tzone_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {	rbtdb_search_t *search = arg;	rdatasetheader_t *header, *header_next;	rdatasetheader_t *dname_header, *sigdname_header, *ns_header;	rdatasetheader_t *found;	isc_result_t result;	dns_rbtnode_t *onode;	/*	 * We only want to remember the topmost zone cut, since it's the one	 * that counts, so we'll just continue if we've already found a	 * zonecut.	 */	if (search->zonecut != NULL)		return (DNS_R_CONTINUE);	found = NULL;	result = DNS_R_CONTINUE;	onode = search->rbtdb->origin_node;	NODE_LOCK(&(search->rbtdb->node_locks[node->locknum].lock),		  isc_rwlocktype_read);	/*	 * Look for an NS or DNAME rdataset active in our version.	 */	ns_header = NULL;	dname_header = NULL;	sigdname_header = NULL;	for (header = node->data; header != NULL; header = header_next) {		header_next = header->next;		if (header->type == dns_rdatatype_ns ||		    header->type == dns_rdatatype_dname ||		    header->type == RBTDB_RDATATYPE_SIGDNAME) {			do {				if (header->serial <= search->serial &&				    !IGNORE(header)) {					/*					 * Is this a "this rdataset doesn't					 * exist" record?					 */					if (NONEXISTENT(header))						header = NULL;					break;				} else					header = header->down;			} while (header != NULL);			if (header != NULL) {				if (header->type == dns_rdatatype_dname)					dname_header = header;				else if (header->type == 					   RBTDB_RDATATYPE_SIGDNAME)					sigdname_header = header;				else if (node != onode ||					 IS_STUB(search->rbtdb)) {					/*					 * We've found an NS rdataset that					 * isn't at the origin node.  We check					 * that they're not at the origin node,					 * because otherwise we'd erroneously					 * treat the zone top as if it were					 * a delegation.					 */					ns_header = header;				}			}		}	}	/*	 * Did we find anything?	 */	if (dname_header != NULL) {		/*		 * Note that DNAME has precedence over NS if both exist.		 */		found = dname_header;		search->zonecut_sigrdataset = sigdname_header;	} else if (ns_header != NULL) {		found = ns_header;		search->zonecut_sigrdataset = NULL;	}	if (found != NULL) {		/*		 * We increment the reference count on node to ensure that		 * search->zonecut_rdataset will still be valid later.		 */		new_reference(search->rbtdb, node);		search->zonecut = node;		search->zonecut_rdataset = found;		search->need_cleanup = ISC_TRUE;		/*		 * Since we've found a zonecut, anything beneath it is		 * glue and is not subject to wildcard matching, so we		 * may clear search->wild.		 */		search->wild = ISC_FALSE;		if ((search->options & DNS_DBFIND_GLUEOK) == 0) {			/*			 * If the caller does not want to find glue, then			 * this is the best answer and the search should			 * stop now.			 */			result = DNS_R_PARTIALMATCH;		} else {			dns_name_t *zcname;			/*			 * The search will continue beneath the zone cut.			 * This may or may not be the best match.  In case it			 * is, we need to remember the node name.			 */			zcname = dns_fixedname_name(&search->zonecut_name);			RUNTIME_CHECK(dns_name_copy(name, zcname, NULL) ==				      ISC_R_SUCCESS);			search->copy_name = ISC_TRUE;		}	} else {		/*		 * There is no zonecut at this node which is active in this		 * version.		 *		 * If this is a "wild" node and the caller hasn't disabled		 * wildcard matching, remember that we've seen a wild node		 * in case we need to go searching for wildcard matches		 * later on.		 */		if (node->wild && (search->options & DNS_DBFIND_NOWILD) == 0)			search->wild = ISC_TRUE;	}	NODE_UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock),		    isc_rwlocktype_read);	return (result);}static inline voidbind_rdataset(dns_rbtdb_t *rbtdb, dns_rbtnode_t *node,	      rdatasetheader_t *header, isc_stdtime_t now,	      dns_rdataset_t *rdataset){	unsigned char *raw;	/* RDATASLAB */	/*	 * Caller must be holding the node reader lock.	 * XXXJT: technically, we need a writer lock, since we'll increment	 * the header count below.  However, since the actual counter value	 * doesn't matter, we prioritize performance here.  (We may want to	 * use atomic increment when available).	 */	if (rdataset == NULL)		return;	new_reference(rbtdb, node);	INSIST(rdataset->methods == NULL);	/* We must be disassociated. */	rdataset->methods = &rdataset_methods;	rdataset->rdclass = rbtdb->common.rdclass;	rdataset->type = RBTDB_RDATATYPE_BASE(header->type);	rdataset->covers = RBTDB_RDATATYPE_EXT(header->type);	rdataset->ttl = header->ttl - now;	rdataset->trust = header->trust;	if (NXDOMAIN(header))		rdataset->attributes |= DNS_RDATASETATTR_NXDOMAIN;	rdataset->private1 = rbtdb;	rdataset->private2 = node;	raw = (unsigned char *)header + sizeof(*header);	rdataset->private3 = raw;	rdataset->count = header->count++;	if (header->count == ISC_UINT32_MAX)		header->count = 0;	/*	 * Reset iterator state.	 */	rdataset->privateuint4 = 0;	rdataset->private5 = NULL;	/*	 * Add noqname proof.	 */	rdataset->private6 = header->noqname;	if (rdataset->private6 != NULL)		rdataset->attributes |=  DNS_RDATASETATTR_NOQNAME;}static inline isc_result_tsetup_delegation(rbtdb_search_t *search, dns_dbnode_t **nodep,		 dns_name_t *foundname, dns_rdataset_t *rdataset,		 dns_rdataset_t *sigrdataset){	isc_result_t result;	dns_name_t *zcname;	rbtdb_rdatatype_t type;	dns_rbtnode_t *node;	/*	 * The caller MUST NOT be holding any node locks.	 */	node = search->zonecut;	type = search->zonecut_rdataset->type;	/*	 * If we have to set foundname, we do it before anything else.	 * If we were to set foundname after we had set nodep or bound the	 * rdataset, then we'd have to undo that work if dns_name_copy()	 * failed.  By setting foundname first, there's nothing to undo if	 * we have trouble.	 */	if (foundname != NULL && search->copy_name) {		zcname = dns_fixedname_name(&search->zonecut_name);		result = dns_name_copy(zcname, foundname, NULL);		if (result != ISC_R_SUCCESS)			return (result);	}	if (nodep != NULL) {		/*		 * Note that we don't have to increment the node's reference		 * count here because we're going to use the reference we		 * already have in the search block.		 */

⌨️ 快捷键说明

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