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

📄 rbtdb.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	dns_fixedname_t fnext;	dns_fixedname_t forigin;	dns_fixedname_t fprev;	dns_name_t *next;	dns_name_t *origin;	dns_name_t *prev;	dns_name_t name;	dns_name_t rname;	dns_name_t tname;	dns_rbtdb_t *rbtdb;	dns_rbtnode_t *node;	dns_rbtnodechain_t chain;	isc_boolean_t check_next = ISC_TRUE;	isc_boolean_t check_prev = ISC_TRUE;	isc_boolean_t answer = ISC_FALSE;	isc_result_t result;	rdatasetheader_t *header;	unsigned int n;	rbtdb = search->rbtdb;	dns_name_init(&name, NULL);	dns_name_init(&tname, NULL);	dns_name_init(&rname, NULL);	dns_fixedname_init(&fnext);	next = dns_fixedname_name(&fnext);	dns_fixedname_init(&fprev);	prev = dns_fixedname_name(&fprev);	dns_fixedname_init(&forigin);	origin = dns_fixedname_name(&forigin);	/*	 * Find if qname is at or below a empty node.	 * Use our own copy of the chain.	 */	chain = search->chain;	do {		node = NULL;		result = dns_rbtnodechain_current(&chain, &name,						  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_prev(&chain, NULL, NULL);	} while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN);	if (result == ISC_R_SUCCESS)		result = dns_name_concatenate(&name, origin, prev, NULL);	if (result != ISC_R_SUCCESS)		check_prev = ISC_FALSE;	result = dns_rbtnodechain_next(&chain, NULL, NULL);	while (result == ISC_R_SUCCESS || result == DNS_R_NEWORIGIN) {		node = NULL;		result = dns_rbtnodechain_current(&chain, &name,						  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(&name, origin, next, NULL);	if (result != ISC_R_SUCCESS)		check_next = ISC_FALSE;	dns_name_clone(qname, &rname);	/*	 * Remove the wildcard label to find the terminal name.	 */	n = dns_name_countlabels(wname);	dns_name_getlabelsequence(wname, 1, n - 1, &tname);	do {		if ((check_prev && dns_name_issubdomain(prev, &rname)) ||		    (check_next && dns_name_issubdomain(next, &rname))) {			answer = ISC_TRUE;			break;		}		/*		 * Remove the left hand label.		 */		n = dns_name_countlabels(&rname);		dns_name_getlabelsequence(&rname, 1, n - 1, &rname);	} while (!dns_name_equal(&rname, &tname));	return (answer);}static inline isc_result_tfind_wildcard(rbtdb_search_t *search, dns_rbtnode_t **nodep,	      dns_name_t *qname){	unsigned int i, j;	dns_rbtnode_t *node, *level_node, *wnode;	rdatasetheader_t *header;	isc_result_t result = ISC_R_NOTFOUND;	dns_name_t name;	dns_name_t *wname;	dns_fixedname_t fwname;	dns_rbtdb_t *rbtdb;	isc_boolean_t done, wild, active;	dns_rbtnodechain_t wchain;	/*	 * Caller must be holding the tree lock and MUST NOT be holding	 * any node locks.	 */	/*	 * Examine each ancestor level.  If the level's wild bit	 * is set, then construct the corresponding wildcard name and	 * search for it.  If the wildcard node exists, and is active in	 * this version, we're done.  If not, then we next check to see	 * if the ancestor is active in this version.  If so, then there	 * can be no possible wildcard match and again we're done.  If not,	 * continue the search.	 */	rbtdb = search->rbtdb;	i = search->chain.level_matches;	done = ISC_FALSE;	node = *nodep;	do {		LOCK(&(rbtdb->node_locks[node->locknum].lock));		/*		 * First we try to figure out if this node is active in		 * the search's version.  We do this now, even though we		 * may not need the information, because it simplifies the		 * locking and code flow.		 */		for (header = node->data;		     header != NULL;		     header = header->next) {			if (header->serial <= search->serial &&			    !IGNORE(header) && EXISTS(header))				break;		}		if (header != NULL)			active = ISC_TRUE;		else			active = ISC_FALSE;		if (node->wild)			wild = ISC_TRUE;		else			wild = ISC_FALSE;		UNLOCK(&(rbtdb->node_locks[node->locknum].lock));		if (wild) {			/*			 * Construct the wildcard name for this level.			 */			dns_name_init(&name, NULL);			dns_rbt_namefromnode(node, &name);			dns_fixedname_init(&fwname);			wname = dns_fixedname_name(&fwname);			result = dns_name_concatenate(dns_wildcardname, &name,						      wname, NULL);			j = i;			while (result == ISC_R_SUCCESS && j != 0) {				j--;				level_node = search->chain.levels[j];				dns_name_init(&name, NULL);				dns_rbt_namefromnode(level_node, &name);				result = dns_name_concatenate(wname,							      &name,							      wname,							      NULL);			}			if (result != ISC_R_SUCCESS)				break;			wnode = NULL;			dns_rbtnodechain_init(&wchain, NULL);			result = dns_rbt_findnode(rbtdb->tree, wname,						  NULL, &wnode, &wchain,						  DNS_RBTFIND_EMPTYDATA,						  NULL, NULL);			if (result == ISC_R_SUCCESS) {			    /*			     * We have found the wildcard node.  If it			     * is active in the search's version, we're			     * done.			     */			    LOCK(&(rbtdb->node_locks[wnode->locknum].lock));			    for (header = wnode->data;				 header != NULL;				 header = header->next) {				    if (header->serial <= search->serial &&					!IGNORE(header) && EXISTS(header))					    break;			    }			    UNLOCK(&(rbtdb->node_locks[wnode->locknum].lock));			    if (header != NULL ||				activeempty(search, &wchain, wname)) {				    if (activeemtpynode(search, qname, wname))						return (ISC_R_NOTFOUND);				    /*				     * The wildcard node is active!				     *				     * Note: result is still ISC_R_SUCCESS				     * so we don't have to set it.				     */				    *nodep = wnode;				    break;			    }			} else if (result != ISC_R_NOTFOUND &&				   result != DNS_R_PARTIALMATCH) {				/*				 * An error has occurred.  Bail out.				 */				break;			}		}		if (active) {			/*			 * The level node is active.  Any wildcarding			 * present at higher levels has no			 * effect and we're done.			 */			result = ISC_R_NOTFOUND;			break;		}		if (i > 0) {			i--;			node = search->chain.levels[i];		} else			done = ISC_TRUE;	} while (!done);	return (result);}static inline isc_result_tfind_closest_nxt(rbtdb_search_t *search, dns_dbnode_t **nodep,		 dns_name_t *foundname, dns_rdataset_t *rdataset,		 dns_rdataset_t *sigrdataset){	dns_rbtnode_t *node;	rdatasetheader_t *header, *header_next, *found, *foundsig;	isc_boolean_t empty_node;	isc_result_t result;	dns_fixedname_t fname, forigin;	dns_name_t *name, *origin;	do {		node = NULL;		dns_fixedname_init(&fname);		name = dns_fixedname_name(&fname);		dns_fixedname_init(&forigin);		origin = dns_fixedname_name(&forigin);		result = dns_rbtnodechain_current(&search->chain, name,						  origin, &node);		if (result != ISC_R_SUCCESS)			return (result);		LOCK(&(search->rbtdb->node_locks[node->locknum].lock));		found = NULL;		foundsig = NULL;		empty_node = ISC_TRUE;		for (header = node->data;		     header != NULL;		     header = header_next) {			header_next = header->next;			/*			 * Look for an active, extant NXT or SIG NXT.			 */			do {				if (header->serial <= search->serial &&				    !IGNORE(header)) {					/*					 * Is this a "this rdataset doesn't					 * exist" record?					 */					if ((header->attributes &					     RDATASET_ATTR_NONEXISTENT) != 0)						header = NULL;					break;				} else					header = header->down;			} while (header != NULL);			if (header != NULL) {				/*				 * We now know that there is at least one				 * active rdataset at this node.				 */				empty_node = ISC_FALSE;				if (header->type == dns_rdatatype_nxt) {					found = header;					if (foundsig != NULL)						break;				} else if (header->type ==					   RBTDB_RDATATYPE_SIGNXT) {					foundsig = header;					if (found != NULL)						break;				}			}		}		if (!empty_node) {			if (found != NULL && foundsig != NULL) {				/*				 * We've found the right NXT record.				 *				 * Note: for this to really be the right				 * NXT record, it's essential that the NXT				 * records of any nodes obscured by a zone				 * cut have been removed; we assume this is				 * the case.				 */				result = dns_name_concatenate(name, origin,							      foundname, NULL);				if (result == ISC_R_SUCCESS) {					if (nodep != NULL) {						new_reference(search->rbtdb,							      node);						*nodep = node;					}					bind_rdataset(search->rbtdb, node,						      found, search->now,						      rdataset);					bind_rdataset(search->rbtdb, node,						      foundsig, search->now,						      sigrdataset);				}			} else if (found == NULL && foundsig == NULL) {				/*				 * This node is active, but has no NXT or				 * SIG NXT.  That means it's glue or				 * other obscured zone data that isn't				 * relevant for our search.  Treat the				 * node as if it were empty and keep looking.				 */				empty_node = ISC_TRUE;				result = dns_rbtnodechain_prev(&search->chain,							       NULL, NULL);			} else {				/*				 * We found an active node, but either the				 * NXT or the SIG NXT is missing.  This				 * shouldn't happen.				 */				result = DNS_R_BADDB;			}		} else {			/*			 * This node isn't active.  We've got to keep			 * looking.			 */			result = dns_rbtnodechain_prev(&search->chain, NULL,						       NULL);		}		UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));	} while (empty_node && result == ISC_R_SUCCESS);	/*	 * If the result is ISC_R_NOMORE, then we got to the beginning of	 * the database and didn't find a NXT record.  This shouldn't	 * happen.	 */	if (result == ISC_R_NOMORE)		result = DNS_R_BADDB;	return (result);}static isc_result_tzone_find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,	  dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,	  dns_dbnode_t **nodep, dns_name_t *foundname,	  dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	dns_rbtnode_t *node = NULL;	isc_result_t result;	rbtdb_search_t search;	isc_boolean_t cname_ok = ISC_TRUE;	isc_boolean_t close_version = ISC_FALSE;	isc_boolean_t maybe_zonecut = ISC_FALSE;	isc_boolean_t at_zonecut = ISC_FALSE;	isc_boolean_t wild;	isc_boolean_t empty_node;	isc_mutex_t *lock;	rdatasetheader_t *header, *header_next, *found, *nxtheader;	rdatasetheader_t *foundsig, *cnamesig, *nxtsig;	rbtdb_rdatatype_t sigtype;	isc_boolean_t active;	dns_rbtnodechain_t chain;	search.rbtdb = (dns_rbtdb_t *)db;	REQUIRE(VALID_RBTDB(search.rbtdb));	/*	 * We don't care about 'now'.	 */	UNUSED(now);	/*	 * If the caller didn't supply a version, attach to the current	 * version.	 */	if (version == NULL) {		currentversion(db, &version);		close_version = ISC_TRUE;	}	search.rbtversion = version;	search.serial = search.rbtversion->serial;	search.options = options;	search.copy_name = ISC_FALSE;	search.need_cleanup = ISC_FALSE;	search.wild = ISC_FALSE;	search.zonecut = NULL;	dns_fixedname_init(&search.zonecut_name);	dns_rbtnodechain_init(&search.chain, search.rbtdb->common.mctx);	search.now = 0;	/*	 * 'wild' will be true iff. we've matched a wildcard.	 */	wild = ISC_FALSE;	RWLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);	/*	 * Search down from the root of the tree.  If, while going down, we	 * encounter a callback node, zone_zonecut_callback() will search the	 * rdatasets at the zone cut for active DNAME or NS rdatasets.	 */	result = dns_rbt_findnode(search.rbtdb->tree, name, foundname, &node,				  &search.chain, DNS_RBTFIND_EMPTYDATA,				  zone_zonecut_callback, &search);	if (result == DNS_R_PARTIALMATCH) {	partial_match:		if (search.zonecut != NULL) {		    result = setup_delegation(&search, nodep, foundname,					      rdataset, sigrdataset);		    goto tree_exit;		}		if (search.wild) {			/*			 * At least one of the levels in the search chain			 * potentially has a wildcard.  For each such level,			 * we must see if there's a matching wildcard active			 * in the current version.			 */			result = find_wildcard(&search, &node, name);			if (result == ISC_R_SUCCESS) {				result = dns_name_copy(name, foundname, NULL);				if (result != ISC_R_SUCCESS)					goto tree_exit;				wild = ISC_TRUE;				goto found;			}			else if (result != ISC_R_NOTFOUND)				goto tree_exit;		}		chain = search.chain;		active = activeempty(&search, &chain, name);		/*		 * If we're here, then the name does not exist, is not		 * beneath a zonecut, and there's no matching wildcard.		 */		if (search.rbtdb->secure) {			result = find_closest_nxt(&search, nodep, foundname,						  rdataset, sigrdataset);			if (result == ISC_R_SUCCESS)				result = active ? DNS_R_EMPTYNAME :						  DNS_R_NXDOMAIN;		} else			result = active ? DNS_R_EMPTYNAME : DNS_R_NXDOMAIN;		goto tree_exit;	} else if (result != ISC_R_SUCCESS)		goto tree_exit;

⌨️ 快捷键说明

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