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

📄 rbtdb.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
 found:	/*	 * We have found a node whose name is the desired name, or we	 * have matched a wildcard.	 */	if (search.zonecut != NULL) {		/*		 * If we're beneath a zone cut, we don't want to look for		 * CNAMEs because they're not legitimate zone glue.		 */		cname_ok = ISC_FALSE;	} else {		/*		 * The node may be a zone cut itself.  If it might be one,		 * make sure we check for it later.		 */		if (node->find_callback &&		    (node != search.rbtdb->origin_node ||		     IS_STUB(search.rbtdb)))			maybe_zonecut = ISC_TRUE;	}	/*	 * Certain DNSSEC types are not subject to CNAME matching	 * (RFC 2535, section 2.3.5).	 *	 * We don't check for SIG, because we don't store SIG records	 * directly.	 */	if (type == dns_rdatatype_key || type == dns_rdatatype_nxt)		cname_ok = ISC_FALSE;	/*	 * We now go looking for rdata...	 */	LOCK(&(search.rbtdb->node_locks[node->locknum].lock));	found = NULL;	foundsig = NULL;	sigtype = RBTDB_RDATATYPE_VALUE(dns_rdatatype_sig, type);	nxtheader = NULL;	nxtsig = NULL;	cnamesig = NULL;	empty_node = ISC_TRUE;	for (header = node->data; header != NULL; header = header_next) {		header_next = header->next;		/*		 * Look for an active, extant rdataset.		 */		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;			/*			 * Do special zone cut handling, if requested.			 */			if (maybe_zonecut &&			    header->type == dns_rdatatype_ns) {				/*				 * 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 = header;				search.zonecut_sigrdataset = NULL;				search.need_cleanup = ISC_TRUE;				maybe_zonecut = ISC_FALSE;				at_zonecut = ISC_TRUE;				if ((search.options & DNS_DBFIND_GLUEOK) == 0				    && type != dns_rdatatype_nxt				    && type != dns_rdatatype_key) {					/*					 * Glue is not OK, but any answer we					 * could return would be glue.  Return					 * the delegation.					 */					found = NULL;					break;				}				if (found != NULL && foundsig != NULL)					break;			}			/*			 * If we found a type we were looking for,			 * remember it.			 */			if (header->type == type ||			    type == dns_rdatatype_any ||			    (header->type == dns_rdatatype_cname &&			     cname_ok)) {				/*				 * We've found the answer!				 */				found = header;				if (header->type == dns_rdatatype_cname &&				    cname_ok) {					/*					 * We may be finding a CNAME instead					 * of the desired type.					 *					 * If we've already got the CNAME SIG,					 * use it, otherwise change sigtype					 * so that we find it.					 */					if (cnamesig != NULL)						foundsig = cnamesig;					else						sigtype =						    RBTDB_RDATATYPE_SIGCNAME;				}				/*				 * If we've got all we need, end the search.				 */				if (!maybe_zonecut && foundsig != NULL)					break;			} else if (header->type == sigtype) {				/*				 * We've found the SIG rdataset for our				 * target type.  Remember it.				 */				foundsig = header;				/*				 * If we've got all we need, end the search.				 */				if (!maybe_zonecut && found != NULL)					break;			} else if (header->type == dns_rdatatype_nxt) {				/*				 * Remember a NXT rdataset even if we're				 * not specifically looking for it, because				 * we might need it later.				 */				nxtheader = header;			} else if (header->type == RBTDB_RDATATYPE_SIGNXT) {				/*				 * If we need the NXT rdataset, we'll also				 * need its signature.				 */				nxtsig = header;			} else if (cname_ok &&				   header->type == RBTDB_RDATATYPE_SIGCNAME) {				/*				 * If we get a CNAME match, we'll also need				 * its signature.				 */				cnamesig = header;			}		}	}	if (empty_node) {		/*		 * We have an exact match for the name, but there are no		 * active rdatasets in the desired version.  That means that		 * this node doesn't exist in the desired version, and that		 * we really have a partial match.		 */		if (!wild) {			UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));			goto partial_match;		}	}	/*	 * If we didn't find what we were looking for...	 */	if (found == NULL) {		if (search.zonecut != NULL) {		    /*		     * We were trying to find glue at a node beneath a		     * zone cut, but didn't.		     *		     * Return the delegation.		     */		    UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));		    result = setup_delegation(&search, nodep, foundname,					      rdataset, sigrdataset);		    goto tree_exit;		}		/*		 * The desired type doesn't exist.		 */		result = DNS_R_NXRRSET;		if (search.rbtdb->secure &&		    (nxtheader == NULL || nxtsig == NULL)) {			/*			 * The zone is secure but there's no NXT,			 * or the NXT has no signature!			 */			if (!wild) {				result = DNS_R_BADDB;				goto node_exit;			}			UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));			result = find_closest_nxt(&search, nodep, foundname,						  rdataset, sigrdataset);			if (result == ISC_R_SUCCESS)				result = DNS_R_EMPTYWILD;			goto tree_exit;		}		if (nodep != NULL) {			new_reference(search.rbtdb, node);			*nodep = node;		}		if (search.rbtdb->secure) {			bind_rdataset(search.rbtdb, node, nxtheader,				      0, rdataset);			bind_rdataset(search.rbtdb, node, nxtsig,				      0, sigrdataset);		}		goto node_exit;	}	/*	 * We found what we were looking for, or we found a CNAME.	 */	if (type != found->type &&	    type != dns_rdatatype_any &&	    found->type == dns_rdatatype_cname) {		/*		 * We weren't doing an ANY query and we found a CNAME instead		 * of the type we were looking for, so we need to indicate		 * that result to the caller.		 */		result = DNS_R_CNAME;	} else if (search.zonecut != NULL) {		/*		 * If we're beneath a zone cut, we must indicate that the		 * result is glue, unless we're actually at the zone cut		 * and the type is NXT or KEY.		 */		if (search.zonecut == node) {			if (type == dns_rdatatype_nxt ||			    type == dns_rdatatype_key)				result = ISC_R_SUCCESS;			else if (type == dns_rdatatype_any)				result = DNS_R_ZONECUT;			else				result = DNS_R_GLUE;		} else			result = DNS_R_GLUE;		/*		 * We might have found data that isn't glue, but was occluded		 * by a dynamic update.  If the caller cares about this, they		 * will have told us to validate glue.		 *		 * XXX We should cache the glue validity state!		 */		if (result == DNS_R_GLUE &&		    (search.options & DNS_DBFIND_VALIDATEGLUE) != 0 &&		    !valid_glue(&search, foundname, type, node)) {		    UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock));		    result = setup_delegation(&search, nodep, foundname,					      rdataset, sigrdataset);		    goto tree_exit;		}	} else {		/*		 * An ordinary successful query!		 */		result = ISC_R_SUCCESS;	}	if (nodep != NULL) {		if (!at_zonecut)			new_reference(search.rbtdb, node);		else			search.need_cleanup = ISC_FALSE;		*nodep = node;	}	if (type != dns_rdatatype_any) {		bind_rdataset(search.rbtdb, node, found, 0, rdataset);		if (foundsig != NULL)			bind_rdataset(search.rbtdb, node, foundsig, 0,				      sigrdataset);	} node_exit:	UNLOCK(&(search.rbtdb->node_locks[node->locknum].lock)); tree_exit:	RWUNLOCK(&search.rbtdb->tree_lock, isc_rwlocktype_read);	/*	 * If we found a zonecut but aren't going to use it, we have to	 * let go of it.	 */	if (search.need_cleanup) {		node = search.zonecut;		lock = &(search.rbtdb->node_locks[node->locknum].lock);		LOCK(lock);		INSIST(node->references > 0);		node->references--;		if (node->references == 0)			no_references(search.rbtdb, node, 0,				      isc_rwlocktype_none);		UNLOCK(lock);	}	if (close_version)		closeversion(db, &version, ISC_FALSE);	dns_rbtnodechain_reset(&search.chain);	return (result);}static isc_result_tzone_findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,		 isc_stdtime_t now, dns_dbnode_t **nodep,		 dns_name_t *foundname,		 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	UNUSED(db);	UNUSED(name);	UNUSED(options);	UNUSED(now);	UNUSED(nodep);	UNUSED(foundname);	UNUSED(rdataset);	UNUSED(sigrdataset);	FATAL_ERROR(__FILE__, __LINE__, "zone_findzonecut() called!");	return (ISC_R_NOTIMPLEMENTED);}static isc_result_tcache_zonecut_callback(dns_rbtnode_t *node, dns_name_t *name, void *arg) {	rbtdb_search_t *search = arg;	rdatasetheader_t *header, *header_prev, *header_next;	rdatasetheader_t *dname_header, *sigdname_header;	isc_result_t result;	/* XXX comment */	REQUIRE(search->zonecut == NULL);	/*	 * Keep compiler silent.	 */	UNUSED(name);	LOCK(&(search->rbtdb->node_locks[node->locknum].lock));	/*	 * Look for a DNAME or SIG DNAME rdataset.	 */	dname_header = NULL;	sigdname_header = NULL;	header_prev = NULL;	for (header = node->data; header != NULL; header = header_next) {		header_next = header->next;		if (header->ttl <= search->now) {			/*			 * This rdataset is stale.  If no one else is			 * using the node, we can clean it up right			 * now, otherwise we mark it as stale, and			 * the node as dirty, so it will get cleaned			 * up later.			 */			if (node->references == 0) {				INSIST(header->down == NULL);				if (header_prev != NULL)					header_prev->next =						header->next;				else					node->data = header->next;				free_rdataset(search->rbtdb->common.mctx,					      header);			} else {				header->attributes |=					RDATASET_ATTR_STALE;				node->dirty = 1;				header_prev = header;			}		} else if (header->type == dns_rdatatype_dname &&			   EXISTS(header)) {			dname_header = header;			header_prev = header;		} else if (header->type == RBTDB_RDATATYPE_SIGDNAME &&			 EXISTS(header)) {			sigdname_header = header;			header_prev = header;		} else			header_prev = header;	}	if (dname_header != NULL &&	    (dname_header->trust != dns_trust_pending ||	     (search->options & DNS_DBFIND_PENDINGOK) != 0)) {		/*		 * 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 = dname_header;		search->zonecut_sigrdataset = sigdname_header;		search->need_cleanup = ISC_TRUE;		result = DNS_R_PARTIALMATCH;	} else		result = DNS_R_CONTINUE;	UNLOCK(&(search->rbtdb->node_locks[node->locknum].lock));	return (result);}static inline isc_result_tfind_deepest_zonecut(rbtdb_search_t *search, dns_rbtnode_t *node,		     dns_dbnode_t **nodep, dns_name_t *foundname,		     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	unsigned int i;	dns_rbtnode_t *level_node;	rdatasetheader_t *header, *header_prev, *header_next;	rdatasetheader_t *found, *foundsig;	isc_result_t result = ISC_R_NOTFOUND;	dns_name_t name;	dns_rbtdb_t *rbtdb;	isc_boolean_t done;	/*	 * Caller must be holding the tree lock.	 */	rbtdb = search->rbtdb;	i = search->chain.level_matches;	done = ISC_FALSE;	do {		LOCK(&(rbtdb->node_locks[node->locknum].lock));		/*		 * Look for NS and SIG NS rdatasets.		 */		found = NULL;		foundsig = NULL;		header_prev = NULL;		for (header = node->data;		     header != NULL;		     header = header_next) {			header_next = header->next;			if (header->ttl <= search->now) {				/*				 * This rdataset is stale.  If no one else is				 * using the node, we can clean it up right				 * now, otherwise we mark it as stale, and				 * the node as dirty, so it will get cleaned				 * up later.				 */				if (node->references == 0) {					INSIST(header->down == NULL);					if (header_prev != NULL)						header_prev->next =							header->next;					else						node->data = header->next;					free_rdataset(rbtdb->common.mctx,						      header);				} else {					header->attributes |=						RDATASET_ATTR_STALE;					node->dirty = 1;					header_prev = header;				}			} else if ((header->attributes &				    RDATASET_ATTR_NONEXISTENT) == 0) {				/*				 * We've found an extant rdataset.  See if				 * we're interested in it.				 */				if (header->type == dns_rdatatype_ns) {					

⌨️ 快捷键说明

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