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

📄 resolver.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 5 页
字号:
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) {		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;	} else		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 (fctx->timeouts >= MAX_EDNS0_TIMEOUTS &&	    (query->options & DNS_FETCHOPT_NOEDNS0) == 0) {		query->options |= DNS_FETCHOPT_NOEDNS0;		FCTXTRACE("too many timeouts, disabling EDNS0");	}	if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {		if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) {			result = fctx_addopt(fctx->qmessage, res);			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;	}	/*	 * 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);		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_result_t result;	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--;	if (RESQUERY_CANCELED(query)) {		/*		 * This query was canceled while the connect() was in		 * progress.		 */		isc_socket_detach(&query->tcpsocket);		resquery_destroy(&query);	} else {		if (sevent->result == ISC_R_SUCCESS) {			unsigned int attrs;			/*			 * 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) {				fetchctx_t *fctx = query->fctx;				fctx_cancelquery(&query, NULL, NULL,						 ISC_FALSE);				fctx_done(fctx, result);			}		} else {			isc_socket_detach(&query->tcpsocket);			fctx_cancelquery(&query, NULL, NULL, ISC_FALSE);		}	}	isc_event_free(&event);}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 &&		   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;

⌨️ 快捷键说明

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