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

📄 query.c

📁 bind 源码 最新实现 linux/unix/windows平台
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * We'll need some resources...	 */	dbuf = query_getnamebuf(client);	if (dbuf == NULL)		return;	fname = query_newname(client, dbuf, &b);	if (fname == NULL)		return;	dns_name_split(name, sig.labels + 1, NULL, fname);	/* This will succeed, since we've stripped labels. */	RUNTIME_CHECK(dns_name_concatenate(dns_wildcardname, fname, fname,					   NULL) == ISC_R_SUCCESS);	query_addrrset(client, &fname, rdatasetp, sigrdatasetp,		       dbuf, DNS_SECTION_AUTHORITY);}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));	LOCK(&client->query.fetchlock);	if (client->query.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;	}	UNLOCK(&client->query.fetchlock);	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);		if (fetch_cancelled)			query_error(client, DNS_R_SERVFAIL);		else			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_SOFTQUOTA) {			ns_client_log(client, NS_LOGCATEGORY_CLIENT,				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,				      "recursive-clients soft limit exceeded, "				      "aborting oldest query");			ns_client_killoldestquery(client);			result = ISC_R_SUCCESS;		} else if (result == ISC_R_QUOTA) {			ns_client_log(client, NS_LOGCATEGORY_CLIENT,				      NS_LOGMODULE_QUERY, ISC_LOG_WARNING,				      "no more recursive clients: %s",				      isc_result_totext(result));			ns_client_killoldestquery(client);		}		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,					      "ns_client_replace() failed: %s",					      isc_result_totext(result));				isc_quota_detach(&client->recursionquota);			}		}		if (result != ISC_R_SUCCESS)			return (result);		ns_client_recursing(client);	}	/*	 * 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);}#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);}static voidquery_addnoqnameproof(ns_client_t *client, dns_rdataset_t *rdataset) {	isc_buffer_t *dbuf, b;	dns_name_t *fname;	dns_rdataset_t *nsec, *nsecsig;	isc_result_t result = ISC_R_NOMEMORY;	CTRACE("query_addnoqnameproof");	fname = NULL;	nsec = NULL;	nsecsig = NULL;	dbuf = query_getnamebuf(client);	if (dbuf == NULL)		goto cleanup;	fname = query_newname(client, dbuf, &b);	nsec = query_newrdataset(client);	nsecsig = query_newrdataset(client);	if (fname == NULL || nsec == NULL || nsecsig == NULL)		goto cleanup;	result = dns_rdataset_getnoqname(rdataset, fname, nsec, nsecsig);	RUNTIME_CHECK(result == ISC_R_SUCCESS);	query_addrrset(client, &fname, &nsec, &nsecsig, dbuf,		       DNS_SECTION_AUTHORITY); cleanup:	if (nsec != NULL)                query_putrdataset(client, &nsec);        if (nsecsig != NULL)                query_putrdataset(client, &nsecsig);        if (fname != NULL)                query_releasename(client, &fname);}static inline voidanswer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {	dns_name_t *name;	dns_message_t *msg;	dns_section_t section = DNS_SECTION_ADDITIONAL;	dns_rdataset_t *rdataset = NULL;	msg = client->message;	for (name = ISC_LIST_HEAD(msg->sections[section]);	     name != NULL;	     name = ISC_LIST_NEXT(name, link))		if (dns_name_equal(name, client->query.qname)) {			for (rdataset = ISC_LIST_HEAD(name->list);			     rdataset != NULL;			     rdataset = ISC_LIST_NEXT(rdataset, link))				if (rdataset->type == qtype)					break;			break;		}	if (rdataset != NULL) {		ISC_LIST_UNLINK(msg->sections[section], name, link);		ISC_LIST_PREPEND(msg->sections[section], name, link);		ISC_LIST_UNLINK(name->list, rdataset, link);		ISC_LIST_PREPEND(name->list, rdataset, link);		rdataset->attributes |= DNS_RDATASETATTR_REQUIREDGLUE;	}}/* * 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, need_wildcardproof;	unsigned int n, nlabels;	dns_namereln_t namereln;	int order;	isc_buffer_t *dbuf;	isc_buffer_t b;	isc_result_t result, eresult;	dns_fixedname_t fixed;	dns_fixedname_t wildcardname;	dns_dbversion_t *version;	dns_zone_t *zone;	dns_rdata_cname_t cname;	dns_rdata_dname_t dname;	unsigned int options;	isc_boolean_t empty_wild;	dns_rdataset_t *noqname;	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;	need_wildcardproof = ISC_FALSE;	empty_wild = ISC_FALSE;	options = 0;	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_rrsig)			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_rrsig)		type = dns_rdatatype_any;	else		type = qtype; restart:	CTRACE("query_find: restart");	want_restart = ISC_FALSE;	authoritative = ISC_FALSE;	version = NULL;	need_wildcardproof = ISC_FALSE;	if (client->view->checknames &&	    !dns_rdata_checkowner(client->query.qname,				  client->message->rdclass,				  qtype, ISC_FALSE)) {		char namebuf[DNS_NAME_FORMATSIZE];		char typename[DNS_RDATATYPE_FORMATSIZE];		char classname[DNS_RDATACLASS_FORMATSIZE];		dns_name_format(client->query.qname, namebuf, sizeof(namebuf));		dns_rdatatype_format(qtype, typename, sizeof(typename));		dns_rdataclass_format(client->message->rdclass, classname,				      sizeof(classname));		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,			      NS_LOGMODULE_QUERY, ISC_LOG_ERROR,			      "check-names failure %s/%s/%s", namebuf,			      typename, classname);		QUERY_ERROR(DNS_R_REFUSED);		goto cleanup;	}	/*	 * First we must find the right database.	 */	options = 0;	if (dns_rdatatype_atparent(qtype) &&	    !dns_name_equal(client->query.qname, dns_rootname))		options |= DNS_GETDB_NOEXACT;	result = query_getdb(client, client->query.qname, qtype, options,			    

⌨️ 快捷键说明

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