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

📄 client.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * the request; that's all except the TCP flag.	 */	client->attributes &= NS_CLIENTATTR_TCP;}static voidns_client_checkactive(ns_client_t *client) {	if (client->mortal) {		/*		 * This client object should normally go inactive		 * at this point, but if we have fewer active client		 * objects than  desired due to earlier quota exhaustion,		 * keep it active to make up for the shortage.		 */		isc_boolean_t need_another_client = ISC_FALSE;		if (TCP_CLIENT(client)) {			LOCK(&client->interface->lock);			if (client->interface->ntcpcurrent <			    client->interface->ntcptarget)				need_another_client = ISC_TRUE;			UNLOCK(&client->interface->lock);		} else {			/*			 * The UDP client quota is enforced by making			 * requests fail rather than by not listening			 * for new ones.  Therefore, there is always a			 * full set of UDP clients listening.			 */		}		if (! need_another_client) {			/*			 * We don't need this client object.  Recycle it.			 */			if (client->newstate >= NS_CLIENTSTATE_INACTIVE)				client->newstate = NS_CLIENTSTATE_INACTIVE;		}	}}voidns_client_next(ns_client_t *client, isc_result_t result) {	int newstate;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(client->state == NS_CLIENTSTATE_WORKING ||		client->state == NS_CLIENTSTATE_READING);	CTRACE("next");	if (result != ISC_R_SUCCESS)		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),			      "request failed: %s", isc_result_totext(result));	/*	 * An error processing a TCP request may have left	 * the connection out of sync.  To be safe, we always	 * sever the connection when result != ISC_R_SUCCESS.	 */	if (result == ISC_R_SUCCESS && TCP_CLIENT(client))		newstate = NS_CLIENTSTATE_READING;	else		newstate = NS_CLIENTSTATE_READY;	if (client->newstate > newstate)		client->newstate = newstate;	(void) exit_check(client);}static voidclient_senddone(isc_task_t *task, isc_event_t *event) {	ns_client_t *client;	isc_socketevent_t *sevent = (isc_socketevent_t *) event;	REQUIRE(sevent != NULL);	REQUIRE(sevent->ev_type == ISC_SOCKEVENT_SENDDONE);	client = sevent->ev_arg;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(task == client->task);	REQUIRE(sevent == client->sendevent);	UNUSED(task);	CTRACE("senddone");	if (sevent->result != ISC_R_SUCCESS)		ns_client_log(client, NS_LOGCATEGORY_CLIENT,			      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,			      "error sending response: %s",			      isc_result_totext(sevent->result));	INSIST(client->nsends > 0);	client->nsends--;	if (client->tcpbuf != NULL) {		INSIST(TCP_CLIENT(client));		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);		client->tcpbuf = NULL;	}	if (exit_check(client))		return;	ns_client_next(client, ISC_R_SUCCESS);}/* * We only want to fail with ISC_R_NOSPACE when called from * ns_client_sendraw() and not when called from ns_client_send(), * tcpbuffer is NULL when called from ns_client_sendraw() and * length != 0.  tcpbuffer != NULL when called from ns_client_send() * and length == 0. */static isc_result_tclient_allocsendbuf(ns_client_t *client, isc_buffer_t *buffer,		    isc_buffer_t *tcpbuffer, isc_uint32_t length,		    unsigned char *sendbuf, unsigned char **datap){	unsigned char *data;	isc_uint32_t bufsize;	isc_result_t result;	INSIST(datap != NULL);	INSIST((tcpbuffer == NULL && length != 0) ||	       (tcpbuffer != NULL && length == 0));	if (TCP_CLIENT(client)) {		INSIST(client->tcpbuf == NULL);		if (length + 2 > TCP_BUFFER_SIZE) {			result = ISC_R_NOSPACE;			goto done;		}		client->tcpbuf = isc_mem_get(client->mctx, TCP_BUFFER_SIZE);		if (client->tcpbuf == NULL) {			result = ISC_R_NOMEMORY;			goto done;		}		data = client->tcpbuf;		if (tcpbuffer != NULL) {			isc_buffer_init(tcpbuffer, data, TCP_BUFFER_SIZE);			isc_buffer_init(buffer, data + 2, TCP_BUFFER_SIZE - 2);		} else {			isc_buffer_init(buffer, data, TCP_BUFFER_SIZE);			INSIST(length <= 0xffff);			isc_buffer_putuint16(buffer, (isc_uint16_t)length);		}	} else {		data = sendbuf;		if (client->udpsize < SEND_BUFFER_SIZE)			bufsize = client->udpsize;		else			bufsize = SEND_BUFFER_SIZE;		if (length > bufsize) {			result = ISC_R_NOSPACE;			goto done;		}		isc_buffer_init(buffer, data, bufsize);	}	*datap = data;	result = ISC_R_SUCCESS; done:	return (result);}static isc_result_tclient_sendpkg(ns_client_t *client, isc_buffer_t *buffer) {	struct in6_pktinfo *pktinfo;	isc_result_t result;	isc_region_t r;	isc_sockaddr_t *address;	isc_socket_t *socket;	isc_netaddr_t netaddr;	int match;	unsigned int sockflags = ISC_SOCKFLAG_IMMEDIATE;	if (TCP_CLIENT(client)) {		socket = client->tcpsocket;		address = NULL;	} else {		socket = client->udpsocket;		address = &client->peeraddr;		isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);		if (ns_g_server->blackholeacl != NULL &&		    dns_acl_match(&netaddr, NULL,			    	  ns_g_server->blackholeacl,				  &ns_g_server->aclenv,				  &match, NULL) == ISC_R_SUCCESS &&		    match > 0)			return (DNS_R_BLACKHOLED);		sockflags |= ISC_SOCKFLAG_NORETRY;	}	if ((client->attributes & NS_CLIENTATTR_PKTINFO) != 0)		pktinfo = &client->pktinfo;	else		pktinfo = NULL;	isc_buffer_usedregion(buffer, &r);	CTRACE("sendto");		result = isc_socket_sendto2(socket, &r, client->task,				    address, pktinfo,				    client->sendevent, sockflags);	if (result == ISC_R_SUCCESS || result == ISC_R_INPROGRESS) {		client->nsends++;		if (result == ISC_R_SUCCESS)			client_senddone(client->task,					(isc_event_t *)client->sendevent);		result = ISC_R_SUCCESS;	}	return (result);}voidns_client_sendraw(ns_client_t *client, dns_message_t *message) {	isc_result_t result;	unsigned char *data;	isc_buffer_t buffer;	isc_region_t r;	isc_region_t *mr;	unsigned char sendbuf[SEND_BUFFER_SIZE];	REQUIRE(NS_CLIENT_VALID(client));	CTRACE("sendraw");	mr = dns_message_getrawmessage(message);	if (mr == NULL) {		result = ISC_R_UNEXPECTEDEND;		goto done;	}	result = client_allocsendbuf(client, &buffer, NULL, mr->length,				     sendbuf, &data);	if (result != ISC_R_SUCCESS)		goto done;	/*	 * Copy message to buffer and fixup id.	 */	isc_buffer_availableregion(&buffer, &r);	result = isc_buffer_copyregion(&buffer, mr);	if (result != ISC_R_SUCCESS)		goto done;	r.base[0] = (client->message->id >> 8) & 0xff;	r.base[1] = client->message->id & 0xff;	result = client_sendpkg(client, &buffer);	if (result == ISC_R_SUCCESS)		return; done:	if (client->tcpbuf != NULL) {		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);		client->tcpbuf = NULL;	}	ns_client_next(client, result);}voidns_client_send(ns_client_t *client) {	isc_result_t result;	unsigned char *data;	isc_buffer_t buffer;	isc_buffer_t tcpbuffer;	isc_region_t r;	dns_compress_t cctx;	isc_boolean_t cleanup_cctx = ISC_FALSE;	unsigned char sendbuf[SEND_BUFFER_SIZE];	REQUIRE(NS_CLIENT_VALID(client));	CTRACE("send");	if ((client->attributes & NS_CLIENTATTR_RA) != 0)		client->message->flags |= DNS_MESSAGEFLAG_RA;	/*	 * XXXRTH  The following doesn't deal with TCP buffer resizing.	 */	result = client_allocsendbuf(client, &buffer, &tcpbuffer, 0,				     sendbuf, &data);	if (result != ISC_R_SUCCESS)		goto done;	result = dns_compress_init(&cctx, -1, client->mctx);	if (result != ISC_R_SUCCESS)		goto done;	cleanup_cctx = ISC_TRUE;	result = dns_message_renderbegin(client->message, &cctx, &buffer);	if (result != ISC_R_SUCCESS)		goto done;	if (client->opt != NULL) {		result = dns_message_setopt(client->message, client->opt);		/*		 * XXXRTH dns_message_setopt() should probably do this...		 */		client->opt = NULL;		if (result != ISC_R_SUCCESS)			goto done;	}	result = dns_message_rendersection(client->message,					   DNS_SECTION_QUESTION, 0);	if (result == ISC_R_NOSPACE) {		client->message->flags |= DNS_MESSAGEFLAG_TC;		goto renderend;	}	if (result != ISC_R_SUCCESS)		goto done;	result = dns_message_rendersection(client->message,					   DNS_SECTION_ANSWER,					   DNS_MESSAGERENDER_PARTIAL);	if (result == ISC_R_NOSPACE) {		client->message->flags |= DNS_MESSAGEFLAG_TC;		goto renderend;	}	if (result != ISC_R_SUCCESS)		goto done;	result = dns_message_rendersection(client->message,					   DNS_SECTION_AUTHORITY,					   DNS_MESSAGERENDER_PARTIAL);	if (result == ISC_R_NOSPACE) {		client->message->flags |= DNS_MESSAGEFLAG_TC;		goto renderend;	}	if (result != ISC_R_SUCCESS)		goto done;	result = dns_message_rendersection(client->message,					   DNS_SECTION_ADDITIONAL, 0);	if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE)		goto done; renderend:	result = dns_message_renderend(client->message);	if (result != ISC_R_SUCCESS)		goto done;	if (cleanup_cctx) {		dns_compress_invalidate(&cctx);		cleanup_cctx = ISC_FALSE;	}	if (TCP_CLIENT(client)) {		isc_buffer_usedregion(&buffer, &r);		isc_buffer_putuint16(&tcpbuffer, (isc_uint16_t) r.length);		isc_buffer_add(&tcpbuffer, r.length);		result = client_sendpkg(client, &tcpbuffer);	} else		result = client_sendpkg(client, &buffer);	if (result == ISC_R_SUCCESS)		return; done:	if (client->tcpbuf != NULL) {		isc_mem_put(client->mctx, client->tcpbuf, TCP_BUFFER_SIZE);		client->tcpbuf = NULL;	}	if (cleanup_cctx)		dns_compress_invalidate(&cctx);	ns_client_next(client, result);}voidns_client_error(ns_client_t *client, isc_result_t result) {	dns_rcode_t rcode;	dns_message_t *message;	REQUIRE(NS_CLIENT_VALID(client));	CTRACE("error");	message = client->message;	rcode = dns_result_torcode(result);	/*	 * Message may be an in-progress reply that we had trouble	 * with, in which case QR will be set.  We need to clear QR before	 * calling dns_message_reply() to avoid triggering an assertion.	 */	message->flags &= ~DNS_MESSAGEFLAG_QR;	/*	 * AA and AD shouldn't be set.	 */	message->flags &= ~(DNS_MESSAGEFLAG_AA | DNS_MESSAGEFLAG_AD);	result = dns_message_reply(message, ISC_TRUE);	if (result != ISC_R_SUCCESS) {		/*		 * It could be that we've got a query with a good header,		 * but a bad question section, so we try again with		 * want_question_section set to ISC_FALSE.		 */		result = dns_message_reply(message, ISC_FALSE);		if (result != ISC_R_SUCCESS) {			ns_client_next(client, result);			return;		}	}	message->rcode = rcode;	/*	 * FORMERR loop avoidance:  If we sent a FORMERR message	 * with the same ID to the same client less than two	 * seconds ago, assume that we are in an infinite error 	 * packet dialog with a server for some protocol whose 	 * error responses look enough like DNS queries to	 * elicit a FORMERR response.  Drop a packet to break	 * the loop.	 */	if (rcode == dns_rcode_formerr) {		if (isc_sockaddr_equal(&client->peeraddr,				       &client->formerrcache.addr) &&		    message->id == client->formerrcache.id &&		    client->requesttime - client->formerrcache.time < 2) {			/* Drop packet. */			ns_client_log(client, NS_LOGCATEGORY_CLIENT,				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),				      "possible error packet loop, "				      "FORMERR dropped");			ns_client_next(client, result);			return;		}		client->formerrcache.addr = client->peeraddr;		client->formerrcache.time = client->requesttime;		client->formerrcache.id = message->id;	}	ns_client_send(client);}static inline isc_result_tclient_addopt(ns_client_t *client) {	dns_rdataset_t *rdataset;	dns_rdatalist_t *rdatalist;	dns_rdata_t *rdata;	isc_result_t result;	REQUIRE(client->opt == NULL);	/* XXXRTH free old. */	rdatalist = NULL;	result = dns_message_gettemprdatalist(client->message, &rdatalist);	if (result != ISC_R_SUCCESS)		return (result);	rdata = NULL;	result = dns_message_gettemprdata(client->message, &rdata);	if (result != ISC_R_SUCCESS)		return (result);	rdataset = NULL;	result = dns_message_gettemprdataset(client->message, &rdataset);	if (result != ISC_R_SUCCESS)		return (result);	dns_rdataset_init(rdataset);	rdatalist->type = dns_rdatatype_opt;	rdatalist->covers = 0;	/*	 * Set the maximum UDP buffer size.	 */	rdatalist->rdclass = RECV_BUFFER_SIZE;	/*	 * Set EXTENDED-RCODE, VERSION, and Z to 0.	 */#ifdef ISC_RFC2535	rdatalist->ttl = (client->extflags & DNS_MESSAGEEXTFLAG_REPLYPRESERVE);#else	rdatalist->ttl = 0;#endif	/*	 * No ENDS options in the default case.	 */	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);	dns_rdatalist_tordataset(rdatalist, rdataset);	client->opt = rdataset;	return (ISC_R_SUCCESS);}static inline isc_boolean_tallowed(isc_netaddr_t *addr, dns_acl_t *acl) {	int match;	isc_result_t result;	if (acl == NULL)		return (ISC_TRUE);	result = dns_acl_match(addr, NULL, acl, &ns_g_server->aclenv,			       &match, NULL);	if (result == ISC_R_SUCCESS && match > 0)		return (ISC_TRUE);	return (ISC_FALSE);}/* * Handle an incoming request event from the socket (UDP case) * or tcpmsg (TCP case). */static voidclient_request(isc_task_t *task, isc_event_t *event) {	ns_client_t *client;	isc_socketevent_t *sevent;	isc_result_t result;	isc_result_t sigresult;	isc_buffer_t *buffer;	isc_buffer_t tbuffer;	dns_view_t *view;	dns_rdataset_t *opt;	isc_boolean_t ra; 	/* Recursion available. */	isc_netaddr_t netaddr;	isc_netaddr_t destaddr;	int match;	dns_messageid_t id;	unsigned int flags;	isc_boolean_t notimp;	REQUIRE(event != NULL);	client = event->ev_arg;	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(task == client->task);	UNUSED(task);	INSIST(client->recursionquota == NULL);	INSIST(client->state ==	       TCP_CLIENT(client) ?	       NS_CLIENTSTATE_READING :	       NS_CLIENTSTATE_READY);	if (event->ev_type == ISC_SOCKEVENT_RECVDONE) {		INSIST(!TCP_CLIENT(client));		sevent = (isc_socketevent_t *)event;

⌨️ 快捷键说明

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