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

📄 query.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
isc_result_tns_query_init(ns_client_t *client) {	isc_result_t result;	ISC_LIST_INIT(client->query.namebufs);	ISC_LIST_INIT(client->query.activeversions);	ISC_LIST_INIT(client->query.freeversions);	client->query.restarts = 0;	client->query.timerset = ISC_FALSE;	client->query.qname = NULL;	client->query.fetch = NULL;	client->query.authdb = NULL;	client->query.authzone = NULL;	client->query.authdbset = ISC_FALSE;	client->query.isreferral = ISC_FALSE;		query_reset(client, ISC_FALSE);	result = query_newdbversion(client, 3);	if (result != ISC_R_SUCCESS)		return (result);	dns_a6_init(&client->query.a6ctx, query_simplefind, query_adda6rrset,		    NULL, NULL, client);	return (query_newnamebuf(client));}static inline ns_dbversion_t *query_findversion(ns_client_t *client, dns_db_t *db,		  isc_boolean_t *newzonep){	ns_dbversion_t *dbversion;	/*	 * We may already have done a query related to this	 * database.  If so, we must be sure to make subsequent	 * queries from the same version.	 */	for (dbversion = ISC_LIST_HEAD(client->query.activeversions);	     dbversion != NULL;	     dbversion = ISC_LIST_NEXT(dbversion, link)) {		if (dbversion->db == db)			break;	}	if (dbversion == NULL) {		/*		 * This is a new zone for this query.  Add it to		 * the active list.		 */		dbversion = query_getdbversion(client);		if (dbversion == NULL)			return (NULL);		dns_db_attach(db, &dbversion->db);		dns_db_currentversion(db, &dbversion->version);		dbversion->queryok = ISC_FALSE;		ISC_LIST_APPEND(client->query.activeversions,				dbversion, link);		*newzonep = ISC_TRUE;	} else		*newzonep = ISC_FALSE;	return (dbversion);}static inline isc_result_tquery_getzonedb(ns_client_t *client, dns_name_t *name, unsigned int options,		dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp){	isc_result_t result;	isc_boolean_t check_acl, new_zone;	dns_acl_t *queryacl;	ns_dbversion_t *dbversion;	unsigned int ztoptions;	dns_zone_t *zone = NULL;	dns_db_t *db = NULL;	REQUIRE(zonep != NULL && *zonep == NULL);	REQUIRE(dbp != NULL && *dbp == NULL);	/*	 * Find a zone database to answer the query.	 */	ztoptions = ((options & DNS_GETDB_NOEXACT) != 0) ?		DNS_ZTFIND_NOEXACT : 0;	result = dns_zt_find(client->view->zonetable, name, ztoptions, NULL,			     &zone);	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)		result = dns_zone_getdb(zone, &db);	if (result != ISC_R_SUCCESS)				goto fail;	/*	 * This limits our searching to the zone where the first name	 * (the query target) was looked for.  This prevents following	 * CNAMES or DNAMES into other zones and prevents returning 	 * additional data from other zones.	 */	if (!client->view->additionalfromauth &&	    client->query.authdbset &&	    db != client->query.authdb)		goto refuse;	/*	 * If the zone has an ACL, we'll check it, otherwise	 * we use the view's "allow-query" ACL.  Each ACL is only checked	 * once per query.	 *	 * Also, get the database version to use.	 */	check_acl = ISC_TRUE;	/* Keep compiler happy. */	queryacl = NULL;	/*	 * Get the current version of this database.	 */	dbversion = query_findversion(client, db, &new_zone);	if (dbversion == NULL) {		result = DNS_R_SERVFAIL;		goto fail;	}	if (new_zone) {		check_acl = ISC_TRUE;	} else if (!dbversion->queryok) {		goto refuse;	} else {		check_acl = ISC_FALSE;	}	queryacl = dns_zone_getqueryacl(zone);	if (queryacl == NULL) {		queryacl = client->view->queryacl;		if ((client->query.attributes &		     NS_QUERYATTR_QUERYOKVALID) != 0) {			/*			 * We've evaluated the view's queryacl already.  If			 * NS_QUERYATTR_QUERYOK is set, then the client is			 * allowed to make queries, otherwise the query should			 * be refused.			 */			check_acl = ISC_FALSE;			if ((client->query.attributes &			     NS_QUERYATTR_QUERYOK) == 0)				goto refuse;		} else {			/*			 * We haven't evaluated the view's queryacl yet.			 */			check_acl = ISC_TRUE;		}	}	if (check_acl) {		isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);		result = ns_client_checkaclsilent(client, queryacl, ISC_TRUE);		if (log) {			char msg[DNS_NAME_FORMATSIZE + DNS_RDATACLASS_FORMATSIZE				+ sizeof "query '/'"];			if (result == ISC_R_SUCCESS) {				if (isc_log_wouldlog(ns_g_lctx,						     ISC_LOG_DEBUG(3)))				{					ns_client_aclmsg("query", name,							 client->view->rdclass,							 msg, sizeof(msg));					ns_client_log(client,						      DNS_LOGCATEGORY_SECURITY,						      NS_LOGMODULE_QUERY,						      ISC_LOG_DEBUG(3),						      "%s approved", msg);				}		    	} else {				ns_client_aclmsg("query", name,						 client->view->rdclass,						 msg, sizeof(msg));				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,					      NS_LOGMODULE_QUERY, ISC_LOG_INFO,					      "%s denied", msg);			}		}		if (queryacl == client->view->queryacl) {			if (result == ISC_R_SUCCESS) {				/*				 * We were allowed by the default				 * "allow-query" ACL.  Remember this so we				 * don't have to check again.				 */				client->query.attributes |=					NS_QUERYATTR_QUERYOK;			}			/*			 * We've now evaluated the view's query ACL, and			 * the NS_QUERYATTR_QUERYOK attribute is now valid.			 */			client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;		}		if (result != ISC_R_SUCCESS)			goto refuse;	}	/* Approved. */	/*	 * Remember the result of the ACL check so we	 * don't have to check again.	 */	dbversion->queryok = ISC_TRUE;	/* Transfer ownership. */	*zonep = zone;	*dbp = db;	*versionp = dbversion->version;	return (ISC_R_SUCCESS); refuse:	result = DNS_R_REFUSED; fail:	if (zone != NULL)		dns_zone_detach(&zone);	if (db != NULL)		dns_db_detach(&db);	return (result);}static inline isc_result_tquery_getcachedb(ns_client_t *client, dns_db_t **dbp, unsigned int options){	isc_result_t result;	isc_boolean_t check_acl;	dns_db_t *db = NULL;	REQUIRE(dbp != NULL && *dbp == NULL);	/*	 * Find a cache database to answer the query.	 * This may fail with DNS_R_REFUSED if the client	 * is not allowed to use the cache.	 */	if (!USECACHE(client))		return (DNS_R_REFUSED);	dns_db_attach(client->view->cachedb, &db);	if ((client->query.attributes &	     NS_QUERYATTR_QUERYOKVALID) != 0) {		/*		 * We've evaluated the view's queryacl already.  If		 * NS_QUERYATTR_QUERYOK is set, then the client is		 * allowed to make queries, otherwise the query should		 * be refused.		 */		check_acl = ISC_FALSE;		if ((client->query.attributes &		     NS_QUERYATTR_QUERYOK) == 0)			goto refuse;	} else {		/*		 * We haven't evaluated the view's queryacl yet.		 */		check_acl = ISC_TRUE;	}	if (check_acl) {		isc_boolean_t log = ISC_TF((options & DNS_GETDB_NOLOG) == 0);				result = ns_client_checkacl(client, "query (cache)",					    client->view->queryacl,					    ISC_TRUE,					    log ? ISC_LOG_INFO :						  ISC_LOG_DEBUG(3));		if (result == ISC_R_SUCCESS) {			/*			 * We were allowed by the default			 * "allow-query" ACL.  Remember this so we			 * don't have to check again.			 */			client->query.attributes |=				NS_QUERYATTR_QUERYOK;		}		/*		 * We've now evaluated the view's query ACL, and		 * the NS_QUERYATTR_QUERYOK attribute is now valid.		 */		client->query.attributes |= NS_QUERYATTR_QUERYOKVALID;		if (result != ISC_R_SUCCESS)			goto refuse;	}	/* Approved. */	/* Transfer ownership. */	*dbp = db;	return (ISC_R_SUCCESS); refuse:	result = DNS_R_REFUSED;	if (db != NULL)		dns_db_detach(&db);	return (result);}static inline isc_result_tquery_getdb(ns_client_t *client, dns_name_t *name, unsigned int options,	    dns_zone_t **zonep, dns_db_t **dbp, dns_dbversion_t **versionp,	    isc_boolean_t *is_zonep){	isc_result_t result;	result = query_getzonedb(client, name, options, zonep, dbp, versionp);	if (result == ISC_R_SUCCESS) {		*is_zonep = ISC_TRUE;	} else if (result == ISC_R_NOTFOUND) {		result = query_getcachedb(client, dbp, options);		*is_zonep = ISC_FALSE;	}	return (result);}static isc_result_tquery_simplefind(void *arg, dns_name_t *name, dns_rdatatype_t type,		 isc_stdtime_t now,		 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	ns_client_t *client = arg;	isc_result_t result;	dns_fixedname_t foundname;	dns_db_t *db;	dns_dbversion_t *version;	unsigned int dboptions;	isc_boolean_t is_zone;	dns_rdataset_t zrdataset, zsigrdataset;	dns_zone_t *zone;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(rdataset != NULL);	dns_rdataset_init(&zrdataset);	if (sigrdataset != NULL)		dns_rdataset_init(&zsigrdataset);	/*	 * Find a database to answer the query.	 */	zone = NULL;	db = NULL;	version = NULL;	result = query_getdb(client, name, 0, &zone, &db, &version, &is_zone);	if (result != ISC_R_SUCCESS)		goto cleanup; db_find:	/*	 * Now look for an answer in the database.	 */	dns_fixedname_init(&foundname);	dboptions = client->query.dboptions;	if (db == client->query.gluedb || (!is_zone && CACHEGLUEOK(client)))		dboptions |= DNS_DBFIND_GLUEOK;	result = dns_db_find(db, name, version, type, dboptions,			     now, NULL, dns_fixedname_name(&foundname),			     rdataset, sigrdataset);	if (result == DNS_R_DELEGATION ||	    result == ISC_R_NOTFOUND) {		if (dns_rdataset_isassociated(rdataset))			dns_rdataset_disassociate(rdataset);		if (sigrdataset != NULL &&		    dns_rdataset_isassociated(sigrdataset))			dns_rdataset_disassociate(sigrdataset);		if (is_zone) {			if (USECACHE(client)) {				/*				 * Either the answer is in the cache, or we				 * don't know it.				 */				is_zone = ISC_FALSE;				version = NULL;				dns_db_detach(&db);				dns_db_attach(client->view->cachedb, &db);				goto db_find;			}		} else {			/*			 * We don't have the data in the cache.  If we've got			 * glue from the zone, use it.			 */			if (dns_rdataset_isassociated(&zrdataset)) {				dns_rdataset_clone(&zrdataset, rdataset);				if (sigrdataset != NULL &&				    dns_rdataset_isassociated(&zsigrdataset))					dns_rdataset_clone(&zsigrdataset,							   sigrdataset);				result = ISC_R_SUCCESS;				goto cleanup;			}		}		/*		 * We don't know the answer.		 */		result = ISC_R_NOTFOUND;	} else if (result == DNS_R_GLUE) {		if (USECACHE(client) && RECURSIONOK(client)) {			/*			 * We found an answer, but the cache may be better.			 * Remember what we've got and go look in the cache.			 */			is_zone = ISC_FALSE;			version = NULL;			dns_rdataset_clone(rdataset, &zrdataset);			dns_rdataset_disassociate(rdataset);			if (sigrdataset != NULL &&			    dns_rdataset_isassociated(sigrdataset))			{				dns_rdataset_clone(sigrdataset, &zsigrdataset);				dns_rdataset_disassociate(sigrdataset);			}			dns_db_detach(&db);			dns_db_attach(client->view->cachedb, &db);			goto db_find;		}		/*		 * Otherwise, the glue is the best answer.		 */		result = ISC_R_SUCCESS;	} else if (result != ISC_R_SUCCESS) {		if (dns_rdataset_isassociated(rdataset))			dns_rdataset_disassociate(rdataset);		if (sigrdataset != NULL &&		    dns_rdataset_isassociated(sigrdataset))			dns_rdataset_disassociate(sigrdataset);		result = ISC_R_NOTFOUND;	}	/*	 * If we get here, the result is ISC_R_SUCCESS, and we found the	 * answer we were looking for in the zone.	 */ cleanup:	if (dns_rdataset_isassociated(&zrdataset)) {		dns_rdataset_disassociate(&zrdataset);		if (sigrdataset != NULL &&		    dns_rdataset_isassociated(&zsigrdataset))			dns_rdataset_disassociate(&zsigrdataset);	}	if (db != NULL)		dns_db_detach(&db);	if (zone != NULL)		dns_zone_detach(&zone);	return (result);}static inline isc_boolean_tquery_isduplicate(ns_client_t *client, dns_name_t *name,		  dns_rdatatype_t type, dns_name_t **mnamep){	dns_section_t section;	dns_name_t *mname = NULL;	isc_result_t result;	CTRACE("query_isduplicate");	for (section = DNS_SECTION_ANSWER;	     section <= DNS_SECTION_ADDITIONAL;	     section++) {		result = dns_message_findname(client->message, section,					      name, type, 0, &mname, NULL);		if (result == ISC_R_SUCCESS) {			/*			 * We've already got this RRset in the response.			 */			CTRACE("query_isduplicate: true: done");			return (ISC_TRUE);		} else if (result == DNS_R_NXRRSET) {			/*			 * The name exists, but the rdataset does not.			 */			if (section == DNS_SECTION_ADDITIONAL)				break;		} else			RUNTIME_CHECK(result == DNS_R_NXDOMAIN);		mname = NULL;	}	/*	 * If the dns_name_t we're looking up is already in the message,	 * we don't want to trigger the caller's name replacement logic.	 */	if (name == mname)		mname = NULL;	*mnamep = mname;

⌨️ 快捷键说明

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