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

📄 resolver.c

📁 非常好的dns解析软件
💻 C
📖 第 1 页 / 共 5 页
字号:
	FCTXTRACE("query");	res = fctx->res;	task = res->buckets[fctx->bucketnum].task;	fctx_setretryinterval(fctx, addrinfo->srtt);	result = fctx_startidletimer(fctx);	if (result != ISC_R_SUCCESS)		return (result);	INSIST(ISC_LIST_EMPTY(fctx->validators));	dns_message_reset(fctx->rmessage, DNS_MESSAGE_INTENTPARSE);	query = isc_mem_get(res->buckets[fctx->bucketnum].mctx,			    sizeof(*query));	if (query == NULL) {		result = ISC_R_NOMEMORY;		goto stop_idle_timer;	}	query->mctx = res->buckets[fctx->bucketnum].mctx;	query->options = options;	query->attributes = 0;	query->sends = 0;	query->connects = 0;	/*	 * Note that the caller MUST guarantee that 'addrinfo' will remain	 * valid until this query is canceled.	 */	query->addrinfo = addrinfo;	TIME_NOW(&query->start);	/*	 * If this is a TCP query, then we need to make a socket and	 * a dispatch for it here.  Otherwise we use the resolver's	 * shared dispatch.	 */	query->dispatchmgr = res->dispatchmgr;	query->dispatch = NULL;	query->tcpsocket = NULL;	if (res->view->peers != NULL) {		dns_peer_t *peer = NULL;		isc_netaddr_t dstip;		isc_netaddr_fromsockaddr(&dstip, &addrinfo->sockaddr);		result = dns_peerlist_peerbyaddr(res->view->peers,					         &dstip, &peer);		if (result == ISC_R_SUCCESS) {			result = dns_peer_getquerysource(peer, &addr);			if (result == ISC_R_SUCCESS)				have_addr = ISC_TRUE;		}	}	if ((query->options & DNS_FETCHOPT_TCP) != 0) {		int pf;		pf = isc_sockaddr_pf(&addrinfo->sockaddr);		if (!have_addr) {			switch (pf) {			case PF_INET:				result =				  dns_dispatch_getlocaladdress(res->dispatchv4,							       &addr);				break;			case PF_INET6:				result =				  dns_dispatch_getlocaladdress(res->dispatchv6,							       &addr);				break;			default:				result = ISC_R_NOTIMPLEMENTED;				break;			}			if (result != ISC_R_SUCCESS)				goto cleanup_query;		}		isc_sockaddr_setport(&addr, 0);		result = isc_socket_create(res->socketmgr, pf,					   isc_sockettype_tcp,					   &query->tcpsocket);		if (result != ISC_R_SUCCESS)			goto cleanup_query;#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT		result = isc_socket_bind(query->tcpsocket, &addr);		if (result != ISC_R_SUCCESS)			goto cleanup_socket;#endif		/*		 * A dispatch will be created once the connect succeeds.		 */	} else {		if (have_addr) {			unsigned int attrs, attrmask;			attrs = DNS_DISPATCHATTR_UDP;			switch (isc_sockaddr_pf(&addr)) {			case AF_INET:				attrs |= DNS_DISPATCHATTR_IPV4;				break;			case AF_INET6:				attrs |= DNS_DISPATCHATTR_IPV6;				break;			default:				result = ISC_R_NOTIMPLEMENTED;				goto cleanup_query;			}			attrmask = DNS_DISPATCHATTR_UDP;			attrmask |= DNS_DISPATCHATTR_TCP;			attrmask |= DNS_DISPATCHATTR_IPV4;			attrmask |= DNS_DISPATCHATTR_IPV6;			result = dns_dispatch_getudp(res->dispatchmgr,						     res->socketmgr,						     res->taskmgr, &addr,						     4096, 1000, 32768, 16411,						     16433, attrs, attrmask,						     &query->dispatch);			if (result != ISC_R_SUCCESS)				goto cleanup_query;		} else {			switch (isc_sockaddr_pf(&addrinfo->sockaddr)) {			case PF_INET:				dns_dispatch_attach(res->dispatchv4,						    &query->dispatch);				break;			case PF_INET6:				dns_dispatch_attach(res->dispatchv6,						    &query->dispatch);				break;			default:				result = ISC_R_NOTIMPLEMENTED;				goto cleanup_query;			}		}		/*		 * We should always have a valid dispatcher here.  If we		 * don't support a protocol family, then its dispatcher		 * will be NULL, but we shouldn't be finding addresses for		 * protocol types we don't support, so the dispatcher		 * we found should never be NULL.		 */		INSIST(query->dispatch != NULL);	}	query->dispentry = NULL;	query->fctx = fctx;	query->tsig = NULL;	query->tsigkey = NULL;	ISC_LINK_INIT(query, link);	query->magic = QUERY_MAGIC;	if ((query->options & DNS_FETCHOPT_TCP) != 0) {		/*		 * Connect to the remote server.		 *		 * XXXRTH  Should we attach to the socket?		 */		result = isc_socket_connect(query->tcpsocket,					    &addrinfo->sockaddr, task,					    resquery_connected, query);		if (result != ISC_R_SUCCESS)			goto cleanup_socket;		query->connects++;		QTRACE("connecting via TCP");	} else {		result = resquery_send(query);		if (result != ISC_R_SUCCESS)			goto cleanup_dispatch;	}	ISC_LIST_APPEND(fctx->queries, query, link);	query->fctx->nqueries++;	return (ISC_R_SUCCESS); cleanup_socket:	isc_socket_detach(&query->tcpsocket); cleanup_dispatch:	if (query->dispatch != NULL)		dns_dispatch_detach(&query->dispatch); cleanup_query:	query->magic = 0;	isc_mem_put(res->buckets[fctx->bucketnum].mctx,		    query, sizeof(*query)); stop_idle_timer:	RUNTIME_CHECK(fctx_stopidletimer(fctx) == ISC_R_SUCCESS);	return (result);}static isc_boolean_ttriededns(fetchctx_t *fctx, isc_sockaddr_t *address) {	isc_sockaddr_t *sa;	for (sa = ISC_LIST_HEAD(fctx->edns);	     sa != NULL;	     sa = ISC_LIST_NEXT(sa, link)) {		if (isc_sockaddr_equal(sa, address))			return (ISC_TRUE);	}	return (ISC_FALSE);}static voidadd_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {	isc_sockaddr_t *sa;	if (triededns(fctx, address))		return;	sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,			 sizeof(*sa));	if (sa == NULL)		return;	*sa = *address;	ISC_LIST_INITANDAPPEND(fctx->edns, sa, link);}static isc_boolean_ttriededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {	isc_sockaddr_t *sa;	for (sa = ISC_LIST_HEAD(fctx->edns512);	     sa != NULL;	     sa = ISC_LIST_NEXT(sa, link)) {		if (isc_sockaddr_equal(sa, address))			return (ISC_TRUE);	}	return (ISC_FALSE);}static voidadd_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {	isc_sockaddr_t *sa;	if (triededns512(fctx, address))		return;	sa = isc_mem_get(fctx->res->buckets[fctx->bucketnum].mctx,			 sizeof(*sa));	if (sa == NULL)		return;	*sa = *address;	ISC_LIST_INITANDAPPEND(fctx->edns512, sa, link);}static isc_result_tresquery_send(resquery_t *query) {	fetchctx_t *fctx;	isc_result_t result;	dns_name_t *qname = NULL;	dns_rdataset_t *qrdataset = NULL;	isc_region_t r;	dns_resolver_t *res;	isc_task_t *task;	isc_socket_t *socket;	isc_buffer_t tcpbuffer;	isc_sockaddr_t *address;	isc_buffer_t *buffer;	isc_netaddr_t ipaddr;	dns_tsigkey_t *tsigkey = NULL;	dns_peer_t *peer = NULL;	isc_boolean_t useedns;	dns_compress_t cctx;	isc_boolean_t cleanup_cctx = ISC_FALSE;	isc_boolean_t secure_domain;	fctx = query->fctx;	QTRACE("send");	res = fctx->res;	task = res->buckets[fctx->bucketnum].task;	address = NULL;	if ((query->options & DNS_FETCHOPT_TCP) != 0) {		/*		 * Reserve space for the TCP message length.		 */		isc_buffer_init(&tcpbuffer, query->data, sizeof(query->data));		isc_buffer_init(&query->buffer, query->data + 2,				sizeof(query->data) - 2);		buffer = &tcpbuffer;	} else {		isc_buffer_init(&query->buffer, query->data,				sizeof(query->data));		buffer = &query->buffer;	}	result = dns_message_gettempname(fctx->qmessage, &qname);	if (result != ISC_R_SUCCESS)		goto cleanup_temps;	result = dns_message_gettemprdataset(fctx->qmessage, &qrdataset);	if (result != ISC_R_SUCCESS)		goto cleanup_temps;	/*	 * Get a query id from the dispatch.	 */	result = dns_dispatch_addresponse(query->dispatch,					  &query->addrinfo->sockaddr,					  task,					  resquery_response,					  query,					  &query->id,					  &query->dispentry);	if (result != ISC_R_SUCCESS)		goto cleanup_temps;	fctx->qmessage->opcode = dns_opcode_query;	/*	 * Set up question.	 */	dns_name_init(qname, NULL);	dns_name_clone(&fctx->name, qname);	dns_rdataset_init(qrdataset);	dns_rdataset_makequestion(qrdataset, res->rdclass, fctx->type);	ISC_LIST_APPEND(qname->list, qrdataset, link);	dns_message_addname(fctx->qmessage, qname, DNS_SECTION_QUESTION);	qname = NULL;	qrdataset = NULL;	/*	 * Set RD if the client has requested that we do a recursive query,	 * or if we're sending to a forwarder.	 */	if ((query->options & DNS_FETCHOPT_RECURSIVE) != 0 ||	    ISFORWARDER(query->addrinfo))		fctx->qmessage->flags |= DNS_MESSAGEFLAG_RD;	/*	 * Set CD if the client says don't validate or the question is	 * under a secure entry point.	 */	if ((query->options & DNS_FETCHOPT_NOVALIDATE) != 0) {		fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;	} else if (res->view->enablevalidation) {		result = dns_keytable_issecuredomain(res->view->secroots,						     &fctx->name,						     &secure_domain);		if (result != ISC_R_SUCCESS)			secure_domain = ISC_FALSE;		if (res->view->dlv != NULL)			secure_domain = ISC_TRUE;		if (secure_domain)			fctx->qmessage->flags |= DNS_MESSAGEFLAG_CD;	}	/*	 * We don't have to set opcode because it defaults to query.	 */	fctx->qmessage->id = query->id;	/*	 * Convert the question to wire format.	 */	result = dns_compress_init(&cctx, -1, fctx->res->mctx);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	cleanup_cctx = ISC_TRUE;	result = dns_message_renderbegin(fctx->qmessage, &cctx,					 &query->buffer);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	result = dns_message_rendersection(fctx->qmessage,					   DNS_SECTION_QUESTION, 0);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	peer = NULL;	isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);	(void) dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);	/*	 * The ADB does not know about servers with "edns no".  Check this,	 * and then inform the ADB for future use.	 */	if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0 &&	    peer != NULL &&	    dns_peer_getsupportedns(peer, &useedns) == ISC_R_SUCCESS &&	    !useedns)	{		query->options |= DNS_FETCHOPT_NOEDNS0;		dns_adb_changeflags(fctx->adb,				    query->addrinfo,				    DNS_FETCHOPT_NOEDNS0,				    DNS_FETCHOPT_NOEDNS0);	}	/*	 * Use EDNS0, unless the caller doesn't want it, or we know that	 * the remote server doesn't like it.	 */	if ((triededns512(fctx, &query->addrinfo->sockaddr) ||	     fctx->timeouts >= (MAX_EDNS0_TIMEOUTS * 2)) &&	    (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {		query->options |= DNS_FETCHOPT_NOEDNS0;		FCTXTRACE("too many timeouts, disabling EDNS0");	} else if ((triededns(fctx, &query->addrinfo->sockaddr) ||		    fctx->timeouts >= MAX_EDNS0_TIMEOUTS) &&	           (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {		query->options |= DNS_FETCHOPT_EDNS512;		FCTXTRACE("too many timeouts, setting EDNS size to 512");	}	if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {		if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {			unsigned int version = 0;	/* Default version. */			unsigned int flags;			isc_uint16_t udpsize = res->udpsize;			flags = query->addrinfo->flags;			if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {				version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;				version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;			}			if ((query->options & DNS_FETCHOPT_EDNS512) != 0)				udpsize = 512;			else if (peer != NULL)				(void)dns_peer_getudpsize(peer, &udpsize);			result = fctx_addopt(fctx->qmessage, version, udpsize);			if (result != ISC_R_SUCCESS) {				/*				 * We couldn't add the OPT, but we'll press on.				 * We're not using EDNS0, so set the NOEDNS0				 * bit.				 */				query->options |= DNS_FETCHOPT_NOEDNS0;			}		} else {			/*			 * We know this server doesn't like EDNS0, so we			 * won't use it.  Set the NOEDNS0 bit since we're			 * not using EDNS0.			 */			query->options |= DNS_FETCHOPT_NOEDNS0;		}	}	/*	 * If we need EDNS0 to do this query and aren't using it, we lose.	 */	if (NEEDEDNS0(fctx) && (query->options & DNS_FETCHOPT_NOEDNS0) != 0) {		result = DNS_R_SERVFAIL;		goto cleanup_message;	}	if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0)		add_triededns(fctx, &query->addrinfo->sockaddr);	if ((query->options & DNS_FETCHOPT_EDNS512) != 0)		add_triededns512(fctx, &query->addrinfo->sockaddr);	/*	 * Clear CD if EDNS is not in use.	 */	if ((query->options & DNS_FETCHOPT_NOEDNS0) != 0)		fctx->qmessage->flags &= ~DNS_MESSAGEFLAG_CD;	/*	 * Add TSIG record tailored to the current recipient.	 */	result = dns_view_getpeertsig(fctx->res->view, &ipaddr, &tsigkey);	if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)		goto cleanup_message;	if (tsigkey != NULL) {		result = dns_message_settsigkey(fctx->qmessage, tsigkey);		dns_tsigkey_detach(&tsigkey);		if (result != ISC_R_SUCCESS)			goto cleanup_message;	}	result = dns_message_rendersection(fctx->qmessage,					   DNS_SECTION_ADDITIONAL, 0);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	result = dns_message_renderend(fctx->qmessage);	if (result != ISC_R_SUCCESS)		goto cleanup_message;	dns_compress_invalidate(&cctx);	cleanup_cctx = ISC_FALSE;	if (dns_message_gettsigkey(fctx->qmessage) != NULL) {		dns_tsigkey_attach(dns_message_gettsigkey(fctx->qmessage),				   &query->tsigkey);		result = dns_message_getquerytsig(fctx->qmessage,						  fctx->res->mctx,						  &query->tsig);		if (result != ISC_R_SUCCESS)			goto cleanup_message;	}	/*	 * If using TCP, write the length of the message at the beginning	 * of the buffer.	 */	if ((query->options & DNS_FETCHOPT_TCP) != 0) {		isc_buffer_usedregion(&query->buffer, &r);

⌨️ 快捷键说明

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