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

📄 resolver.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t)r.length);		isc_buffer_add(&tcpbuffer, r.length);	}	/*	 * We're now done with the query message.	 */	dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);	socket = dns_dispatch_getsocket(query->dispatch);	/*	 * Send the query!	 */	if ((query->options & DNS_FETCHOPT_TCP) == 0)		address = &query->addrinfo->sockaddr;	isc_buffer_usedregion(buffer, &r);	/*	 * XXXRTH  Make sure we don't send to ourselves!  We should probably	 *	   prune out these addresses when we get them from the ADB.	 */	result = isc_socket_sendto(socket, &r, task, resquery_senddone,				   query, address, NULL);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	query->sends++;	QTRACE("sent");	return (ISC_R_SUCCESS); cleanup_message:	if (cleanup_cctx)		dns_compress_invalidate(&cctx);	dns_message_reset(fctx->qmessage, DNS_MESSAGE_INTENTRENDER);	/*	 * Stop the dispatcher from listening.	 */	dns_dispatch_removeresponse(&query->dispentry, NULL); cleanup_temps:	if (qname != NULL)		dns_message_puttempname(fctx->qmessage, &qname);	if (qrdataset != NULL)		dns_message_puttemprdataset(fctx->qmessage, &qrdataset);	return (result);}static voidresquery_connected(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;	unsigned int attrs;	fetchctx_t *fctx;	REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);	REQUIRE(VALID_QUERY(query));	QTRACE("connected");	UNUSED(task);	/*	 * XXXRTH	 *	 * Currently we don't wait for the connect event before retrying	 * a query.  This means that if we get really behind, we may end	 * up doing extra work!	 */	query->connects--;	fctx = query->fctx;	if (RESQUERY_CANCELED(query)) {		/*		 * This query was canceled while the connect() was in		 * progress.		 */		isc_socket_detach(&query->tcpsocket);		resquery_destroy(&query);	} else {		switch (sevent->result) {		case ISC_R_SUCCESS:			/*			 * We are connected.  Create a dispatcher and			 * send the query.			 */			attrs = 0;			attrs |= DNS_DISPATCHATTR_TCP;			attrs |= DNS_DISPATCHATTR_PRIVATE;			attrs |= DNS_DISPATCHATTR_CONNECTED;			if (isc_sockaddr_pf(&query->addrinfo->sockaddr) ==			    AF_INET)				attrs |= DNS_DISPATCHATTR_IPV4;			else				attrs |= DNS_DISPATCHATTR_IPV6;			attrs |= DNS_DISPATCHATTR_MAKEQUERY;			result = dns_dispatch_createtcp(query->dispatchmgr,						     query->tcpsocket,						     query->fctx->res->taskmgr,						     4096, 2, 1, 1, 3, attrs,						     &query->dispatch);			/*			 * Regardless of whether dns_dispatch_create()			 * succeeded or not, we don't need our reference			 * to the socket anymore.			 */			isc_socket_detach(&query->tcpsocket);			if (result == ISC_R_SUCCESS)				result = resquery_send(query);			if (result != ISC_R_SUCCESS) {				fctx_cancelquery(&query, NULL, NULL,						 ISC_FALSE);				fctx_done(fctx, result);			}			break;		case ISC_R_NETUNREACH:		case ISC_R_HOSTUNREACH:		case ISC_R_CONNREFUSED:		case ISC_R_NOPERM:		case ISC_R_ADDRNOTAVAIL:		case ISC_R_CONNECTIONRESET:			/*			 * No route to remote.			 */			isc_socket_detach(&query->tcpsocket);			fctx_cancelquery(&query, NULL, NULL, ISC_TRUE);			retry = ISC_TRUE;			break;		default:			isc_socket_detach(&query->tcpsocket);			fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);			break;		}	}	isc_event_free(&event);		if (retry) {		/*		 * Behave as if the idle timer has expired.  For TCP		 * connections 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 voidfctx_finddone(isc_task_t *task, isc_event_t *event) {	fetchctx_t *fctx;	dns_adbfind_t *find;	dns_resolver_t *res;	isc_boolean_t want_try = ISC_FALSE;	isc_boolean_t want_done = ISC_FALSE;	isc_boolean_t bucket_empty = ISC_FALSE;	unsigned int bucketnum;	find = event->ev_sender;	fctx = event->ev_arg;	REQUIRE(VALID_FCTX(fctx));	res = fctx->res;	UNUSED(task);	FCTXTRACE("finddone");	INSIST(fctx->pending > 0);	fctx->pending--;	if (ADDRWAIT(fctx)) {		/*		 * The fetch is waiting for a name to be found.		 */		INSIST(!SHUTTINGDOWN(fctx));		fctx->attributes &= ~FCTX_ATTR_ADDRWAIT;		if (event->ev_type == DNS_EVENT_ADBMOREADDRESSES)			want_try = ISC_TRUE;		else if (fctx->pending == 0) {			/*			 * We've got nothing else to wait for and don't			 * know the answer.  There's nothing to do but			 * fail the fctx.			 */			want_done = ISC_TRUE;		}	} else if (SHUTTINGDOWN(fctx) && fctx->pending == 0 &&		   fctx->nqueries == 0 && ISC_LIST_EMPTY(fctx->validators)) {		bucketnum = fctx->bucketnum;		LOCK(&res->buckets[bucketnum].lock);		/*		 * Note that we had to wait until we had the lock before		 * looking at fctx->references.		 */		if (fctx->references == 0)			bucket_empty = fctx_destroy(fctx);		UNLOCK(&res->buckets[bucketnum].lock);	}	isc_event_free(&event);	dns_adb_destroyfind(&find);	if (want_try)		fctx_try(fctx);	else if (want_done)		fctx_done(fctx, ISC_R_FAILURE);	else if (bucket_empty)		empty_bucket(res);}static inline isc_boolean_tbad_server(fetchctx_t *fctx, isc_sockaddr_t *address) {	isc_sockaddr_t *sa;	for (sa = ISC_LIST_HEAD(fctx->bad);	     sa != NULL;	     sa = ISC_LIST_NEXT(sa, link)) {		if (isc_sockaddr_equal(sa, address))			return (ISC_TRUE);	}	return (ISC_FALSE);}static inline isc_boolean_tmark_bad(fetchctx_t *fctx) {	dns_adbfind_t *curr;	dns_adbaddrinfo_t *addrinfo;	isc_boolean_t all_bad = ISC_TRUE;	/*	 * Mark all known bad servers, so we don't try to talk to them	 * again.	 */	/*	 * Mark any bad nameservers.	 */	for (curr = ISC_LIST_HEAD(fctx->finds);	     curr != NULL;	     curr = ISC_LIST_NEXT(curr, publink)) {		for (addrinfo = ISC_LIST_HEAD(curr->list);		     addrinfo != NULL;		     addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {			if (bad_server(fctx, &addrinfo->sockaddr))				addrinfo->flags |= FCTX_ADDRINFO_MARK;			else				all_bad = ISC_FALSE;		}	}	/*	 * Mark any bad forwarders.	 */	for (addrinfo = ISC_LIST_HEAD(fctx->forwaddrs);	     addrinfo != NULL;	     addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {		if (bad_server(fctx, &addrinfo->sockaddr))			addrinfo->flags |= FCTX_ADDRINFO_MARK;		else			all_bad = ISC_FALSE;	}	/*	 * Mark any bad alternates.	 */	for (curr = ISC_LIST_HEAD(fctx->altfinds);	     curr != NULL;	     curr = ISC_LIST_NEXT(curr, publink)) {		for (addrinfo = ISC_LIST_HEAD(curr->list);		     addrinfo != NULL;		     addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {			if (bad_server(fctx, &addrinfo->sockaddr))				addrinfo->flags |= FCTX_ADDRINFO_MARK;			else				all_bad = ISC_FALSE;		}	}	for (addrinfo = ISC_LIST_HEAD(fctx->altaddrs);	     addrinfo != NULL;	     addrinfo = ISC_LIST_NEXT(addrinfo, publink)) {		if (bad_server(fctx, &addrinfo->sockaddr))			addrinfo->flags |= FCTX_ADDRINFO_MARK;		else			all_bad = ISC_FALSE;	}	return (all_bad);}static voidadd_bad(fetchctx_t *fctx, isc_sockaddr_t *address, isc_result_t reason) {	char namebuf[DNS_NAME_FORMATSIZE];	char addrbuf[ISC_SOCKADDR_FORMATSIZE];	char classbuf[64];	char typebuf[64];	char code[64];	isc_buffer_t b;	isc_sockaddr_t *sa;	const char *sep1, *sep2;	if (bad_server(fctx, address)) {		/*		 * We already know this server is bad.		 */		return;	}	FCTXTRACE("add_bad");	sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,			 sizeof(*sa));	if (sa == NULL)		return;	*sa = *address;	ISC_LIST_INITANDAPPEND(fctx->bad, sa, link);	if (reason == DNS_R_LAME)	/* already logged */		return;	if (reason == DNS_R_UNEXPECTEDRCODE) {		isc_buffer_init(&b, code, sizeof(code) - 1);		dns_rcode_totext(fctx->rmessage->rcode, &b);		code[isc_buffer_usedlength(&b)] = '\0';		sep1 = "(";		sep2 = ") ";	} else if (reason == DNS_R_UNEXPECTEDOPCODE) {		isc_buffer_init(&b, code, sizeof(code) - 1);		dns_opcode_totext((dns_opcode_t)fctx->rmessage->opcode, &b);		code[isc_buffer_usedlength(&b)] = '\0';		sep1 = "(";		sep2 = ") ";	} else {		code[0] = '\0';		sep1 = "";		sep2 = "";	}	dns_name_format(&fctx->name, namebuf, sizeof(namebuf));	dns_rdatatype_format(fctx->type, typebuf, sizeof(typebuf));	dns_rdataclass_format(fctx->res->rdclass, classbuf, sizeof(classbuf));	isc_sockaddr_format(address, addrbuf, sizeof(addrbuf));	isc_log_write(dns_lctx, DNS_LOGCATEGORY_LAME_SERVERS,		      DNS_LOGMODULE_RESOLVER, ISC_LOG_INFO,		      "%s %s%s%sresolving '%s/%s/%s': %s",		      dns_result_totext(reason), sep1, code, sep2,		      namebuf, typebuf, classbuf, addrbuf);}static voidsort_adbfind(dns_adbfind_t *find) {	dns_adbaddrinfo_t *best, *curr;	dns_adbaddrinfolist_t sorted;	/*	 * Lame N^2 bubble sort.	 */	ISC_LIST_INIT(sorted);	while (!ISC_LIST_EMPTY(find->list)) {		best = ISC_LIST_HEAD(find->list);		curr = ISC_LIST_NEXT(best, publink);		while (curr != NULL) {			if (curr->srtt < best->srtt)				best = curr;			curr = ISC_LIST_NEXT(curr, publink);		}		ISC_LIST_UNLINK(find->list, best, publink);		ISC_LIST_APPEND(sorted, best, publink);	}	find->list = sorted;}static voidsort_finds(fetchctx_t *fctx) {	dns_adbfind_t *best, *curr;	dns_adbfindlist_t sorted;	dns_adbaddrinfo_t *addrinfo, *bestaddrinfo;	/*	 * Lame N^2 bubble sort.	 */	ISC_LIST_INIT(sorted);	while (!ISC_LIST_EMPTY(fctx->finds)) {		best = ISC_LIST_HEAD(fctx->finds);		bestaddrinfo = ISC_LIST_HEAD(best->list);		INSIST(bestaddrinfo != NULL);		curr = ISC_LIST_NEXT(best, publink);		while (curr != NULL) {			addrinfo = ISC_LIST_HEAD(curr->list);			INSIST(addrinfo != NULL);			if (addrinfo->srtt < bestaddrinfo->srtt) {				best = curr;				bestaddrinfo = addrinfo;			}			curr = ISC_LIST_NEXT(curr, publink);		}		ISC_LIST_UNLINK(fctx->finds, best, publink);		ISC_LIST_APPEND(sorted, best, publink);	}	fctx->finds = sorted;	ISC_LIST_INIT(sorted);	while (!ISC_LIST_EMPTY(fctx->altfinds)) {		best = ISC_LIST_HEAD(fctx->altfinds);		bestaddrinfo = ISC_LIST_HEAD(best->list);		INSIST(bestaddrinfo != NULL);		curr = ISC_LIST_NEXT(best, publink);		while (curr != NULL) {			addrinfo = ISC_LIST_HEAD(curr->list);			INSIST(addrinfo != NULL);			if (addrinfo->srtt < bestaddrinfo->srtt) {				best = curr;				bestaddrinfo = addrinfo;			}			curr = ISC_LIST_NEXT(curr, publink);		}		ISC_LIST_UNLINK(fctx->altfinds, best, publink);		ISC_LIST_APPEND(sorted, best, publink);	}	fctx->altfinds = sorted;}static voidfindname(fetchctx_t *fctx, dns_name_t *name, in_port_t port,	 unsigned int options, unsigned int flags, isc_stdtime_t now,	 isc_boolean_t *need_alternate){	dns_adbaddrinfo_t *ai;	dns_adbfind_t *find;	dns_resolver_t *res;	isc_boolean_t unshared;	isc_result_t result;	res = fctx->res;	unshared = ISC_TF((fctx->options | DNS_FETCHOPT_UNSHARED) != 0);	/*	 * If this name is a subdomain of the query domain, tell	 * the ADB to start looking using zone/hint data. This keeps us	 * from getting stuck if the nameserver is beneath the zone cut	 * and we don't know its address (e.g. because the A record has	 * expired).	 */	if (dns_name_issubdomain(name, &fctx->domain))		options |= DNS_ADBFIND_STARTATZONE;	options |= DNS_ADBFIND_GLUEOK;	options |= DNS_ADBFIND_HINTOK;	/*	 * See what we know about this address.	 */	find = NULL;	result = dns_adb_createfind(fctx->adb,				    res->buckets[fctx->bucketnum].task,				    fctx_finddone, fctx, name,				    &fctx->name, fctx->type,				    options, now, NULL,				    res->view->dstport, &find);	if (result != ISC_R_SUCCESS) {		if (result == DNS_R_ALIAS) {			/*			 * XXXRTH  Follow the CNAME/DNAME chain?			 */			dns_adb_destroyfind(&find);		}	} else if (!ISC_LIST_EMPTY(find->list)) {		/*		 * We have at least some of the addresses for the		 * name.		 */		INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0);		sort_adbfind(find);		if (flags != 0 || port != 0) {			for (ai = ISC_LIST_HEAD(find->list);			     ai != NULL;			     ai = ISC_LIST_NEXT(ai, publink)) {				ai->flags |= flags;				if (port != 0)					isc_sockaddr_setport(&ai->sockaddr,							     port);			}		}		if ((flags & FCTX_ADDRINFO_FORWARDER) != 0)			ISC_LIST_APPEND(fctx->altfinds, find, publink);		else			ISC_LIST_APPEND(fctx->finds, find, publink);	} else {		/*		 * We don't know any of the addresses for this		 * name.		 */		if ((find->options & DNS_ADBFIND_WANTEVENT) != 0) {			/*			 * We're looking for them and will get an			 * event about it later.			 */

⌨️ 快捷键说明

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