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

📄 rbtdb.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	least_serial = rbtdb->least_serial;	UNLOCK(&rbtdb->lock);	if (cleanup_version != NULL)		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) {			next_changed = NEXT(changed, link);			rbtnode = changed->node;			lock = &rbtdb->node_locks[rbtnode->locknum].lock;			LOCK(lock);			INSIST(rbtnode->references > 0);			rbtnode->references--;			if (rollback)				rollback_node(rbtnode, serial);			if (rbtnode->references == 0)				no_references(rbtdb, rbtnode, least_serial,					      isc_rwlocktype_none);			UNLOCK(lock);			isc_mem_put(rbtdb->common.mctx, changed,				    sizeof *changed);		}	}	*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;	unsigned int locknum;	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);		}	}	locknum = node->locknum;	LOCK(&rbtdb->node_locks[locknum].lock);	new_reference(rbtdb, node);	UNLOCK(&rbtdb->node_locks[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;	LOCK(&(search->rbtdb->node_locks[node->locknum].lock));	/*	 * 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;	}	UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));	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;	/*	 * Caller must be holding the node lock.	 */	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;		/*	 * Reset iterator state.	 */	rdataset->privateuint4 = 0;	rdataset->private5 = NULL;}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_concatenate()	 * 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.		 */		*nodep = node;		search->need_cleanup = ISC_FALSE;	}	if (rdataset != NULL) {		LOCK(&(search->rbtdb->node_locks[node->locknum].lock));		bind_rdataset(search->rbtdb, node, search->zonecut_rdataset,			      search->now, rdataset);		if (sigrdataset != NULL && search->zonecut_sigrdataset != NULL)			bind_rdataset(search->rbtdb, node,				      search->zonecut_sigrdataset,				      search->now, sigrdataset);		UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));	}	if (type == dns_rdatatype_dname)		return (DNS_R_DNAME);	return (DNS_R_DELEGATION);}static inline isc_boolean_tvalid_glue(rbtdb_search_t *search, dns_name_t *name, rbtdb_rdatatype_t type,	   dns_rbtnode_t *node){	unsigned char *raw;	unsigned int count, size;	dns_name_t ns_name;	isc_boolean_t valid = ISC_FALSE;	dns_offsets_t offsets;	isc_region_t region;	rdatasetheader_t *header;	/*	 * No additional locking is required.	 */	/*	 * Valid glue types are A, AAAA, A6.  NS is also a valid glue type	 * if it occurs at a zone cut, but is not valid below it.	 */	if (type == dns_rdatatype_ns) {		if (node != search->zonecut) {			return (ISC_FALSE);		}	} else if (type != dns_rdatatype_a &&		   type != dns_rdatatype_aaaa &&		   type != dns_rdatatype_a6) {		return (ISC_FALSE);	}	header = search->zonecut_rdataset;	raw = (unsigned char *)header + sizeof *header;	count = raw[0] * 256 + raw[1];	raw += 2;	while (count > 0) {		count--;		size = raw[0] * 256 + raw[1];		raw += 2;		region.base = raw;		region.length = size;		raw += size;		/*		 * XXX Until we have rdata structures, we have no choice but		 * to directly access the rdata format.		 */		dns_name_init(&ns_name, offsets);		dns_name_fromregion(&ns_name, &region);		if (dns_name_compare(&ns_name, name) == 0) {			valid = ISC_TRUE;			break;		}	}	return (valid);}static inline isc_boolean_tactiveempty(rbtdb_search_t *search, dns_rbtnodechain_t *chain,	    dns_name_t *name){	dns_fixedname_t fnext;	dns_fixedname_t forigin;	dns_name_t *next;	dns_name_t *origin;	dns_name_t prefix;	dns_rbtdb_t *rbtdb;	dns_rbtnode_t *node;	isc_result_t result;	isc_boolean_t answer = ISC_FALSE;	rdatasetheader_t *header;	rbtdb = search->rbtdb;	dns_name_init(&prefix, NULL);	dns_fixedname_init(&fnext);	next = dns_fixedname_name(&fnext);	dns_fixedname_init(&forigin);	origin = dns_fixedname_name(&forigin);	result = dns_rbtnodechain_next(chain, NULL, NULL);	while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {		node = NULL;		result = dns_rbtnodechain_current(chain, &prefix,						  origin, &node);		if (result != ISC_R_SUCCESS)			break;		LOCK(&(rbtdb->node_locks[node->locknum].lock));		for (header = node->data;		     header != NULL;		     header = header->next) {			if (header->serial <= search->serial &&			    !IGNORE(header) && EXISTS(header))				break;		}		UNLOCK(&(rbtdb->node_locks[node->locknum].lock));		if (header != NULL)			break;		result = dns_rbtnodechain_next(chain, NULL, NULL);	}	if (result == ISC_R_SUCCESS)		result = dns_name_concatenate(&prefix, origin, next, NULL);	if (result == ISC_R_SUCCESS && dns_name_issubdomain(next, name))		answer = ISC_TRUE;	return (answer);}static inline isc_boolean_tactiveemtpynode(rbtdb_search_t *search, dns_name_t *qname, dns_name_t *wname) {

⌨️ 快捷键说明

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