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

📄 resolver.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
fctx_startidletimer(fetchctx_t *fctx) {	/*	 * Start the idle timer for fctx.  The lifetime timer continues	 * to be in effect.	 */	return (isc_timer_reset(fctx->timer, isc_timertype_once,				&fctx->expires, &fctx->interval,				ISC_FALSE));}/* * Stopping the idle timer is equivalent to calling fctx_starttimer(), but * we use fctx_stopidletimer for readability in the code below. */#define fctx_stopidletimer	fctx_starttimerstatic inline voidresquery_destroy(resquery_t **queryp) {	resquery_t *query;	REQUIRE(queryp != NULL);	query = *queryp;	REQUIRE(!ISC_LINK_LINKED(query, link));	INSIST(query->tcpsocket == NULL);	query->fctx->nqueries--;	if (SHUTTINGDOWN(query->fctx))		maybe_destroy(query->fctx);	/* Locks bucket. */	query->magic = 0;	isc_mem_put(query->mctx, query, sizeof(*query));	*queryp = NULL;}static voidfctx_cancelquery(resquery_t **queryp, dns_dispatchevent_t **deventp,		 isc_time_t *finish, isc_boolean_t no_response){	fetchctx_t *fctx;	resquery_t *query;	unsigned int rtt;	unsigned int factor;	dns_adbfind_t *find;	dns_adbaddrinfo_t *addrinfo;	query = *queryp;	fctx = query->fctx;	FCTXTRACE("cancelquery");	REQUIRE(!RESQUERY_CANCELED(query));	query->attributes |= RESQUERY_ATTR_CANCELED;	/*	 * Should we update the RTT?	 */	if (finish != NULL || no_response) {		if (finish != NULL) {			/*			 * We have both the start and finish times for this			 * packet, so we can compute a real RTT.			 */			rtt = (unsigned int)isc_time_microdiff(finish,							       &query->start);			factor = DNS_ADB_RTTADJDEFAULT;		} else {			/*			 * We don't have an RTT for this query.  Maybe the			 * packet was lost, or maybe this server is very			 * slow.  We don't know.  Increase the RTT.			 */			INSIST(no_response);			rtt = query->addrinfo->srtt + 200000;			if (rtt > 10000000)				rtt = 10000000;			/*			 * Replace the current RTT with our value.			 */			factor = DNS_ADB_RTTADJREPLACE;		}		dns_adb_adjustsrtt(fctx->adb, query->addrinfo, rtt, factor);	}	/*	 * Age RTTs of servers not tried.	 */	factor = DNS_ADB_RTTADJAGE;	if (finish != NULL)		for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);		     addrinfo != NULL;		     addrinfo = ISC_LIST_NEXT(addrinfo, publink))			if (UNMARKED(addrinfo))				dns_adb_adjustsrtt(fctx->adb, addrinfo,						   0, factor);	if (finish != NULL && TRIEDFIND(fctx))		for (find = ISC_LIST_HEAD(fctx->finds);		     find != NULL;		     find = ISC_LIST_NEXT(find, publink))			for (addrinfo = ISC_LIST_HEAD(find->list);			     addrinfo != NULL;			     addrinfo = ISC_LIST_NEXT(addrinfo, publink))				if (UNMARKED(addrinfo))					dns_adb_adjustsrtt(fctx->adb, addrinfo,							   0, factor);	if (finish != NULL && TRIEDALT(fctx)) {		for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);		     addrinfo != NULL;		     addrinfo = ISC_LIST_NEXT(addrinfo, publink))			if (UNMARKED(addrinfo))				dns_adb_adjustsrtt(fctx->adb, addrinfo,						   0, factor);		for (find = ISC_LIST_HEAD(fctx->altfinds);		     find != NULL;		     find = ISC_LIST_NEXT(find, publink))			for (addrinfo = ISC_LIST_HEAD(find->list);			     addrinfo != NULL;			     addrinfo = ISC_LIST_NEXT(addrinfo, publink))				if (UNMARKED(addrinfo))					dns_adb_adjustsrtt(fctx->adb, addrinfo,							   0, factor);	}	if (query->dispentry != NULL)		dns_dispatch_removeresponse(&query->dispentry, deventp);	ISC_LIST_UNLINK(fctx->queries, query, link);	if (query->tsig != NULL)		isc_buffer_free(&query->tsig);	if (query->tsigkey != NULL)		dns_tsigkey_detach(&query->tsigkey);	/*	 * Check for any outstanding socket events.  If they exist, cancel	 * them and let the event handlers finish the cleanup.  The resolver	 * only needs to worry about managing the connect and send events;	 * the dispatcher manages the recv events.	 */	if (RESQUERY_CONNECTING(query))		/*		 * Cancel the connect.		 */		isc_socket_cancel(query->tcpsocket, NULL,				  ISC_SOCKCANCEL_CONNECT);	else if (RESQUERY_SENDING(query))		/*		 * Cancel the pending send.		 */		isc_socket_cancel(dns_dispatch_getsocket(query->dispatch),				  NULL, ISC_SOCKCANCEL_SEND);	if (query->dispatch != NULL)		dns_dispatch_detach(&query->dispatch);	if (! (RESQUERY_CONNECTING(query) || RESQUERY_SENDING(query)))		/*		 * It's safe to destroy the query now.		 */		resquery_destroy(&query);}static voidfctx_cancelqueries(fetchctx_t *fctx, isc_boolean_t no_response) {	resquery_t *query, *next_query;	FCTXTRACE("cancelqueries");	for (query = ISC_LIST_HEAD(fctx->queries);	     query != NULL;	     query = next_query) {		next_query = ISC_LIST_NEXT(query, link);		fctx_cancelquery(&query, NULL, NULL, no_response);	}}static voidfctx_cleanupfinds(fetchctx_t *fctx) {	dns_adbfind_t *find, *next_find;	REQUIRE(ISC_LIST_EMPTY(fctx->queries));	for (find = ISC_LIST_HEAD(fctx->finds);	     find != NULL;	     find = next_find) {		next_find = ISC_LIST_NEXT(find, publink);		ISC_LIST_UNLINK(fctx->finds, find, publink);		dns_adb_destroyfind(&find);	}	fctx->find = NULL;}static voidfctx_cleanupaltfinds(fetchctx_t *fctx) {	dns_adbfind_t *find, *next_find;	REQUIRE(ISC_LIST_EMPTY(fctx->queries));	for (find = ISC_LIST_HEAD(fctx->altfinds);	     find != NULL;	     find = next_find) {		next_find = ISC_LIST_NEXT(find, publink);		ISC_LIST_UNLINK(fctx->altfinds, find, publink);		dns_adb_destroyfind(&find);	}	fctx->altfind = NULL;}static voidfctx_cleanupforwaddrs(fetchctx_t *fctx) {	dns_adbaddrinfo_t *addr, *next_addr;	REQUIRE(ISC_LIST_EMPTY(fctx->queries));	for (addr = ISC_LIST_HEAD(fctx->forwaddrs);	     addr != NULL;	     addr = next_addr) {		next_addr = ISC_LIST_NEXT(addr, publink);		ISC_LIST_UNLINK(fctx->forwaddrs, addr, publink);		dns_adb_freeaddrinfo(fctx->adb, &addr);	}}static voidfctx_cleanupaltaddrs(fetchctx_t *fctx) {	dns_adbaddrinfo_t *addr, *next_addr;	REQUIRE(ISC_LIST_EMPTY(fctx->queries));	for (addr = ISC_LIST_HEAD(fctx->altaddrs);	     addr != NULL;	     addr = next_addr) {		next_addr = ISC_LIST_NEXT(addr, publink);		ISC_LIST_UNLINK(fctx->altaddrs, addr, publink);		dns_adb_freeaddrinfo(fctx->adb, &addr);	}}static inline voidfctx_stopeverything(fetchctx_t *fctx, isc_boolean_t no_response) {	FCTXTRACE("stopeverything");	fctx_cancelqueries(fctx, no_response);	fctx_cleanupfinds(fctx);	fctx_cleanupaltfinds(fctx);	fctx_cleanupforwaddrs(fctx);	fctx_cleanupaltaddrs(fctx);	fctx_stoptimer(fctx);}static inline voidfctx_sendevents(fetchctx_t *fctx, isc_result_t result) {	dns_fetchevent_t *event, *next_event;	isc_task_t *task;	unsigned int count = 0;	isc_interval_t i;	isc_boolean_t logit = ISC_FALSE;	/*	 * Caller must be holding the appropriate bucket lock.	 */	REQUIRE(fctx->state == fetchstate_done);	FCTXTRACE("sendevents");	for (event = ISC_LIST_HEAD(fctx->events);	     event != NULL;	     event = next_event) {		next_event = ISC_LIST_NEXT(event, ev_link);		ISC_LIST_UNLINK(fctx->events, event, ev_link);		task = event->ev_sender;		event->ev_sender = fctx;		if (!HAVE_ANSWER(fctx))			event->result = result;		INSIST(result != ISC_R_SUCCESS ||		       dns_rdataset_isassociated(event->rdataset) ||		       fctx->type == dns_rdatatype_any ||		       fctx->type == dns_rdatatype_rrsig ||		       fctx->type == dns_rdatatype_sig);		isc_task_sendanddetach(&task, ISC_EVENT_PTR(&event));		count++;	}	if ((fctx->attributes & FCTX_ATTR_HAVEANSWER) != 0 &&	    fctx->spilled &&	    (count < fctx->res->spillatmax || fctx->res->spillatmax == 0)) {		LOCK(&fctx->res->lock);	    	if (count == fctx->res->spillat && !fctx->res->exiting) {			fctx->res->spillat += 5;			if (fctx->res->spillat > fctx->res->spillatmax &&			    fctx->res->spillatmax != 0)				fctx->res->spillat = fctx->res->spillatmax;			isc_interval_set(&i, 20 * 60, 0);			result = isc_timer_reset(fctx->res->spillattimer,						 isc_timertype_ticker, NULL,						 &i, ISC_TRUE);			RUNTIME_CHECK(result == ISC_R_SUCCESS);			logit = ISC_TRUE;		}		UNLOCK(&fctx->res->lock);		if (logit)			isc_log_write(dns_lctx, DNS_LOGCATEGORY_RESOLVER,				      DNS_LOGMODULE_RESOLVER, ISC_LOG_NOTICE,				      "clients-per-query increased to %u",				      count + 1);	}}static voidfctx_done(fetchctx_t *fctx, isc_result_t result) {	dns_resolver_t *res;	isc_boolean_t no_response;	FCTXTRACE("done");	res = fctx->res;	if (result == ISC_R_SUCCESS)		no_response = ISC_TRUE;	else		no_response = ISC_FALSE;	fctx_stopeverything(fctx, no_response);	LOCK(&res->buckets[fctx->bucketnum].lock);	fctx->state = fetchstate_done;	fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;	fctx_sendevents(fctx, result);	UNLOCK(&res->buckets[fctx->bucketnum].lock);}static voidresquery_senddone(isc_task_t *task, isc_event_t *event) {	isc_socketevent_t *sevent = (isc_socketevent_t *)event;	resquery_t *query = event->ev_arg;	isc_boolean_t retry = ISC_FALSE;	isc_result_t result;	fetchctx_t *fctx;	REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);	QTRACE("senddone");	/*	 * XXXRTH	 *	 * Currently we don't wait for the senddone event before retrying	 * a query.  This means that if we get really behind, we may end	 * up doing extra work!	 */	UNUSED(task);	INSIST(RESQUERY_SENDING(query));	query->sends--;	fctx = query->fctx;	if (RESQUERY_CANCELED(query)) {		if (query->sends == 0) {			/*			 * This query was canceled while the			 * isc_socket_sendto() was in progress.			 */			if (query->tcpsocket != NULL)				isc_socket_detach(&query->tcpsocket);			resquery_destroy(&query);		}	} else 		switch (sevent->result) {		case ISC_R_SUCCESS:			break;		case ISC_R_HOSTUNREACH:		case ISC_R_NETUNREACH:		case ISC_R_NOPERM:		case ISC_R_ADDRNOTAVAIL:		case ISC_R_CONNREFUSED:			/*			 * No route to remote.			 */			fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);			retry = ISC_TRUE;			break;		default:			fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);			break;		}	isc_event_free(&event);	if (retry) {		/*		 * Behave as if the idle timer has expired.  For TCP		 * this may not actually reflect the latest timer.		 */		fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;		result = fctx_stopidletimer(fctx);		if (result != ISC_R_SUCCESS)			fctx_done(fctx, result);		else			fctx_try(fctx);	}}static inline isc_result_tfctx_addopt(dns_message_t *message, unsigned int version, isc_uint16_t udpsize){ 	dns_rdataset_t *rdataset;	dns_rdatalist_t *rdatalist;	dns_rdata_t *rdata;	isc_result_t result;	rdatalist = NULL;	result = dns_message_gettemprdatalist(message, &rdatalist);	if (result != ISC_R_SUCCESS)		return (result);	rdata = NULL;	result = dns_message_gettemprdata(message, &rdata);	if (result != ISC_R_SUCCESS)		return (result);	rdataset = NULL;	result = dns_message_gettemprdataset(message, &rdataset);	if (result != ISC_R_SUCCESS)		return (result);	dns_rdataset_init(rdataset);	rdatalist->type = dns_rdatatype_opt;	rdatalist->covers = 0;	/*	 * Set Maximum UDP buffer size.	 */	rdatalist->rdclass = udpsize;	/*	 * Set EXTENDED-RCODE and Z to 0, DO to 1.	 */	rdatalist->ttl = (version << 16);	rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;	/*	 * No EDNS options.	 */	rdata->data = NULL;	rdata->length = 0;	rdata->rdclass = rdatalist->rdclass;	rdata->type = rdatalist->type;	rdata->flags = 0;	ISC_LIST_INIT(rdatalist->rdata);	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);	RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == ISC_R_SUCCESS);	return (dns_message_setopt(message, rdataset));}static inline voidfctx_setretryinterval(fetchctx_t *fctx, unsigned int rtt) {	unsigned int seconds;	unsigned int us;	/*	 * We retry every .5 seconds the first two times through the address	 * list, and then we do exponential back-off.	 */	if (fctx->restarts < 3)		us = 500000;	else		us = (500000 << (fctx->restarts - 2));	/*	 * Double the round-trip time.	 */	rtt *= 2;	/*	 * Always wait for at least the doubled round-trip time.	 */	if (us < rtt)		us = rtt;	/*	 * But don't ever wait for more than 10 seconds.	 */	if (us > 10000000)		us = 10000000;	seconds = us / 1000000;	us -= seconds * 1000000;	isc_interval_set(&fctx->interval, seconds, us * 1000);}static isc_result_tfctx_query(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo,	   unsigned int options){	dns_resolver_t *res;	isc_task_t *task;	isc_result_t result;	resquery_t *query;	isc_sockaddr_t addr;	isc_boolean_t have_addr = ISC_FALSE;

⌨️ 快捷键说明

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