client.c

来自「非常好的dns解析软件」· C语言 代码 · 共 2,439 行 · 第 1/5 页

C
2,439
字号
	if (result != ISC_R_SUCCESS)		goto cleanup_recvevent;	result = isc_task_onshutdown(client->task, client_shutdown, client);	if (result != ISC_R_SUCCESS)		goto cleanup_query;	CTRACE("create");	*clientp = client;	return (ISC_R_SUCCESS); cleanup_query:	ns_query_free(client); cleanup_recvevent:	isc_event_free((isc_event_t **)&client->recvevent); cleanup_recvbuf:	isc_mem_put(client->mctx, client->recvbuf, RECV_BUFFER_SIZE); cleanup_sendevent:	isc_event_free((isc_event_t **)&client->sendevent);	client->magic = 0; cleanup_message:	dns_message_destroy(&client->message); cleanup_timer:	isc_timer_detach(&client->timer); cleanup_task:	isc_task_detach(&client->task); cleanup_client:	isc_mem_putanddetach(&client->mctx, client, sizeof(*client));	return (result);}static voidclient_read(ns_client_t *client) {	isc_result_t result;	CTRACE("read");	result = dns_tcpmsg_readmessage(&client->tcpmsg, client->task,					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_recv2() failed: %s",				 isc_result_totext(result));		/*		 * This cannot happen in the current implementation, since		 * isc_socket_recv2() cannot fail if flags == 0.		 *		 * 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) {#if NMCTXS > 0	int i;#endif	REQUIRE(ISC_LIST_EMPTY(manager->active));	REQUIRE(ISC_LIST_EMPTY(manager->inactive));	REQUIRE(ISC_LIST_EMPTY(manager->recursing));	MTRACE("clientmgr_destroy");#if NMCTXS > 0	for (i = 0; i < NMCTXS; i++) {		if (manager->mctxpool[i] != NULL)			isc_mem_detach(&manager->mctxpool[i]);	}#endif	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;#if NMCTXS > 0	int i;#endif	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);	ISC_LIST_INIT(manager->recursing);#if NMCTXS > 0	manager->nextmctx = 0;	for (i = 0; i < NMCTXS; i++)		manager->mctxpool[i] = NULL; /* will be created on-demand */#endif	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->recursing);	     client != NULL;	     client = ISC_LIST_NEXT(client, link))		isc_task_shutdown(client->task);	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) &&	    ISC_LIST_EMPTY(manager->recursing))		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){	

⌨️ 快捷键说明

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