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

📄 query.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
 cleanup:	if (rdataset != NULL)		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);	if (zdb != NULL) {		query_putrdataset(client, &zrdataset);		if (zsigrdataset != NULL)			query_putrdataset(client, &zsigrdataset);		if (zfname != NULL)			query_releasename(client, &zfname);		dns_db_detach(&zdb);	}}static voidquery_resume(isc_task_t *task, isc_event_t *event) {	dns_fetchevent_t *devent = (dns_fetchevent_t *)event;	ns_client_t *client;	isc_boolean_t fetch_cancelled, client_shuttingdown;	/*	 * Resume a query after recursion.	 */	UNUSED(task);	REQUIRE(event->ev_type == DNS_EVENT_FETCHDONE);	client = devent->ev_arg;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(task == client->task);	REQUIRE(RECURSING(client));	if (devent->fetch != NULL) {		/*		 * This is the fetch we've been waiting for.		 */		INSIST(devent->fetch == client->query.fetch);		client->query.fetch = NULL;		fetch_cancelled = ISC_FALSE;		/*		 * Update client->now.		 */		isc_stdtime_get(&client->now);	} else {		/*		 * This is a fetch completion event for a cancelled fetch.		 * Clean up and don't resume the find.		 */		fetch_cancelled = ISC_TRUE;	}	INSIST(client->query.fetch == NULL);	client->query.attributes &= ~NS_QUERYATTR_RECURSING;	dns_resolver_destroyfetch(&devent->fetch);	/*	 * If this client is shutting down, or this transaction	 * has timed out, do not resume the find.	 */	client_shuttingdown = ns_client_shuttingdown(client);	if (fetch_cancelled || client_shuttingdown) {		if (devent->node != NULL)			dns_db_detachnode(devent->db, &devent->node);		if (devent->db != NULL)			dns_db_detach(&devent->db);		query_putrdataset(client, &devent->rdataset);		if (devent->sigrdataset != NULL)			query_putrdataset(client, &devent->sigrdataset);		isc_event_free(&event);		query_next(client, ISC_R_CANCELED);		/*		 * This may destroy the client.		 */		ns_client_detach(&client);	} else {		query_find(client, devent, 0);	}}static isc_result_tquery_recurse(ns_client_t *client, dns_rdatatype_t qtype, dns_name_t *qdomain,	      dns_rdataset_t *nameservers){	isc_result_t result;	dns_rdataset_t *rdataset, *sigrdataset;	inc_stats(client, dns_statscounter_recursion);	/*	 * We are about to recurse, which means that this client will	 * be unavailable for serving new requests for an indeterminate	 * amount of time.  If this client is currently responsible	 * for handling incoming queries, set up a new client	 * object to handle them while we are waiting for a	 * response.  There is no need to replace TCP clients	 * because those have already been replaced when the	 * connection was accepted (if allowed by the TCP quota).	 */	if (client->recursionquota == NULL) {		result = isc_quota_attach(&ns_g_server->recursionquota,					  &client->recursionquota);		if (result == ISC_R_SUCCESS && !client->mortal &&		    (client->attributes & NS_CLIENTATTR_TCP) == 0)			result = ns_client_replace(client);		if (result != ISC_R_SUCCESS) {			ns_client_log(client, NS_LOGCATEGORY_CLIENT,				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,				      "no more recursive clients: %s",				      isc_result_totext(result));			return (result);		}	}	/*	 * Invoke the resolver.	 */	REQUIRE(nameservers == NULL || nameservers->type == dns_rdatatype_ns);	REQUIRE(client->query.fetch == NULL);	rdataset = query_newrdataset(client);	if (rdataset == NULL)		return (ISC_R_NOMEMORY);	if (WANTDNSSEC(client)) {		sigrdataset = query_newrdataset(client);		if (sigrdataset == NULL) {			query_putrdataset(client, &rdataset);			return (ISC_R_NOMEMORY);		}	} else		sigrdataset = NULL;	if (client->query.timerset == ISC_FALSE)		ns_client_settimeout(client, 60);	result = dns_resolver_createfetch(client->view->resolver,					  client->query.qname,					  qtype, qdomain, nameservers,					  NULL, client->query.fetchoptions,					  client->task,					  query_resume, client,					  rdataset, sigrdataset,					  &client->query.fetch);	if (result == ISC_R_SUCCESS) {		/*		 * Record that we're waiting for an event.  A client which		 * is shutting down will not be destroyed until all the		 * events have been received.		 */	} else {		query_putrdataset(client, &rdataset);		if (sigrdataset != NULL)			query_putrdataset(client, &sigrdataset);	}	return (result);}static inline isc_result_tquery_findparentkey(ns_client_t *client, dns_name_t *name,		    dns_zone_t **zonep, dns_db_t **dbp,		    dns_dbversion_t **versionp, dns_dbnode_t **nodep,		    dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset){	dns_db_t *pdb;	dns_dbnode_t *pnode;	dns_dbversion_t *pversion;	dns_rdataset_t prdataset, psigrdataset;	dns_rdataset_t *psigrdatasetp;	isc_result_t result;	dns_zone_t *pzone;	isc_boolean_t is_zone;	dns_fixedname_t pfoundname;	/*	 * 'name' is at a zone cut.  Try to find a KEY for 'name' in	 * the deepest ancestor zone of 'name' (if any).  If it exists,	 * update *zonep, *dbp, *nodep, rdataset, and sigrdataset and	 * return ISC_R_SUCCESS.  If not, leave them alone and return a	 * non-success status.	 */	pzone = NULL;	pdb = NULL;	pnode = NULL;	pversion = NULL;	dns_rdataset_init(&prdataset);	if (sigrdataset != NULL)		dns_rdataset_init(&psigrdataset);	is_zone = ISC_FALSE;	dns_fixedname_init(&pfoundname);	result = query_getdb(client, name, DNS_GETDB_NOEXACT,			     &pzone, &pdb, &pversion, &is_zone);	if (result != ISC_R_SUCCESS)		goto cleanup;	if (!is_zone) {		result = ISC_R_FAILURE;		goto cleanup;	}	if (sigrdataset != NULL)		psigrdatasetp = &psigrdataset;	else		psigrdatasetp = NULL;	result = dns_db_find(pdb, name, pversion, dns_rdatatype_key,			     client->query.dboptions,			     client->now, &pnode,			     dns_fixedname_name(&pfoundname),			     &prdataset, psigrdatasetp);	if (result == ISC_R_SUCCESS) {		if (dns_rdataset_isassociated(rdataset))			dns_rdataset_disassociate(rdataset);		dns_rdataset_clone(&prdataset, rdataset);		if (sigrdataset != NULL) {			if (dns_rdataset_isassociated(sigrdataset))				dns_rdataset_disassociate(sigrdataset);			if (dns_rdataset_isassociated(&psigrdataset))				dns_rdataset_clone(&psigrdataset, sigrdataset);		}		if (*nodep != NULL)			dns_db_detachnode(*dbp, nodep);		*nodep = pnode;		pnode = NULL;		*versionp = pversion;		if (*dbp != NULL)			dns_db_detach(dbp);		*dbp = pdb;		pdb = NULL;		if (*zonep != NULL)			dns_zone_detach(zonep);		*zonep = pzone;		pzone = NULL;	} cleanup:	if (dns_rdataset_isassociated(&prdataset))		dns_rdataset_disassociate(&prdataset);	if (sigrdataset != NULL && dns_rdataset_isassociated(&psigrdataset))		dns_rdataset_disassociate(&psigrdataset);	if (pnode != NULL)		dns_db_detachnode(pdb, &pnode);	if (pdb != NULL)		dns_db_detach(&pdb);	if (pzone != NULL)		dns_zone_detach(&pzone);	return (result);}#define MAX_RESTARTS 16#define QUERY_ERROR(r) \do { \	eresult = r; \	want_restart = ISC_FALSE; \} while (0)/* * Extract a network address from the RDATA of an A or AAAA * record. * * Returns: *	ISC_R_SUCCESS *	ISC_R_NOTIMPLEMENTED	The rdata is not a known address type. */static isc_result_trdata_tonetaddr(dns_rdata_t *rdata, isc_netaddr_t *netaddr) {	struct in_addr ina;	struct in6_addr in6a;		switch (rdata->type) {	case dns_rdatatype_a:		INSIST(rdata->length == 4);		memcpy(&ina.s_addr, rdata->data, 4);		isc_netaddr_fromin(netaddr, &ina);		return (ISC_R_SUCCESS);	case dns_rdatatype_aaaa:		INSIST(rdata->length == 16);		memcpy(in6a.s6_addr, rdata->data, 16);		isc_netaddr_fromin6(netaddr, &in6a);		return (ISC_R_SUCCESS);	default:		return (ISC_R_NOTIMPLEMENTED);	}}/* * Find the sort order of 'rdata' in the topology-like * ACL forming the second element in a 2-element top-level * sortlist statement. */static intquery_sortlist_order_2element(dns_rdata_t *rdata, void *arg) {	isc_netaddr_t netaddr;	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)		return (INT_MAX);	return (ns_sortlist_addrorder2(&netaddr, arg));}/* * Find the sort order of 'rdata' in the matching element * of a 1-element top-level sortlist statement. */static intquery_sortlist_order_1element(dns_rdata_t *rdata, void *arg) {	isc_netaddr_t netaddr;	if (rdata_tonetaddr(rdata, &netaddr) != ISC_R_SUCCESS)		return (INT_MAX);	return (ns_sortlist_addrorder1(&netaddr, arg));}/* * Find the sortlist statement that applies to 'client' and set up * the sortlist info in in client->message appropriately. */static voidsetup_query_sortlist(ns_client_t *client) {	isc_netaddr_t netaddr;	dns_rdatasetorderfunc_t order = NULL;	void *order_arg = NULL;		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);	switch (ns_sortlist_setup(client->view->sortlist,			       &netaddr, &order_arg)) {	case NS_SORTLISTTYPE_1ELEMENT:		order = query_sortlist_order_1element;		break;	case NS_SORTLISTTYPE_2ELEMENT:		order = query_sortlist_order_2element;		break;	case NS_SORTLISTTYPE_NONE:		order = NULL;		break;	default:		INSIST(0);		break;	}	dns_message_setsortorder(client->message, order, order_arg);}/* * Do the bulk of query processing for the current query of 'client'. * If 'event' is non-NULL, we are returning from recursion and 'qtype' * is ignored.  Otherwise, 'qtype' is the query type. */static voidquery_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype) {	dns_db_t *db, *zdb;	dns_dbnode_t *node;	dns_rdatatype_t type;	dns_name_t *fname, *zfname, *tname, *prefix;	dns_rdataset_t *rdataset, *trdataset;	dns_rdataset_t *sigrdataset, *zrdataset, *zsigrdataset;	dns_rdataset_t **sigrdatasetp;	dns_rdata_t rdata = DNS_RDATA_INIT;	dns_rdatasetiter_t *rdsiter;	isc_boolean_t want_restart, authoritative, is_zone;	unsigned int n, nlabels, nbits;	dns_namereln_t namereln;	int order;	isc_buffer_t *dbuf;	isc_buffer_t b;	isc_result_t result, eresult;	dns_fixedname_t fixed;	dns_dbversion_t *version;	dns_zone_t *zone;	dns_rdata_cname_t cname;	dns_rdata_dname_t dname;	isc_boolean_t empty_wild;	CTRACE("query_find");	/*	 * One-time initialization.	 *	 * It's especially important to initialize anything that the cleanup	 * code might cleanup.	 */	eresult = ISC_R_SUCCESS;	fname = NULL;	zfname = NULL;	rdataset = NULL;	zrdataset = NULL;	sigrdataset = NULL;	zsigrdataset = NULL;	node = NULL;	db = NULL;	zdb = NULL;	version = NULL;	zone = NULL;	empty_wild = ISC_FALSE;	if (event != NULL) {		/*		 * We're returning from recursion.  Restore the query context		 * and resume.		 */		want_restart = ISC_FALSE;		authoritative = ISC_FALSE;		is_zone = ISC_FALSE;		qtype = event->qtype;		if (qtype == dns_rdatatype_sig)			type = dns_rdatatype_any;		else			type = qtype;		db = event->db;		node = event->node;		rdataset = event->rdataset;		sigrdataset = event->sigrdataset;		/*		 * We'll need some resources...		 */		dbuf = query_getnamebuf(client);		if (dbuf == NULL) {			QUERY_ERROR(DNS_R_SERVFAIL);			goto cleanup;		}		fname = query_newname(client, dbuf, &b);		if (fname == NULL) {			QUERY_ERROR(DNS_R_SERVFAIL);			goto cleanup;		}		tname = dns_fixedname_name(&event->foundname);		result = dns_name_copy(tname, fname, NULL);		if (result != ISC_R_SUCCESS) {			QUERY_ERROR(DNS_R_SERVFAIL);			goto cleanup;		}		result = event->result;		goto resume;	}		/*	 * Not returning from recursion.	 */	/*	 * If it's a SIG query, we'll iterate the node.	 */	if (qtype == dns_rdatatype_sig)		type = dns_rdatatype_any;	else		type = qtype; restart:	CTRACE("query_find: restart");	want_restart = ISC_FALSE;	authoritative = ISC_FALSE;	version = NULL;	/*	 * First we must find the right database.	 */	result = query_getdb(client, client->query.qname, 0, &zone, &db,			     &version, &is_zone);	if (result != ISC_R_SUCCESS) {		if (result == DNS_R_REFUSED)			QUERY_ERROR(DNS_R_REFUSED);		else			QUERY_ERROR(DNS_R_SERVFAIL);		goto cleanup;	}	if (is_zone)		authoritative = ISC_TRUE;       	if (event == NULL && client->query.restarts == 0) {		if (is_zone) {			dns_zone_attach(zone, &client->query.authzone);			dns_db_attach(db, &client->query.authdb);		}		client->query.authdbset = ISC_TRUE;	} db_find:	CTRACE("query_find: db_find");	/*	 * We'll need some resources...	 */	

⌨️ 快捷键说明

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