📄 client.c
字号:
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 == 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) { REQUIRE(ISC_LIST_EMPTY(manager->active)); REQUIRE(ISC_LIST_EMPTY(manager->inactive)); REQUIRE(ISC_LIST_EMPTY(manager->recursing)); 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); ISC_LIST_INIT(manager->recursing); 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){ 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);}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]; const char *name = ""; const char *sep = ""; vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap); ns_client_name(client, peerbuf, sizeof(peerbuf)); if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { name = client->view->name; sep = ": view "; } isc_log_write(ns_g_lctx, category, module, level, "client %s%s%s: %s", peerbuf, sep, name, 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_rdatatype_t type, dns_rdataclass_t rdclass, char *buf, size_t len) { char namebuf[DNS_NAME_FORMATSIZE]; char typebuf[DNS_RDATATYPE_FORMATSIZE]; char classbuf[DNS_RDATACLASS_FORMATSIZE]; dns_name_format(name, namebuf, sizeof(namebuf)); dns_rdatatype_format(type, typebuf, sizeof(typebuf)); dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf)); (void)snprintf(buf, len, "%s '%s/%s/%s'", msg, namebuf, typebuf, 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);}voidns_client_dumprecursing(FILE *f, ns_clientmgr_t *manager) { ns_client_t *client; char namebuf[DNS_NAME_FORMATSIZE]; char peerbuf[ISC_SOCKADDR_FORMATSIZE]; const char *name; const char *sep; REQUIRE(VALID_MANAGER(manager)); LOCK(&manager->lock); client = ISC_LIST_HEAD(manager->recursing); while (client != NULL) { ns_client_name(client, peerbuf, sizeof(peerbuf)); if (client->view != NULL && strcmp(client->view->name, "_bind") != 0 && strcmp(client->view->name, "_default") != 0) { name = client->view->name; sep = ": view "; } else { name = ""; sep = ""; } dns_name_format(client->query.qname, namebuf, sizeof(namebuf)); fprintf(f, "; client %s%s%s: '%s' requesttime %d\n", peerbuf, sep, name, namebuf, client->requesttime); client = ISC_LIST_NEXT(client, link); } UNLOCK(&manager->lock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -