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

📄 resolver.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (bucket_empty)		empty_bucket(res);}static voidfctx_start(isc_task_t *task, isc_event_t *event) {	fetchctx_t *fctx = event->ev_arg;	isc_boolean_t done = ISC_FALSE, bucket_empty = ISC_FALSE;	dns_resolver_t *res;	unsigned int bucketnum;	REQUIRE(VALID_FCTX(fctx));	UNUSED(task);	res = fctx->res;	bucketnum = fctx->bucketnum;	FCTXTRACE("start");	LOCK(&res->buckets[bucketnum].lock);	INSIST(fctx->state == fetchstate_init);	if (fctx->want_shutdown) {		/*		 * We haven't started this fctx yet, and we've been requested		 * to shut it down.		 */		fctx->attributes |= FCTX_ATTR_SHUTTINGDOWN;		fctx->state = fetchstate_done;		fctx_sendevents(fctx, ISC_R_CANCELED);		/*		 * Since we haven't started, we INSIST that we have no		 * pending ADB finds and no pending validations.		 */		INSIST(fctx->pending == 0);		INSIST(ISC_LIST_EMPTY(fctx->validators));		if (fctx->references == 0) {			/*			 * It's now safe to destroy this fctx.			 */			bucket_empty = fctx_destroy(fctx);		}		done = ISC_TRUE;	} else {		/*		 * Normal fctx startup.		 */		fctx->state = fetchstate_active;		/*		 * Reset the control event for later use in shutting down		 * the fctx.		 */		ISC_EVENT_INIT(event, sizeof(*event), 0, NULL,			       DNS_EVENT_FETCHCONTROL, fctx_doshutdown, fctx,			       NULL, NULL, NULL);	}	UNLOCK(&res->buckets[bucketnum].lock);	if (!done) {		/*		 * All is well.  Start working on the fetch.		 */		fctx_starttimer(fctx);		fctx_try(fctx);	} else if (bucket_empty)		empty_bucket(res);}/* * Fetch Creation, Joining, and Cancelation. */static inline isc_result_tfctx_join(fetchctx_t *fctx, isc_task_t *task, isc_taskaction_t action,	  void *arg, dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset,	  dns_fetch_t *fetch){	isc_task_t *clone;	dns_fetchevent_t *event;	FCTXTRACE("join");	/*	 * We store the task we're going to send this event to in the	 * sender field.  We'll make the fetch the sender when we actually	 * send the event.	 */	clone = NULL;	isc_task_attach(task, &clone);	event = (dns_fetchevent_t *)		isc_event_allocate(fctx->res->mctx, clone,				   DNS_EVENT_FETCHDONE,				   action, arg, sizeof *event);	if (event == NULL) {		isc_task_detach(&clone);		return (ISC_R_NOMEMORY);	}	event->result = DNS_R_SERVFAIL;	event->qtype = fctx->type;	event->db = NULL;	event->node = NULL;	event->rdataset = rdataset;	event->sigrdataset = sigrdataset;	event->fetch = fetch;	dns_fixedname_init(&event->foundname);	/*	 * Make sure that we can store the sigrdataset in the	 * first event if it is needed by any of the events.	 */	if (event->sigrdataset != NULL)		ISC_LIST_PREPEND(fctx->events, event, ev_link);	else		ISC_LIST_APPEND(fctx->events, event, ev_link);	fctx->references++;	fetch->magic = DNS_FETCH_MAGIC;	fetch->private = fctx;	return (ISC_R_SUCCESS);}static isc_result_tfctx_create(dns_resolver_t *res, dns_name_t *name, dns_rdatatype_t type,	    dns_name_t *domain, dns_rdataset_t *nameservers,	    unsigned int options, unsigned int bucketnum, fetchctx_t **fctxp){	fetchctx_t *fctx;	isc_result_t result = ISC_R_SUCCESS;	isc_result_t iresult;	isc_interval_t interval;	dns_fixedname_t qdomain;	unsigned int findoptions = 0;	/*	 * Caller must be holding the lock for bucket number 'bucketnum'.	 */	REQUIRE(fctxp != NULL && *fctxp == NULL);	fctx = isc_mem_get(res->mctx, sizeof *fctx);	if (fctx == NULL)		return (ISC_R_NOMEMORY);	FCTXTRACE("create");	dns_name_init(&fctx->name, NULL);	result = dns_name_dup(name, res->mctx, &fctx->name);	if (result != ISC_R_SUCCESS)		goto cleanup_fetch;	dns_name_init(&fctx->domain, NULL);	dns_rdataset_init(&fctx->nameservers);	fctx->type = type;	fctx->options = options;	/*	 * Note!  We do not attach to the task.  We are relying on the	 * resolver to ensure that this task doesn't go away while we are	 * using it.	 */	fctx->res = res;	fctx->references = 0;	fctx->bucketnum = bucketnum;	fctx->state = fetchstate_init;	fctx->want_shutdown = ISC_FALSE;	fctx->cloned = ISC_FALSE;	ISC_LIST_INIT(fctx->queries);	ISC_LIST_INIT(fctx->finds);	ISC_LIST_INIT(fctx->forwaddrs);	ISC_LIST_INIT(fctx->forwarders);	fctx->fwdpolicy = dns_fwdpolicy_none;	ISC_LIST_INIT(fctx->bad);	ISC_LIST_INIT(fctx->validators);	fctx->find = NULL;	fctx->pending = 0;	fctx->restarts = 0;	fctx->timeouts = 0;	if (dns_name_requiresedns(name))		fctx->attributes = FCTX_ATTR_NEEDEDNS0;	else		fctx->attributes = 0;	if (domain == NULL) {		dns_forwarders_t *forwarders = NULL;		result = dns_fwdtable_find(fctx->res->view->fwdtable,					   &fctx->name, &forwarders);		if (result == ISC_R_SUCCESS)			fctx->fwdpolicy = forwarders->fwdpolicy;		if (fctx->fwdpolicy != dns_fwdpolicy_only) {			/*			 * The caller didn't supply a query domain and			 * nameservers, and we're not in forward-only mode,			 * so find the best nameservers to use.			 */			if (type == dns_rdatatype_key)				findoptions |= DNS_DBFIND_NOEXACT;			dns_fixedname_init(&qdomain);			result = dns_view_findzonecut(res->view, name,					      dns_fixedname_name(&qdomain), 0,						      findoptions, ISC_TRUE,						      &fctx->nameservers,						      NULL);			if (result != ISC_R_SUCCESS)				goto cleanup_name;			result = dns_name_dup(dns_fixedname_name(&qdomain),					      res->mctx, &fctx->domain);			if (result != ISC_R_SUCCESS) {				dns_rdataset_disassociate(&fctx->nameservers);				goto cleanup_name;			}		} else {			/*			 * We're in forward-only mode.  Set the query domain			 * to ".".			 */			result = dns_name_dup(dns_rootname, res->mctx,					      &fctx->domain);			if (result != ISC_R_SUCCESS)				goto cleanup_name;		}	} else {		result = dns_name_dup(domain, res->mctx, &fctx->domain);		if (result != ISC_R_SUCCESS)			goto cleanup_name;		dns_rdataset_clone(nameservers, &fctx->nameservers);	}	INSIST(dns_name_issubdomain(&fctx->name, &fctx->domain));	fctx->qmessage = NULL;	result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTRENDER,				    &fctx->qmessage);	if (result != ISC_R_SUCCESS)		goto cleanup_domain;	fctx->rmessage = NULL;	result = dns_message_create(res->mctx, DNS_MESSAGE_INTENTPARSE,				    &fctx->rmessage);	if (result != ISC_R_SUCCESS)		goto cleanup_qmessage;	/*	 * Compute an expiration time for the entire fetch.	 */	isc_interval_set(&interval, 30, 0);		/* XXXRTH constant */	iresult = isc_time_nowplusinterval(&fctx->expires, &interval);	if (iresult != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_time_nowplusinterval: %s",				 isc_result_totext(iresult));		result = ISC_R_UNEXPECTED;		goto cleanup_rmessage;	}	/*	 * Default retry interval initialization.  We set the interval now	 * mostly so it won't be uninitialized.  It will be set to the	 * correct value before a query is issued.	 */	isc_interval_set(&fctx->interval, 2, 0);	/*	 * Create an inactive timer.  It will be made active when the fetch	 * is actually started.	 */	fctx->timer = NULL;	iresult = isc_timer_create(res->timermgr, isc_timertype_inactive,				   NULL, NULL,				   res->buckets[bucketnum].task, fctx_timeout,				   fctx, &fctx->timer);	if (iresult != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_timer_create: %s",				 isc_result_totext(iresult));		result = ISC_R_UNEXPECTED;		goto cleanup_rmessage;	}	/*	 * Attach to the view's cache and adb.	 */	fctx->cache = NULL;	dns_db_attach(res->view->cachedb, &fctx->cache);	fctx->adb = NULL;	dns_adb_attach(res->view->adb, &fctx->adb);	ISC_LIST_INIT(fctx->events);	ISC_LINK_INIT(fctx, link);	fctx->magic = FCTX_MAGIC;	ISC_LIST_APPEND(res->buckets[bucketnum].fctxs, fctx, link);	*fctxp = fctx;	return (ISC_R_SUCCESS); cleanup_rmessage:	dns_message_destroy(&fctx->rmessage); cleanup_qmessage:	dns_message_destroy(&fctx->qmessage); cleanup_domain:	if (dns_name_countlabels(&fctx->domain) > 0)		dns_name_free(&fctx->domain, res->mctx);	if (dns_rdataset_isassociated(&fctx->nameservers))		dns_rdataset_disassociate(&fctx->nameservers); cleanup_name:	dns_name_free(&fctx->name, res->mctx); cleanup_fetch:	isc_mem_put(res->mctx, fctx, sizeof *fctx);	return (result);}/* * Handle Responses */static inline isc_boolean_tis_lame(fetchctx_t *fctx) {	dns_message_t *message = fctx->rmessage;	dns_name_t *name;	dns_rdataset_t *rdataset;	isc_result_t result;	if (message->rcode != dns_rcode_noerror &&	    message->rcode != dns_rcode_nxdomain)		return (ISC_FALSE);	if (message->counts[DNS_SECTION_ANSWER] != 0)		return (ISC_FALSE);	if (message->counts[DNS_SECTION_AUTHORITY] == 0)		return (ISC_FALSE);	result = dns_message_firstname(message, DNS_SECTION_AUTHORITY);	while (result == ISC_R_SUCCESS) {		name = NULL;		dns_message_currentname(message, DNS_SECTION_AUTHORITY, &name);		for (rdataset = ISC_LIST_HEAD(name->list);		     rdataset != NULL;		     rdataset = ISC_LIST_NEXT(rdataset, link)) {			dns_namereln_t namereln;			int order;			unsigned int labels, bits;			if (rdataset->type != dns_rdatatype_ns)				continue;			namereln = dns_name_fullcompare(name, &fctx->domain,				   			&order, &labels, &bits);			if (namereln == dns_namereln_equal &&			    (message->flags & DNS_MESSAGEFLAG_AA) != 0)				return (ISC_FALSE);			if (namereln == dns_namereln_subdomain)				return (ISC_FALSE);			return (ISC_TRUE);		}		result = dns_message_nextname(message, DNS_SECTION_AUTHORITY);	}	return (ISC_FALSE);}static inline voidlog_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {	char namebuf[DNS_NAME_FORMATSIZE];	char domainbuf[DNS_NAME_FORMATSIZE];		char addrbuf[ISC_SOCKADDR_FORMATSIZE];		dns_name_format(&fctx->name, namebuf, sizeof(namebuf));	dns_name_format(&fctx->domain, domainbuf, sizeof(domainbuf));	isc_sockaddr_format(&addrinfo->sockaddr, addrbuf, sizeof(addrbuf));	isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,		      DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,		      "lame server resolving '%s' (in '%s'?): %s",		      namebuf, domainbuf, addrbuf);}static inline isc_result_tsame_question(fetchctx_t *fctx) {	isc_result_t result;	dns_message_t *message = fctx->rmessage;	dns_name_t *name;	dns_rdataset_t *rdataset;	/*	 * Caller must be holding the fctx lock.	 */	/*	 * XXXRTH  Currently we support only one question.	 */	if (message->counts[DNS_SECTION_QUESTION] != 1)		return (DNS_R_FORMERR);	result = dns_message_firstname(message, DNS_SECTION_QUESTION);	if (result != ISC_R_SUCCESS)		return (result);	name = NULL;	dns_message_currentname(message, DNS_SECTION_QUESTION, &name);	rdataset = ISC_LIST_HEAD(name->list);	INSIST(rdataset != NULL);	INSIST(ISC_LIST_NEXT(rdataset, link) == NULL);	if (fctx->type != rdataset->type ||	    fctx->res->rdclass != rdataset->rdclass ||	    !dns_name_equal(&fctx->name, name))		return (DNS_R_FORMERR);	return (ISC_R_SUCCESS);}static voidclone_results(fetchctx_t *fctx) {	dns_fetchevent_t *event, *hevent;	isc_result_t result;	dns_name_t *name, *hname;	/*	 * Set up any other events to have the same data as the first	 * event.	 *	 * Caller must be holding the appropriate lock.	 */	fctx->cloned = ISC_TRUE;	hevent = ISC_LIST_HEAD(fctx->events);	if (hevent == NULL)		return;	hname = dns_fixedname_name(&hevent->foundname);	for (event = ISC_LIST_NEXT(hevent, ev_link);	     event != NULL;	     event = ISC_LIST_NEXT(event, ev_link)) {		name = dns_fixedname_name(&event->foundname);		result = dns_name_copy(hname, name, NULL);		if (result != ISC_R_SUCCESS)			event->result = result;		else			event->result = hevent->result;		dns_db_attach(hevent->db, &event->db);		dns_db_attachnode(hevent->db, hevent->node, &event->node);		INSIST(hevent->rdataset != NULL);		INSIST(event->rdataset != NULL);		if (dns_rdataset_isassociated(hevent->rdataset))			dns_rdataset_clone(hevent->rdataset, event->rdataset);		INSIST(! (hevent->sigrdataset == NULL &&			  event->sigrdataset != NULL));		if (hevent->sigrdataset != NULL &&		    dns_rdataset_isassociated(hevent->sigrdataset) &&		    event->sigrdataset != NULL)			dns_rdataset_clone(hevent->sigrdataset,					   event->sigrdataset);	}}#define CACHE(r)	(((r)->attributes & DNS_RDATASETATTR_CACHE) != 0)#define ANSWER(r)	(((r)->attributes & DNS_RDATASETATTR_ANSWER) != 0)#define ANSWERSIG(r)	(((r)->attributes & DNS_RDATASETATTR_ANSWERSIG) != 0)#define EXTERNAL(r)	(((r)->attributes & DNS_RDATASETATTR_EXTERNAL) != 0)#define CHAINING(r)	(((r)->attributes & DNS_RDATASETATTR_CHAINING) != 0)#define CHASE(r)	(((r)->attributes & DNS_RDATASETATTR_CHASE) != 0)/* * Destroy '*fctx' if it is ready to be destroyed (i.e., if it has * no references and is no longer waiting for any events).  If this * was the last fctx in the resolver, destroy the resolver. * * Requires: *	'*fctx' is shutting down. */static voidmaybe_destroy(fetchctx_t *fctx) {	unsigned int bucketnum;	isc_boolean_t bucket_empty = ISC_FALSE;	dns_resolver_t *res = fctx->res;	REQUIRE(SHUTTINGDOWN(fctx));	if (fctx->pending != 0 || !ISC_LIST_EMPTY(fctx->validators))		return;	bucketnum = fctx->bucketnum;	LOCK(&res->buckets[bucketnum].lock);	if (fctx->references == 0)		bucket_empty = fctx_destroy(fctx);	UNLOCK(&res->buckets[bucketnum].lock);	if (bucket_empty)		empty_bucket(res);}/* * The validator has finished. */static voidvalidated(isc_task_t *task, isc_event_t *event) {	isc_result_t result = ISC_R_SUCCESS;	isc_result_t eresult = ISC_R_SUCCESS;	isc_stdtime_t now;	fetchctx_t *fctx;	dns_validatorevent_t *vevent;	dns_fetchevent_t *hevent;	dns_rdataset_t *ardataset = NULL;	dns_rdataset_t *asigrdataset = NULL;	dns_dbnode_t *node = NULL;	isc_boolean_t negative;	isc_boolean_t chaining;	isc_boolean_t sentresponse;	isc_uint32_t tt

⌨️ 快捷键说明

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