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

📄 client.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 4 页
字号:
					client_request, client);	if (result != ISC_R_SUCCESS)		goto fail;	/*	 * Set a timeout to limit the amount of time we will wait	 * for a request on this TCP connection.	 */	ns_client_settimeout(client, 30);	client->state = client->newstate = NS_CLIENTSTATE_READING;	INSIST(client->nreads == 0);	INSIST(client->recursionquota == NULL);	client->nreads++;	return; fail:	ns_client_next(client, result);}static voidclient_newconn(isc_task_t *task, isc_event_t *event) {	ns_client_t *client = event->ev_arg;	isc_socket_newconnev_t *nevent = (isc_socket_newconnev_t *)event;	isc_result_t result;	REQUIRE(event->ev_type == ISC_SOCKEVENT_NEWCONN);	REQUIRE(NS_CLIENT_VALID(client));	REQUIRE(client->task == task);	UNUSED(task);	INSIST(client->state == NS_CLIENTSTATE_READY);	INSIST(client->naccepts == 1);	client->naccepts--;	LOCK(&client->interface->lock);	INSIST(client->interface->ntcpcurrent > 0);	client->interface->ntcpcurrent--;	UNLOCK(&client->interface->lock);	/*	 * We must take ownership of the new socket before the exit	 * check to make sure it gets destroyed if we decide to exit.	 */	if (nevent->result == ISC_R_SUCCESS) {		client->tcpsocket = nevent->newsocket;		client->state = NS_CLIENTSTATE_READING;		INSIST(client->recursionquota == NULL);		(void) isc_socket_getpeername(client->tcpsocket,					      &client->peeraddr);		client->peeraddr_valid = ISC_TRUE;		ns_client_log(client, NS_LOGCATEGORY_CLIENT,			   NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),			   "new TCP connection");	} else {		/*		 * XXXRTH  What should we do?  We're trying to accept but		 *         it didn't work.  If we just give up, then TCP		 *	   service may eventually stop.		 *		 *	   For now, we just go idle.		 *		 *	   Going idle is probably the right thing if the		 *	   I/O was canceled.		 */		ns_client_log(client, NS_LOGCATEGORY_CLIENT,			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),			      "accept failed: %s",			      isc_result_totext(nevent->result));	}	if (exit_check(client))		goto freeevent;	if (nevent->result == ISC_R_SUCCESS) {		int match;		isc_netaddr_t netaddr;		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)		{			ns_client_log(client, DNS_LOGCATEGORY_SECURITY,				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),				      "blackholed connection attempt");			client->newstate = NS_CLIENTSTATE_READY;			(void)exit_check(client);			goto freeevent;		}		INSIST(client->tcpmsg_valid == ISC_FALSE);		dns_tcpmsg_init(client->mctx, client->tcpsocket,				&client->tcpmsg);		client->tcpmsg_valid = ISC_TRUE;		/*		 * Let a new client take our place immediately, before		 * we wait for a request packet.  If we don't,		 * telnetting to port 53 (once per CPU) will		 * deny service to legititmate TCP clients.		 */		result = isc_quota_attach(&ns_g_server->tcpquota,					  &client->tcpquota);		if (result == ISC_R_SUCCESS)			result = ns_client_replace(client);		if (result != ISC_R_SUCCESS) {			ns_client_log(client, NS_LOGCATEGORY_CLIENT,				      NS_LOGMODULE_CLIENT, ISC_LOG_WARNING,				      "no more TCP clients: %s",				      isc_result_totext(result));		}		client_read(client);	} freeevent:	isc_event_free(&event);}static voidclient_accept(ns_client_t *client) {	isc_result_t result;	CTRACE("accept");	result = isc_socket_accept(client->tcplistener, client->task,				   client_newconn, client);	if (result != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_socket_accept() failed: %s",				 isc_result_totext(result));		/*		 * XXXRTH  What should we do?  We're trying to accept but		 *         it didn't work.  If we just give up, then TCP		 *	   service may eventually stop.		 *		 *	   For now, we just go idle.		 */		return;	}	INSIST(client->naccepts == 0);	client->naccepts++;	LOCK(&client->interface->lock);	client->interface->ntcpcurrent++;	UNLOCK(&client->interface->lock);}static voidclient_udprecv(ns_client_t *client) {	isc_result_t result;	isc_region_t r;	CTRACE("udprecv");	r.base = client->recvbuf;	r.length = RECV_BUFFER_SIZE;	result = isc_socket_recv2(client->udpsocket, &r, 1,				  client->task, client->recvevent, 0);	if (result != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_socket_recv() failed: %s",				 isc_result_totext(result));		/*		 * This cannot happen in the current implementation, since		 * isc_socket_recv2() cannot fail if flags == 0A		 *		 * If this does fail, we just go idle.		 */		return;	}	INSIST(client->nrecvs == 0);	client->nrecvs++;}voidns_client_attach(ns_client_t *source, ns_client_t **targetp) {	REQUIRE(NS_CLIENT_VALID(source));	REQUIRE(targetp != NULL && *targetp == NULL);	source->references++;	ns_client_log(source, NS_LOGCATEGORY_CLIENT,		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),		      "ns_client_attach: ref = %d", source->references);	*targetp = source;}voidns_client_detach(ns_client_t **clientp) {	ns_client_t *client = *clientp;	client->references--;	INSIST(client->references >= 0);	*clientp = NULL;	ns_client_log(client, NS_LOGCATEGORY_CLIENT,		      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(10),		      "ns_client_detach: ref = %d", client->references);	(void) exit_check(client);}isc_boolean_tns_client_shuttingdown(ns_client_t *client) {	return (ISC_TF(client->newstate == NS_CLIENTSTATE_FREED));}isc_result_tns_client_replace(ns_client_t *client) {	isc_result_t result;	CTRACE("replace");	result = ns_clientmgr_createclients(client->manager,					    1, client->interface,					    (TCP_CLIENT(client) ?					     ISC_TRUE : ISC_FALSE));	if (result != ISC_R_SUCCESS)		return (result);	/*	 * The responsibility for listening for new requests is hereby	 * transferred to the new client.  Therefore, the old client	 * should refrain from listening for any more requests.	 */	client->mortal = ISC_TRUE;	return (ISC_R_SUCCESS);}/*** *** Client Manager ***/static voidclientmgr_destroy(ns_clientmgr_t *manager) {	REQUIRE(ISC_LIST_EMPTY(manager->active));	REQUIRE(ISC_LIST_EMPTY(manager->inactive));	MTRACE("clientmgr_destroy");	DESTROYLOCK(&manager->lock);	manager->magic = 0;	isc_mem_put(manager->mctx, manager, sizeof *manager);}isc_result_tns_clientmgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,		    isc_timermgr_t *timermgr, ns_clientmgr_t **managerp){	ns_clientmgr_t *manager;	isc_result_t result;	manager = isc_mem_get(mctx, sizeof *manager);	if (manager == NULL)		return (ISC_R_NOMEMORY);	result = isc_mutex_init(&manager->lock);	if (result != ISC_R_SUCCESS)		goto cleanup_manager;	manager->mctx = mctx;	manager->taskmgr = taskmgr;	manager->timermgr = timermgr;	manager->exiting = ISC_FALSE;	ISC_LIST_INIT(manager->active);	ISC_LIST_INIT(manager->inactive);	manager->magic = MANAGER_MAGIC;	MTRACE("create");	*managerp = manager;	return (ISC_R_SUCCESS); cleanup_manager:	isc_mem_put(manager->mctx, manager, sizeof *manager);	return (result);}voidns_clientmgr_destroy(ns_clientmgr_t **managerp) {	ns_clientmgr_t *manager;	ns_client_t *client;	isc_boolean_t need_destroy = ISC_FALSE;	REQUIRE(managerp != NULL);	manager = *managerp;	REQUIRE(VALID_MANAGER(manager));	MTRACE("destroy");	LOCK(&manager->lock);	manager->exiting = ISC_TRUE;	for (client = ISC_LIST_HEAD(manager->active);	     client != NULL;	     client = ISC_LIST_NEXT(client, link))		isc_task_shutdown(client->task);	for (client = ISC_LIST_HEAD(manager->inactive);	     client != NULL;	     client = ISC_LIST_NEXT(client, link))		isc_task_shutdown(client->task);	if (ISC_LIST_EMPTY(manager->active) &&	    ISC_LIST_EMPTY(manager->inactive))		need_destroy = ISC_TRUE;	UNLOCK(&manager->lock);	if (need_destroy)		clientmgr_destroy(manager);	*managerp = NULL;}isc_result_tns_clientmgr_createclients(ns_clientmgr_t *manager, unsigned int n,			   ns_interface_t *ifp, isc_boolean_t tcp){	isc_result_t result = ISC_R_SUCCESS;	unsigned int i;	ns_client_t *client;	REQUIRE(VALID_MANAGER(manager));	REQUIRE(n > 0);	MTRACE("createclients");	/*	 * We MUST lock the manager lock for the entire client creation	 * process.  If we didn't do this, then a client could get a	 * shutdown event and disappear out from under us.	 */	LOCK(&manager->lock);	for (i = 0; i < n; i++) {		isc_event_t *ev;		/*		 * Allocate a client.  First try to get a recycled one;		 * if that fails, make a new one.		 */		client = ISC_LIST_HEAD(manager->inactive);		if (client != NULL) {			MTRACE("recycle");			ISC_LIST_UNLINK(manager->inactive, client, link);			client->list = NULL;		} else {			MTRACE("create new");			result = client_create(manager, &client);			if (result != ISC_R_SUCCESS)				break;		}		ns_interface_attach(ifp, &client->interface);		client->state = NS_CLIENTSTATE_READY;		INSIST(client->recursionquota == NULL);		if (tcp) {			client->attributes |= NS_CLIENTATTR_TCP;			isc_socket_attach(ifp->tcpsocket,					  &client->tcplistener);		} else {			isc_socket_t *sock;			dns_dispatch_attach(ifp->udpdispatch,					    &client->dispatch);			sock = dns_dispatch_getsocket(client->dispatch);			isc_socket_attach(sock, &client->udpsocket);		}		client->manager = manager;		ISC_LIST_APPEND(manager->active, client, link);		client->list = &manager->active;		INSIST(client->nctls == 0);		client->nctls++;		ev = &client->ctlevent;		isc_task_send(client->task, &ev);	}	if (i != 0) {		/*		 * We managed to create at least one client, so we		 * declare victory.		 */		result = ISC_R_SUCCESS;	}	UNLOCK(&manager->lock);	return (result);}isc_sockaddr_t *ns_client_getsockaddr(ns_client_t *client) {	return (&client->peeraddr);}isc_result_tns_client_checkaclsilent(ns_client_t *client, dns_acl_t *acl,			 isc_boolean_t default_allow){	isc_result_t result;	int match;	isc_netaddr_t netaddr;	if (acl == NULL) {		if (default_allow)			goto allow;		else			goto deny;	}	isc_netaddr_fromsockaddr(&netaddr, &client->peeraddr);	result = dns_acl_match(&netaddr, client->signer, acl,			       &ns_g_server->aclenv,			       &match, NULL);	if (result != ISC_R_SUCCESS)		goto deny; /* Internal error, already logged. */	if (match > 0)		goto allow;	goto deny; /* Negative match or no match. */ allow:	return (ISC_R_SUCCESS); deny:	return (DNS_R_REFUSED);}isc_result_tns_client_checkacl(ns_client_t *client,		   const char *opname, dns_acl_t *acl,		   isc_boolean_t default_allow, int log_level){	isc_result_t result =		ns_client_checkaclsilent(client, acl, default_allow);	if (result == ISC_R_SUCCESS) 		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,			      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(3),			      "%s approved", opname);	else		ns_client_log(client, DNS_LOGCATEGORY_SECURITY,			      NS_LOGMODULE_CLIENT,			      log_level, "%s denied", opname);	return (result);}static voidns_client_name(ns_client_t *client, char *peerbuf, size_t len) {	if (client->peeraddr_valid)		isc_sockaddr_format(&client->peeraddr, peerbuf, len);	else		snprintf(peerbuf, len, "@%p", client);}static voidns_client_logv(ns_client_t *client, isc_logcategory_t *category,	   isc_logmodule_t *module, int level, const char *fmt, va_list ap)     ISC_FORMAT_PRINTF(5, 0);static voidns_client_logv(ns_client_t *client, isc_logcategory_t *category,	   isc_logmodule_t *module, int level, const char *fmt, va_list ap){	char msgbuf[2048];	char peerbuf[ISC_SOCKADDR_FORMATSIZE];	vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);	ns_client_name(client, peerbuf, sizeof peerbuf);	isc_log_write(ns_g_lctx, category, module, level,		      "client %s: %s", peerbuf, msgbuf);}voidns_client_log(ns_client_t *client, isc_logcategory_t *category,	   isc_logmodule_t *module, int level, const char *fmt, ...){	va_list ap;	if (! isc_log_wouldlog(ns_g_lctx, level))		return;	va_start(ap, fmt);	ns_client_logv(client, category, module, level, fmt, ap);	va_end(ap);}voidns_client_aclmsg(const char *msg, dns_name_t *name, dns_rdataclass_t rdclass,		 char *buf, size_t len) {        char namebuf[DNS_NAME_FORMATSIZE];        char classbuf[DNS_RDATACLASS_FORMATSIZE];        dns_name_format(name, namebuf, sizeof(namebuf));        dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));        (void)snprintf(buf, len, "%s '%s/%s'", msg, namebuf, classbuf);}static voidns_client_dumpmessage(ns_client_t *client, const char *reason) {	isc_buffer_t buffer;	char *buf = NULL;	int len = 1024;	isc_result_t result;	/*	 * Note that these are multiline debug messages.  We want a newline	 * to appear in the log after each message.	 */	do {		buf = isc_mem_get(client->mctx, len);		if (buf == NULL)			break;		isc_buffer_init(&buffer, buf, len);		result = dns_message_totext(client->message,					    &dns_master_style_debug,					    0, &buffer);		if (result == ISC_R_NOSPACE) {			isc_mem_put(client->mctx, buf, len);			len += 1024;		} else if (result == ISC_R_SUCCESS)		        ns_client_log(client, NS_LOGCATEGORY_UNMATCHED,				      NS_LOGMODULE_CLIENT, ISC_LOG_DEBUG(1),				      "%s\n%.*s", reason,				       (int)isc_buffer_usedlength(&buffer),				       buf);	} while (result == ISC_R_NOSPACE);	if (buf != NULL)		isc_mem_put(client->mctx, buf, len);}

⌨️ 快捷键说明

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