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

📄 query.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	CTRACE("query_isduplicate: false: done");	return (ISC_FALSE);}static isc_result_tquery_addadditional(void *arg, dns_name_t *name, dns_rdatatype_t qtype) {	ns_client_t *client = arg;	isc_result_t result, eresult;	dns_dbnode_t *node;	dns_db_t *db;	dns_name_t *fname, *mname;	dns_rdataset_t *rdataset, *sigrdataset, *a6rdataset, *trdataset;	isc_buffer_t *dbuf;	isc_buffer_t b;	dns_dbversion_t *version;	isc_boolean_t added_something, need_addname;	dns_zone_t *zone;	dns_rdatatype_t type;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(qtype != dns_rdatatype_any);	if (!WANTDNSSEC(client) && dns_rdatatype_isdnssec(qtype))		return (ISC_R_SUCCESS);	CTRACE("query_addadditional");	/*	 * Initialization.	 */	eresult = ISC_R_SUCCESS;	fname = NULL;	rdataset = NULL;	sigrdataset = NULL;	a6rdataset = NULL;	trdataset = NULL;	db = NULL;	version = NULL;	node = NULL;	added_something = ISC_FALSE;	need_addname = ISC_FALSE;	zone = NULL;	/*	 * We treat type A additional section processing as if it	 * were "any address type" additional section processing.	 * To avoid multiple lookups, we do an 'any' database	 * lookup and iterate over the node.	 */	if (qtype == dns_rdatatype_a)		type = dns_rdatatype_any;	else		type = qtype;	/*	 * Get some resources.	 */	dbuf = query_getnamebuf(client);	if (dbuf == NULL)		goto cleanup;	fname = query_newname(client, dbuf, &b);	rdataset = query_newrdataset(client);	if (fname == NULL || rdataset == NULL)		goto cleanup;	if (WANTDNSSEC(client)) {		sigrdataset = query_newrdataset(client);		if (sigrdataset == NULL)			goto cleanup;	}	/*	 * Look for a zone database that might contain authoritative	 * additional data.	 */	result = query_getzonedb(client, name, DNS_GETDB_NOLOG,				 &zone, &db, &version);	if (result != ISC_R_SUCCESS)		goto try_cache;	CTRACE("query_addadditional: db_find");	/*	 * Since we are looking for authoritative data, we do not set	 * the GLUEOK flag.  Glue will be looked for later, but not	 * necessarily in the same database.	 */	node = NULL;	result = dns_db_find(db, name, version, type, client->query.dboptions,			     client->now, &node, fname, rdataset,			     sigrdataset);	if (result == ISC_R_SUCCESS)		goto found;	if (dns_rdataset_isassociated(rdataset))		dns_rdataset_disassociate(rdataset);	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))		dns_rdataset_disassociate(sigrdataset);	if (node != NULL)		dns_db_detachnode(db, &node);	version = NULL;	dns_db_detach(&db);	/*	 * No authoritative data was found.  The cache is our next best bet.	 */ try_cache:	result = query_getcachedb(client, &db, DNS_GETDB_NOLOG);	if (result != ISC_R_SUCCESS)		/*		 * Most likely the client isn't allowed to query the cache.		 */		goto try_glue;	result = dns_db_find(db, name, version, type,  client->query.dboptions,			     client->now, &node, fname, rdataset,			     sigrdataset);	if (result == ISC_R_SUCCESS)		goto found;	if (dns_rdataset_isassociated(rdataset))		dns_rdataset_disassociate(rdataset);	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))		dns_rdataset_disassociate(sigrdataset);	if (node != NULL)		dns_db_detachnode(db, &node);	dns_db_detach(&db); try_glue:	/*	 * No cached data was found.  Glue is our last chance.	 * RFC1035 sayeth:	 *	 *	NS records cause both the usual additional section	 *	processing to locate a type A record, and, when used	 *	in a referral, a special search of the zone in which	 *	they reside for glue information.	 *	 * This is the "special search".  Note that we must search	 * the zone where the NS record resides, not the zone it	 * points to, and that we only do the search in the delegation	 * case (identified by client->query.gluedb being set).	 */	if (client->query.gluedb == NULL)		goto cleanup;	/*	 * Don't poision caches using the bailiwick protection model.	 */	if (!dns_name_issubdomain(name, dns_db_origin(client->query.gluedb)))		goto cleanup;	dns_db_attach(client->query.gluedb, &db);	result = dns_db_find(db, name, version, type,			     client->query.dboptions | DNS_DBFIND_GLUEOK,			     client->now, &node, fname, rdataset,			     sigrdataset);	if (!(result == ISC_R_SUCCESS ||	      result == DNS_R_ZONECUT ||	      result == DNS_R_GLUE))		goto cleanup; found:	/*	 * We have found a potential additional data rdataset, or	 * at least a node to iterate over.	 */	query_keepname(client, fname, dbuf);	/*	 * If we have an rdataset, add it to the additional data	 * section.	 */	mname = NULL;	if (dns_rdataset_isassociated(rdataset) &&	    !query_isduplicate(client, fname, type, &mname)) {		if (mname != NULL) {			query_releasename(client, &fname);			fname = mname;		} else			need_addname = ISC_TRUE;		ISC_LIST_APPEND(fname->list, rdataset, link);		trdataset = rdataset;		rdataset = NULL;		added_something = ISC_TRUE;		/*		 * Note: we only add SIGs if we've added the type they cover,		 * so we do not need to check if the SIG rdataset is already		 * in the response.		 */		if (sigrdataset != NULL &&		    dns_rdataset_isassociated(sigrdataset))		{			ISC_LIST_APPEND(fname->list, sigrdataset, link);			sigrdataset = NULL;		}	}	if (qtype == dns_rdatatype_a) {		/*		 * We now go looking for A, A6, and AAAA records, along with		 * their signatures.		 *		 * XXXRTH  This code could be more efficient.		 */		if (rdataset != NULL) {			if (dns_rdataset_isassociated(rdataset))				dns_rdataset_disassociate(rdataset);		} else {			rdataset = query_newrdataset(client);			if (rdataset == NULL)				goto addname;		}		if (sigrdataset != NULL) {			if (dns_rdataset_isassociated(sigrdataset))				dns_rdataset_disassociate(sigrdataset);		} else if (WANTDNSSEC(client)) {			sigrdataset = query_newrdataset(client);			if (sigrdataset == NULL)				goto addname;		}		result = dns_db_findrdataset(db, node, version,					     dns_rdatatype_a, 0,					     client->now, rdataset,					     sigrdataset);		if (result == DNS_R_NCACHENXDOMAIN)			goto addname;		if (result == DNS_R_NCACHENXRRSET) {			dns_rdataset_disassociate(rdataset);			/*			 * Negative cache entries don't have sigrdatasets.			 */			INSIST(sigrdataset == NULL ||			       ! dns_rdataset_isassociated(sigrdataset));		}		if (result == ISC_R_SUCCESS) {			mname = NULL;			if (!query_isduplicate(client, fname,					       dns_rdatatype_a, &mname)) {				if (mname != NULL) {					query_releasename(client, &fname);					fname = mname;				} else					need_addname = ISC_TRUE;				ISC_LIST_APPEND(fname->list, rdataset, link);				added_something = ISC_TRUE;				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(sigrdataset))				{					ISC_LIST_APPEND(fname->list,							sigrdataset, link);					sigrdataset =						query_newrdataset(client);				}				rdataset = query_newrdataset(client);				if (rdataset == NULL)					goto addname;				if (WANTDNSSEC(client) && sigrdataset == NULL)					goto addname;			} else {				dns_rdataset_disassociate(rdataset);				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(sigrdataset))					dns_rdataset_disassociate(sigrdataset);			}		}		result = dns_db_findrdataset(db, node, version,					     dns_rdatatype_a6, 0,					     client->now, rdataset,					     sigrdataset);		if (result == DNS_R_NCACHENXDOMAIN)			goto addname;		if (result == DNS_R_NCACHENXRRSET) {			dns_rdataset_disassociate(rdataset);			INSIST(sigrdataset == NULL ||			       ! dns_rdataset_isassociated(sigrdataset));		}		if (result == ISC_R_SUCCESS) {			mname = NULL;			if (!query_isduplicate(client, fname,					       dns_rdatatype_a6, &mname)) {				if (mname != NULL) {					query_releasename(client, &fname);					fname = mname;				} else					need_addname = ISC_TRUE;				a6rdataset = rdataset;				ISC_LIST_APPEND(fname->list, rdataset, link);				added_something = ISC_TRUE;				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(sigrdataset))				{					ISC_LIST_APPEND(fname->list,							sigrdataset, link);					sigrdataset =						query_newrdataset(client);				}				rdataset = query_newrdataset(client);				if (rdataset == NULL)					goto addname;				if (WANTDNSSEC(client) && sigrdataset == NULL)					goto addname;			} else {				dns_rdataset_disassociate(rdataset);				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(sigrdataset))					dns_rdataset_disassociate(sigrdataset);			}		}		result = dns_db_findrdataset(db, node, version,					     dns_rdatatype_aaaa, 0,					     client->now, rdataset,					     sigrdataset);		if (result == DNS_R_NCACHENXDOMAIN)			goto addname;		if (result == DNS_R_NCACHENXRRSET) {			dns_rdataset_disassociate(rdataset);			INSIST(sigrdataset == NULL ||			       ! dns_rdataset_isassociated(sigrdataset));		}		if (result == ISC_R_SUCCESS) {			mname = NULL;			if (!query_isduplicate(client, fname,					       dns_rdatatype_aaaa, &mname)) {				if (mname != NULL) {					query_releasename(client, &fname);					fname = mname;				} else					need_addname = ISC_TRUE;				ISC_LIST_APPEND(fname->list, rdataset, link);				added_something = ISC_TRUE;				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(sigrdataset))				{					ISC_LIST_APPEND(fname->list,							sigrdataset, link);					sigrdataset = NULL;				}				rdataset = NULL;			}		}	} addname:	CTRACE("query_addadditional: addname");	/*	 * If we haven't added anything, then we're done.	 */	if (!added_something)		goto cleanup;	/*	 * We may have added our rdatasets to an existing name, if so, then	 * need_addname will be ISC_FALSE.  Whether we used an existing name	 * or a new one, we must set fname to NULL to prevent cleanup.	 */	if (need_addname)		dns_message_addname(client->message, fname,				    DNS_SECTION_ADDITIONAL);	fname = NULL;	/*	 * In a few cases, we want to add additional data for additional	 * data.  It's simpler to just deal with special cases here than	 * to try to create a general purpose mechanism and allow the	 * rdata implementations to do it themselves.	 *	 * This involves recursion, but the depth is limited.  The	 * most complex case is adding a SRV rdataset, which involves	 * recursing to add address records, which in turn can cause	 * recursion to add KEYs.	 */	if (type == dns_rdatatype_a || type == dns_rdatatype_aaaa) {		/*		 * RFC 2535 section 3.5 says that when A or AAAA records are		 * retrieved as additional data, any KEY RRs for the owner name		 * should be added to the additional data section.  Note: we		 * do NOT include A6 in the list of types with such treatment		 * in additional data because we'd have to do it for each A6		 * in the A6 chain.		 *		 * XXXRTH  We should lower the priority here.  Alternatively,		 * we could raise the priority of glue records.		 */		eresult = query_addadditional(client, name, dns_rdatatype_key); 	} else if (type == dns_rdatatype_srv && trdataset != NULL) {		/*		 * If we're adding SRV records to the additional data		 * section, it's helpful if we add the SRV additional data		 * as well.		 */		eresult = dns_rdataset_additionaldata(trdataset,						      query_addadditional,						      client);	}	/*	 * If we added an A6 rdataset, we should also add everything we	 * know about the A6 chains.  We wait until now to do this so that	 * they'll come after any additional data added above.	 */	if (a6rdataset != NULL) {		dns_a6_reset(&client->query.a6ctx);		dns_a6_foreach(&client->query.a6ctx, a6rdataset, client->now);	} cleanup:	CTRACE("query_addadditional: cleanup");	query_putrdataset(client, &rdataset);	if (sigrdataset != NULL)		query_putrdataset(client, &sigrdataset);	if (fname != NULL)		query_releasename(client, &fname);	if (node != NULL)		dns_db_detachnode(db, &node);	if (db != NULL)		dns_db_detach(&db);	if (zone != NULL)		dns_zone_detach(&zone);	CTRACE("query_addadditional: done");	return (eresult);}static voidquery_adda6rrset(void *arg, dns_name_t *name, dns_rdataset_t *rdataset,		      dns_rdataset_t *sigrdataset){	ns_client_t *client = arg;	dns_rdataset_t *crdataset, *csigrdataset;	isc_buffer_t b, *dbuf;	dns_name_t *fname, *mname;	/*	 * Add an rrset to the additional data section.	 */	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(rdataset->type == dns_rdatatype_a6);	/*	 * Get some resources...	 */	fname = NULL;	crdataset = NULL;	csigrdataset = NULL;	dbuf = query_getnamebuf(client);	if (dbuf == NULL)		goto cleanup;	fname = query_newname(client, dbuf, &b);	crdataset = query_newrdataset(client);	if (fname == NULL || crdataset == NULL)		goto cleanup;	if (sigrdataset != NULL) {		csigrdataset = query_newrdataset(client);		if (csigrdataset == NULL)			goto cleanup;	}	if (dns_name_copy(name, fname, NULL) != ISC_R_SUCCESS)		goto cleanup;	dns_rdataset_clone(rdataset, crdataset);	if (sigrdataset != NULL && dns_rdataset_isassociated(sigrdataset))		dns_rdataset_clone(sigrdataset, csigrdataset);	mname = NULL;	if (query_isduplicate(client, fname, crdataset->type, &mname))		goto cleanup;	if (mname != NULL) {		query_releasename(client, &fname);		fname = mname;	} else {		query_keepname(client, fname, dbuf);		dns_message_addname(client->message, fname,				    DNS_SECTION_ADDITIONAL);	}	ISC_LIST_APPEND(fname->list, crdataset, link);	crdataset = NULL;	/*	 * Note: we only add SIGs if we've added the type they cover, so	 * we do not need to check if the SIG rdataset is already in the	 * response.	 */	if (sigrdataset != NULL && dns_rdataset_isassociated(csigrdataset)) {		ISC_LIST_APPEND(fname->list, csigrdataset, link);		csigrdataset = NULL;	}	fname = NULL;	/*	 * In spite of RFC 2535 section 3.5, we don't currently try to add	 * KEY RRs for the A6 records.  It's just too much work.	 */ cleanup:	query_putrdataset(client, &crdataset);	if (sigrdataset != NULL)

⌨️ 快捷键说明

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