📄 lwresd.c
字号:
INSIST(VALID_LWRESD(*lwresdp)); lwresd = *lwresdp; *lwresdp = NULL; LOCK(&lwresd->lock); INSIST(lwresd->refs > 0); lwresd->refs--; if (lwresd->refs == 0) done = ISC_TRUE; UNLOCK(&lwresd->lock); if (!done) return; dns_view_detach(&lwresd->view); if (lwresd->search != NULL) ns_lwsearchlist_detach(&lwresd->search); mctx = lwresd->mctx; lwresd->magic = 0; isc_mem_put(mctx, lwresd, sizeof(*lwresd)); isc_mem_detach(&mctx);}/* * Handle listener objects */voidns_lwreslistener_attach(ns_lwreslistener_t *source, ns_lwreslistener_t **targetp){ INSIST(VALID_LWRESLISTENER(source)); INSIST(targetp != NULL && *targetp == NULL); LOCK(&source->lock); source->refs++; UNLOCK(&source->lock); *targetp = source;}voidns_lwreslistener_detach(ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; isc_mem_t *mctx; isc_boolean_t done = ISC_FALSE; INSIST(listenerp != NULL && *listenerp != NULL); INSIST(VALID_LWRESLISTENER(*listenerp)); listener = *listenerp; LOCK(&listener->lock); INSIST(listener->refs > 0); listener->refs--; if (listener->refs == 0) done = ISC_TRUE; UNLOCK(&listener->lock); if (!done) return; if (listener->manager != NULL) ns_lwdmanager_detach(&listener->manager); if (listener->sock != NULL) isc_socket_detach(&listener->sock); listener->magic = 0; mctx = listener->mctx; isc_mem_put(mctx, listener, sizeof(*listener)); isc_mem_detach(&mctx); listenerp = NULL;}static isc_result_tlistener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd, ns_lwreslistener_t **listenerp){ ns_lwreslistener_t *listener; REQUIRE(listenerp != NULL && *listenerp == NULL); listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t)); if (listener == NULL) return (ISC_R_NOMEMORY); RUNTIME_CHECK(isc_mutex_init(&listener->lock) == ISC_R_SUCCESS); listener->magic = LWRESLISTENER_MAGIC; listener->refs = 1; listener->sock = NULL; listener->manager = NULL; ns_lwdmanager_attach(lwresd, &listener->manager); listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->cmgrs); *listenerp = listener; return (ISC_R_SUCCESS);}static isc_result_tlistener_bind(ns_lwreslistener_t *listener, isc_sockaddr_t *address) { isc_socket_t *sock = NULL; isc_result_t result = ISC_R_SUCCESS; int pf; pf = isc_sockaddr_pf(address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) return (ISC_R_FAMILYNOSUPPORT); listener->address = *address; if (isc_sockaddr_getport(&listener->address) == 0) { in_port_t port; port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; isc_sockaddr_setport(&listener->address, port); } sock = NULL; result = isc_socket_create(ns_g_socketmgr, pf, isc_sockettype_udp, &sock); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "failed to create lwres socket: %s", isc_result_totext(result)); return (result); } result = isc_socket_bind(sock, &listener->address); if (result != ISC_R_SUCCESS) { char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); isc_socket_detach(&sock); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "failed to add lwres socket: %s: %s", socktext, isc_result_totext(result)); return (result); } listener->sock = sock; return (ISC_R_SUCCESS);}static voidlistener_copysock(ns_lwreslistener_t *oldlistener, ns_lwreslistener_t *newlistener){ newlistener->address = oldlistener->address; isc_socket_attach(oldlistener->sock, &newlistener->sock);}static isc_result_tlistener_startclients(ns_lwreslistener_t *listener) { ns_lwdclientmgr_t *cm; unsigned int i; isc_result_t result; /* * Create the client managers. */ result = ISC_R_SUCCESS; for (i = 0; i < NTASKS && result == ISC_R_SUCCESS; i++) result = ns_lwdclientmgr_create(listener, NRECVS, ns_g_taskmgr); /* * Ensure that we have created at least one. */ if (ISC_LIST_EMPTY(listener->cmgrs)) return (result); /* * Walk the list of clients and start each one up. */ LOCK(&listener->lock); cm = ISC_LIST_HEAD(listener->cmgrs); while (cm != NULL) { result = ns_lwdclient_startrecv(cm); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "could not start lwres " "client handler: %s", isc_result_totext(result)); cm = ISC_LIST_NEXT(cm, link); } UNLOCK(&listener->lock); return (ISC_R_SUCCESS);}static voidlistener_shutdown(ns_lwreslistener_t *listener) { ns_lwdclientmgr_t *cm; cm = ISC_LIST_HEAD(listener->cmgrs); while (cm != NULL) { isc_task_shutdown(cm->task); cm = ISC_LIST_NEXT(cm, link); }}static isc_result_tfind_listener(isc_sockaddr_t *address, ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; INSIST(listenerp != NULL && *listenerp == NULL); for (listener = ISC_LIST_HEAD(listeners); listener != NULL; listener = ISC_LIST_NEXT(listener, link)) { if (!isc_sockaddr_equal(address, &listener->address)) continue; *listenerp = listener; return (ISC_R_SUCCESS); } return (ISC_R_NOTFOUND);}voidns_lwreslistener_unlinkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm){ REQUIRE(VALID_LWRESLISTENER(listener)); LOCK(&listener->lock); ISC_LIST_UNLINK(listener->cmgrs, cm, link); UNLOCK(&listener->lock);}voidns_lwreslistener_linkcm(ns_lwreslistener_t *listener, ns_lwdclientmgr_t *cm) { REQUIRE(VALID_LWRESLISTENER(listener)); /* * This does no locking, since it's called early enough that locking * isn't needed. */ ISC_LIST_APPEND(listener->cmgrs, cm, link);}static isc_result_tconfigure_listener(isc_sockaddr_t *address, ns_lwresd_t *lwresd, isc_mem_t *mctx, ns_lwreslistenerlist_t *newlisteners){ ns_lwreslistener_t *listener, *oldlistener = NULL; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_result_t result; (void)find_listener(address, &oldlistener); listener = NULL; result = listener_create(mctx, lwresd, &listener); if (result != ISC_R_SUCCESS) { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "lwres failed to configure %s: %s", socktext, isc_result_totext(result)); return (result); } /* * If there's already a listener, don't rebind the socket. */ if (oldlistener == NULL) { result = listener_bind(listener, address); if (result != ISC_R_SUCCESS) { ns_lwreslistener_detach(&listener); return (ISC_R_SUCCESS); } } else listener_copysock(oldlistener, listener); result = listener_startclients(listener); if (result != ISC_R_SUCCESS) { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_WARNING, "lwres: failed to start %s: %s", socktext, isc_result_totext(result)); ns_lwreslistener_detach(&listener); return (ISC_R_SUCCESS); } if (oldlistener != NULL) { /* * Remove the old listener from the old list and shut it down. */ ISC_LIST_UNLINK(listeners, oldlistener, link); listener_shutdown(oldlistener); ns_lwreslistener_detach(&oldlistener); } else { isc_sockaddr_format(address, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres listening on %s", socktext); } ISC_LIST_APPEND(*newlisteners, listener, link); return (result);}isc_result_tns_lwresd_configure(isc_mem_t *mctx, cfg_obj_t *config) { cfg_obj_t *lwreslist = NULL; cfg_obj_t *lwres = NULL; cfg_obj_t *listenerslist = NULL; cfg_listelt_t *element = NULL; ns_lwreslistener_t *listener; ns_lwreslistenerlist_t newlisteners; isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t *addrs = NULL; ns_lwresd_t *lwresd = NULL; isc_uint32_t count = 0; REQUIRE(mctx != NULL); REQUIRE(config != NULL); RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(newlisteners); result = cfg_map_get(config, "lwres", &lwreslist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); LOCK(&listeners_lock); /* * Run through the new lwres address list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicates addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ for (element = cfg_list_first(lwreslist); element != NULL; element = cfg_list_next(element)) { in_port_t port; lwres = cfg_listelt_value(element); CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd)); port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; listenerslist = NULL; (void)cfg_map_get(lwres, "listen-on", &listenerslist); if (listenerslist == NULL) { struct in_addr localhost; isc_sockaddr_t address; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&address, &localhost, port); CHECK(configure_listener(&address, lwresd, mctx, &newlisteners)); } else { isc_uint32_t i; CHECK(ns_config_getiplist(config, listenerslist, port, mctx, &addrs, &count)); for (i = 0; i < count; i++) CHECK(configure_listener(&addrs[i], lwresd, mctx, &newlisteners)); ns_config_putiplist(mctx, &addrs, count); } ns_lwdmanager_detach(&lwresd); } /* * Shutdown everything on the listeners list, and remove them from * the list. Then put all of the new listeners on it. */ while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); listener_shutdown(listener); ns_lwreslistener_detach(&listener); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres no longer listening on %s", socktext); } cleanup: ISC_LIST_APPENDLIST(listeners, newlisteners, link); if (addrs != NULL) ns_config_putiplist(mctx, &addrs, count); if (lwresd != NULL) ns_lwdmanager_detach(&lwresd); UNLOCK(&listeners_lock); return (result);}voidns_lwresd_shutdown(void) { ns_lwreslistener_t *listener; RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); ns_lwreslistener_detach(&listener); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -