static isc_result_t configure_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); }
void server_shutdown() { int clientno; for (clientno = 0; clientno < MAXCLIENTS; clientno++) { if (CLIENT_USED(&clients[clientno])) server_destroy(&clients[clientno], "server shutdown"); } listener_shutdown(); #ifdef WIN32 WSACleanup(); #endif }
isc_result_t ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) { const cfg_obj_t *lwreslist = NULL; const cfg_obj_t *lwres = NULL; const cfg_obj_t *listenerslist = NULL; const 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); }