query.c

来自「非常好的dns解析软件」· C语言 代码 · 共 2,425 行 · 第 1/5 页

C
2,425
字号
		if (result != ISC_R_SUCCESS)			return (NULL);	}	dbversion = ISC_LIST_HEAD(client->query.freeversions);	INSIST(dbversion != NULL);	ISC_LIST_UNLINK(client->query.freeversions, dbversion, link);	return (dbversion);}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;	result = isc_mutex_init(&client->query.fetchlock);	if (result != ISC_R_SUCCESS)		return (result);	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) {		DESTROYLOCK(&client->query.fetchlock);		return (result);	}	result = query_newnamebuf(client);	if (result != ISC_R_SUCCESS)		query_freefreeversions(client, ISC_TRUE);	return (result);}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_validatezonedb(ns_client_t *client, dns_name_t *name,		     dns_rdatatype_t qtype, unsigned int options,		     dns_zone_t *zone, dns_db_t *db,		     dns_dbversion_t **versionp){	isc_result_t result;	isc_boolean_t check_acl, new_zone;	dns_acl_t *queryacl;	ns_dbversion_t *dbversion;	REQUIRE(zone != NULL);	REQUIRE(db != NULL);	/*	 * 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[NS_CLIENT_ACLMSGSIZE("query")];			if (result == ISC_R_SUCCESS) {				if (isc_log_wouldlog(ns_g_lctx,						     ISC_LOG_DEBUG(3)))				{					ns_client_aclmsg("query", name, qtype,							 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, qtype,						 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, if necessary. */	if (versionp != NULL)		*versionp = dbversion->version;	return (ISC_R_SUCCESS); refuse:	return (DNS_R_REFUSED); fail:	return (result);}static inline isc_result_tquery_getzonedb(ns_client_t *client, dns_name_t *name, dns_rdatatype_t qtype,		unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,		dns_dbversion_t **versionp){	isc_result_t result;	unsigned int ztoptions;	dns_zone_t *zone = NULL;	dns_db_t *db = NULL;	isc_boolean_t partial = ISC_FALSE;	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 == DNS_R_PARTIALMATCH)		partial = ISC_TRUE;	if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)		result = dns_zone_getdb(zone, &db);	if (result != ISC_R_SUCCESS)		goto fail;	result = query_validatezonedb(client, name, qtype, options, zone, db,				      versionp);	if (result != ISC_R_SUCCESS)		goto fail;	/* Transfer ownership. */	*zonep = zone;	*dbp = db;	if (partial && (options & DNS_GETDB_PARTIAL) != 0)		return (DNS_R_PARTIALMATCH);	return (ISC_R_SUCCESS); 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_name_t *name, dns_rdatatype_t qtype,		 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);		char msg[NS_CLIENT_ACLMSGSIZE("query (cache)")];		result = ns_client_checkaclsilent(client,						  client->view->queryacl,						  ISC_TRUE);		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;			if (log && isc_log_wouldlog(ns_g_lctx,						     ISC_LOG_DEBUG(3)))			{				ns_client_aclmsg("query (cache)", name, qtype,						 client->view->rdclass,						 msg, sizeof(msg));				ns_client_log(client,					      DNS_LOGCATEGORY_SECURITY,					      NS_LOGMODULE_QUERY,					      ISC_LOG_DEBUG(3),					      "%s approved", msg);			}		} else if (log) {			ns_client_aclmsg("query (cache)", name, qtype,					 client->view->rdclass, msg,					 sizeof(msg));			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,				      NS_LOGMODULE_QUERY, ISC_LOG_INFO,				      "%s denied", msg);		}		/*		 * 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, dns_rdatatype_t qtype,	    unsigned int options, dns_zone_t **zonep, dns_db_t **dbp,	    dns_dbversion_t **versionp, isc_boolean_t *is_zonep){	isc_result_t result;#ifdef DLZ	isc_result_t tresult;	unsigned int namelabels;	unsigned int zonelabels;	dns_zone_t *zone = NULL;	dns_db_t *tdbp;	REQUIRE(zonep != NULL && *zonep == NULL);	tdbp = NULL;	/* Calculate how many labels are in name. */	namelabels = dns_name_countlabels(name);	zonelabels = 0;	/* Try to find name in bind's standard database. */	result = query_getzonedb(client, name, qtype, options, &zone,				 dbp, versionp);	/* See how many labels are in the zone's name.	  */	if (result == ISC_R_SUCCESS && zone != NULL)		zonelabels = dns_name_countlabels(dns_zone_getorigin(zone));	/*	 * If # zone labels < # name labels, try to find an even better match	 * Only try if a DLZ driver is loaded for this view	 */	if (zonelabels < namelabels && client->view->dlzdatabase != NULL) {		tresult = dns_dlzfindzone(client->view, name,					  zonelabels, &tdbp);		 /* If we successful, we found a better match. */		if (tresult == ISC_R_SUCCESS) {			/*			 * If the previous search returned a zone, detach it.			 */			if (zone != NULL)				dns_zone_detach(&zone);			/*			 * If the previous search returned a database,			 * detach it.			 */			if (*dbp != NULL)				dns_db_detach(dbp);			/*			 * If the previous search returned a version, clear it.			 */			*versionp = NULL;			/*			 * Get our database version.			 */			dns_db_currentversion(tdbp, versionp);			/*			 * Be sure to return our database.			 */			*dbp = tdbp;			/*			 * We return a null zone, No stats for DLZ zones.			 */			zone = NULL;			result = tresult;		}	}#else	result = query_getzonedb(client, name, qtype, options,				 zonep, dbp, versionp);#endif	/* If successfull, Transfer ownership of zone. */	if (result == ISC_R_SUCCESS) {#ifdef DLZ		*zonep = zone;#endif		/*		 * If neither attempt above succeeded, return the cache instead		 */		*is_zonep = ISC_TRUE;	} else if (result == ISC_R_NOTFOUND) {		result = query_getcachedb(client, name, qtype, dbp, options);		*is_zonep = ISC_FALSE;	}	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;

⌨️ 快捷键说明

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