1b7579f77SDag-Erling Smørgrav /* 2b7579f77SDag-Erling Smørgrav * daemon/daemon.c - collection of workers that handles requests. 3b7579f77SDag-Erling Smørgrav * 4b7579f77SDag-Erling Smørgrav * Copyright (c) 2007, NLnet Labs. All rights reserved. 5b7579f77SDag-Erling Smørgrav * 6b7579f77SDag-Erling Smørgrav * This software is open source. 7b7579f77SDag-Erling Smørgrav * 8b7579f77SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 9b7579f77SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 10b7579f77SDag-Erling Smørgrav * are met: 11b7579f77SDag-Erling Smørgrav * 12b7579f77SDag-Erling Smørgrav * Redistributions of source code must retain the above copyright notice, 13b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer. 14b7579f77SDag-Erling Smørgrav * 15b7579f77SDag-Erling Smørgrav * Redistributions in binary form must reproduce the above copyright notice, 16b7579f77SDag-Erling Smørgrav * this list of conditions and the following disclaimer in the documentation 17b7579f77SDag-Erling Smørgrav * and/or other materials provided with the distribution. 18b7579f77SDag-Erling Smørgrav * 19b7579f77SDag-Erling Smørgrav * Neither the name of the NLNET LABS nor the names of its contributors may 20b7579f77SDag-Erling Smørgrav * be used to endorse or promote products derived from this software without 21b7579f77SDag-Erling Smørgrav * specific prior written permission. 22b7579f77SDag-Erling Smørgrav * 23b7579f77SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2417d15b25SDag-Erling Smørgrav * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2517d15b25SDag-Erling Smørgrav * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2617d15b25SDag-Erling Smørgrav * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2717d15b25SDag-Erling Smørgrav * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2817d15b25SDag-Erling Smørgrav * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 2917d15b25SDag-Erling Smørgrav * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 3017d15b25SDag-Erling Smørgrav * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3117d15b25SDag-Erling Smørgrav * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 3217d15b25SDag-Erling Smørgrav * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3317d15b25SDag-Erling Smørgrav * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34b7579f77SDag-Erling Smørgrav */ 35b7579f77SDag-Erling Smørgrav 36b7579f77SDag-Erling Smørgrav /** 37b7579f77SDag-Erling Smørgrav * \file 38b7579f77SDag-Erling Smørgrav * 39b7579f77SDag-Erling Smørgrav * The daemon consists of global settings and a number of workers. 40b7579f77SDag-Erling Smørgrav */ 41b7579f77SDag-Erling Smørgrav 42b7579f77SDag-Erling Smørgrav #include "config.h" 43b7579f77SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ERR_H 44b7579f77SDag-Erling Smørgrav #include <openssl/err.h> 45b7579f77SDag-Erling Smørgrav #endif 46b7579f77SDag-Erling Smørgrav 47b7579f77SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_RAND_H 48b7579f77SDag-Erling Smørgrav #include <openssl/rand.h> 49b7579f77SDag-Erling Smørgrav #endif 50b7579f77SDag-Erling Smørgrav 51b7579f77SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_CONF_H 52b7579f77SDag-Erling Smørgrav #include <openssl/conf.h> 53b7579f77SDag-Erling Smørgrav #endif 54b7579f77SDag-Erling Smørgrav 55b7579f77SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ENGINE_H 56b7579f77SDag-Erling Smørgrav #include <openssl/engine.h> 57b7579f77SDag-Erling Smørgrav #endif 588ed2b524SDag-Erling Smørgrav 5917d15b25SDag-Erling Smørgrav #ifdef HAVE_TIME_H 6017d15b25SDag-Erling Smørgrav #include <time.h> 6117d15b25SDag-Erling Smørgrav #endif 6217d15b25SDag-Erling Smørgrav #include <sys/time.h> 6317d15b25SDag-Erling Smørgrav 648ed2b524SDag-Erling Smørgrav #ifdef HAVE_NSS 658ed2b524SDag-Erling Smørgrav /* nss3 */ 668ed2b524SDag-Erling Smørgrav #include "nss.h" 678ed2b524SDag-Erling Smørgrav #endif 688ed2b524SDag-Erling Smørgrav 69b7579f77SDag-Erling Smørgrav #include "daemon/daemon.h" 70b7579f77SDag-Erling Smørgrav #include "daemon/worker.h" 71b7579f77SDag-Erling Smørgrav #include "daemon/remote.h" 72b7579f77SDag-Erling Smørgrav #include "daemon/acl_list.h" 73b7579f77SDag-Erling Smørgrav #include "util/log.h" 74b7579f77SDag-Erling Smørgrav #include "util/config_file.h" 75b7579f77SDag-Erling Smørgrav #include "util/data/msgreply.h" 7665b390aaSDag-Erling Smørgrav #include "util/shm_side/shm_main.h" 77b7579f77SDag-Erling Smørgrav #include "util/storage/lookup3.h" 78b7579f77SDag-Erling Smørgrav #include "util/storage/slabhash.h" 794c75e3aaSDag-Erling Smørgrav #include "util/tcp_conn_limit.h" 80c0caa2e2SCy Schubert #include "util/edns.h" 81b7579f77SDag-Erling Smørgrav #include "services/listen_dnsport.h" 82b7579f77SDag-Erling Smørgrav #include "services/cache/rrset.h" 83b7579f77SDag-Erling Smørgrav #include "services/cache/infra.h" 84b7579f77SDag-Erling Smørgrav #include "services/localzone.h" 85bc892140SDag-Erling Smørgrav #include "services/view.h" 86b7579f77SDag-Erling Smørgrav #include "services/modstack.h" 8757bddd21SDag-Erling Smørgrav #include "services/authzone.h" 88b7579f77SDag-Erling Smørgrav #include "util/module.h" 89b7579f77SDag-Erling Smørgrav #include "util/random.h" 90b7579f77SDag-Erling Smørgrav #include "util/tube.h" 918ed2b524SDag-Erling Smørgrav #include "util/net_help.h" 9209a3aaf3SDag-Erling Smørgrav #include "sldns/keyraw.h" 9365b390aaSDag-Erling Smørgrav #include "respip/respip.h" 94335c7cdaSCy Schubert #include "iterator/iter_fwd.h" 95335c7cdaSCy Schubert #include "iterator/iter_hints.h" 96b7579f77SDag-Erling Smørgrav #include <signal.h> 97b7579f77SDag-Erling Smørgrav 983005e0a3SDag-Erling Smørgrav #ifdef HAVE_SYSTEMD 993005e0a3SDag-Erling Smørgrav #include <systemd/sd-daemon.h> 1003005e0a3SDag-Erling Smørgrav #endif 101865f46b2SCy Schubert #ifdef HAVE_NETDB_H 102865f46b2SCy Schubert #include <netdb.h> 103865f46b2SCy Schubert #endif 104335c7cdaSCy Schubert #ifdef USE_CACHEDB 105335c7cdaSCy Schubert #include "cachedb/cachedb.h" 106335c7cdaSCy Schubert #endif 1073005e0a3SDag-Erling Smørgrav 108b7579f77SDag-Erling Smørgrav /** How many quit requests happened. */ 109b7579f77SDag-Erling Smørgrav static int sig_record_quit = 0; 110b7579f77SDag-Erling Smørgrav /** How many reload requests happened. */ 111b7579f77SDag-Erling Smørgrav static int sig_record_reload = 0; 112b7579f77SDag-Erling Smørgrav 113b7579f77SDag-Erling Smørgrav #if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 114b7579f77SDag-Erling Smørgrav /** cleaner ssl memory freeup */ 115b7579f77SDag-Erling Smørgrav static void* comp_meth = NULL; 116b7579f77SDag-Erling Smørgrav #endif 117b7579f77SDag-Erling Smørgrav /** remove buffers for parsing and init */ 118b7579f77SDag-Erling Smørgrav int ub_c_lex_destroy(void); 119b7579f77SDag-Erling Smørgrav 120b7579f77SDag-Erling Smørgrav /** used when no other sighandling happens, so we don't die 121b7579f77SDag-Erling Smørgrav * when multiple signals in quick succession are sent to us. 122b7579f77SDag-Erling Smørgrav * @param sig: signal number. 123b7579f77SDag-Erling Smørgrav * @return signal handler return type (void or int). 124b7579f77SDag-Erling Smørgrav */ 125b7579f77SDag-Erling Smørgrav static RETSIGTYPE record_sigh(int sig) 126b7579f77SDag-Erling Smørgrav { 127b7579f77SDag-Erling Smørgrav #ifdef LIBEVENT_SIGNAL_PROBLEM 128ff825849SDag-Erling Smørgrav /* cannot log, verbose here because locks may be held */ 129ff825849SDag-Erling Smørgrav /* quit on signal, no cleanup and statistics, 130ff825849SDag-Erling Smørgrav because installed libevent version is not threadsafe */ 131b7579f77SDag-Erling Smørgrav exit(0); 132b7579f77SDag-Erling Smørgrav #endif 133b7579f77SDag-Erling Smørgrav switch(sig) 134b7579f77SDag-Erling Smørgrav { 135b7579f77SDag-Erling Smørgrav case SIGTERM: 136b7579f77SDag-Erling Smørgrav #ifdef SIGQUIT 137b7579f77SDag-Erling Smørgrav case SIGQUIT: 138b7579f77SDag-Erling Smørgrav #endif 139b7579f77SDag-Erling Smørgrav #ifdef SIGBREAK 140b7579f77SDag-Erling Smørgrav case SIGBREAK: 141b7579f77SDag-Erling Smørgrav #endif 142b7579f77SDag-Erling Smørgrav case SIGINT: 143b7579f77SDag-Erling Smørgrav sig_record_quit++; 144b7579f77SDag-Erling Smørgrav break; 145b7579f77SDag-Erling Smørgrav #ifdef SIGHUP 146b7579f77SDag-Erling Smørgrav case SIGHUP: 147b7579f77SDag-Erling Smørgrav sig_record_reload++; 148b7579f77SDag-Erling Smørgrav break; 149b7579f77SDag-Erling Smørgrav #endif 150b7579f77SDag-Erling Smørgrav #ifdef SIGPIPE 151b7579f77SDag-Erling Smørgrav case SIGPIPE: 152b7579f77SDag-Erling Smørgrav break; 153b7579f77SDag-Erling Smørgrav #endif 154b7579f77SDag-Erling Smørgrav default: 155ff825849SDag-Erling Smørgrav /* ignoring signal */ 156ff825849SDag-Erling Smørgrav break; 157b7579f77SDag-Erling Smørgrav } 158b7579f77SDag-Erling Smørgrav } 159b7579f77SDag-Erling Smørgrav 160b7579f77SDag-Erling Smørgrav /** 161b7579f77SDag-Erling Smørgrav * Signal handling during the time when netevent is disabled. 162b7579f77SDag-Erling Smørgrav * Stores signals to replay later. 163b7579f77SDag-Erling Smørgrav */ 164b7579f77SDag-Erling Smørgrav static void 165b7579f77SDag-Erling Smørgrav signal_handling_record(void) 166b7579f77SDag-Erling Smørgrav { 167b7579f77SDag-Erling Smørgrav if( signal(SIGTERM, record_sigh) == SIG_ERR || 168b7579f77SDag-Erling Smørgrav #ifdef SIGQUIT 169b7579f77SDag-Erling Smørgrav signal(SIGQUIT, record_sigh) == SIG_ERR || 170b7579f77SDag-Erling Smørgrav #endif 171b7579f77SDag-Erling Smørgrav #ifdef SIGBREAK 172b7579f77SDag-Erling Smørgrav signal(SIGBREAK, record_sigh) == SIG_ERR || 173b7579f77SDag-Erling Smørgrav #endif 174b7579f77SDag-Erling Smørgrav #ifdef SIGHUP 175b7579f77SDag-Erling Smørgrav signal(SIGHUP, record_sigh) == SIG_ERR || 176b7579f77SDag-Erling Smørgrav #endif 177b7579f77SDag-Erling Smørgrav #ifdef SIGPIPE 178b7579f77SDag-Erling Smørgrav signal(SIGPIPE, SIG_IGN) == SIG_ERR || 179b7579f77SDag-Erling Smørgrav #endif 180b7579f77SDag-Erling Smørgrav signal(SIGINT, record_sigh) == SIG_ERR 181b7579f77SDag-Erling Smørgrav ) 182b7579f77SDag-Erling Smørgrav log_err("install sighandler: %s", strerror(errno)); 183b7579f77SDag-Erling Smørgrav } 184b7579f77SDag-Erling Smørgrav 185b7579f77SDag-Erling Smørgrav /** 186b7579f77SDag-Erling Smørgrav * Replay old signals. 187b7579f77SDag-Erling Smørgrav * @param wrk: worker that handles signals. 188b7579f77SDag-Erling Smørgrav */ 189b7579f77SDag-Erling Smørgrav static void 190b7579f77SDag-Erling Smørgrav signal_handling_playback(struct worker* wrk) 191b7579f77SDag-Erling Smørgrav { 192b7579f77SDag-Erling Smørgrav #ifdef SIGHUP 1934c75e3aaSDag-Erling Smørgrav if(sig_record_reload) 194b7579f77SDag-Erling Smørgrav worker_sighandler(SIGHUP, wrk); 195b7579f77SDag-Erling Smørgrav #endif 196b7579f77SDag-Erling Smørgrav if(sig_record_quit) 197b7579f77SDag-Erling Smørgrav worker_sighandler(SIGTERM, wrk); 198b7579f77SDag-Erling Smørgrav sig_record_quit = 0; 199b7579f77SDag-Erling Smørgrav sig_record_reload = 0; 200b7579f77SDag-Erling Smørgrav } 201b7579f77SDag-Erling Smørgrav 202b7579f77SDag-Erling Smørgrav struct daemon* 203b7579f77SDag-Erling Smørgrav daemon_init(void) 204b7579f77SDag-Erling Smørgrav { 205b7579f77SDag-Erling Smørgrav struct daemon* daemon = (struct daemon*)calloc(1, 206b7579f77SDag-Erling Smørgrav sizeof(struct daemon)); 207b7579f77SDag-Erling Smørgrav #ifdef USE_WINSOCK 208b7579f77SDag-Erling Smørgrav int r; 209b7579f77SDag-Erling Smørgrav WSADATA wsa_data; 210b7579f77SDag-Erling Smørgrav #endif 211b7579f77SDag-Erling Smørgrav if(!daemon) 212b7579f77SDag-Erling Smørgrav return NULL; 213b7579f77SDag-Erling Smørgrav #ifdef USE_WINSOCK 214b7579f77SDag-Erling Smørgrav r = WSAStartup(MAKEWORD(2,2), &wsa_data); 215b7579f77SDag-Erling Smørgrav if(r != 0) { 216b7579f77SDag-Erling Smørgrav fatal_exit("could not init winsock. WSAStartup: %s", 217b7579f77SDag-Erling Smørgrav wsa_strerror(r)); 218b7579f77SDag-Erling Smørgrav } 219b7579f77SDag-Erling Smørgrav #endif /* USE_WINSOCK */ 220b7579f77SDag-Erling Smørgrav signal_handling_record(); 2218ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 222b5663de9SDag-Erling Smørgrav # ifdef HAVE_ERR_LOAD_CRYPTO_STRINGS 223b7579f77SDag-Erling Smørgrav ERR_load_crypto_strings(); 224b5663de9SDag-Erling Smørgrav # endif 225971980c3SDag-Erling Smørgrav #if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) 226b7579f77SDag-Erling Smørgrav ERR_load_SSL_strings(); 227971980c3SDag-Erling Smørgrav #endif 228b7579f77SDag-Erling Smørgrav # ifdef USE_GOST 22917d15b25SDag-Erling Smørgrav (void)sldns_key_EVP_load_gost_id(); 230b7579f77SDag-Erling Smørgrav # endif 231b5663de9SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_CRYPTO) 2320eefd307SCy Schubert # ifndef S_SPLINT_S 233b7579f77SDag-Erling Smørgrav OpenSSL_add_all_algorithms(); 2340eefd307SCy Schubert # endif 235b5663de9SDag-Erling Smørgrav # else 236b5663de9SDag-Erling Smørgrav OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS 237b5663de9SDag-Erling Smørgrav | OPENSSL_INIT_ADD_ALL_DIGESTS 238b5663de9SDag-Erling Smørgrav | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); 239b5663de9SDag-Erling Smørgrav # endif 240b7579f77SDag-Erling Smørgrav # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS 241b7579f77SDag-Erling Smørgrav /* grab the COMP method ptr because openssl leaks it */ 242b7579f77SDag-Erling Smørgrav comp_meth = (void*)SSL_COMP_get_compression_methods(); 243b7579f77SDag-Erling Smørgrav # endif 244b5663de9SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 || !defined(HAVE_OPENSSL_INIT_SSL) 245b7579f77SDag-Erling Smørgrav (void)SSL_library_init(); 246b5663de9SDag-Erling Smørgrav # else 247971980c3SDag-Erling Smørgrav (void)OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); 248b5663de9SDag-Erling Smørgrav # endif 2498ed2b524SDag-Erling Smørgrav # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 2508ed2b524SDag-Erling Smørgrav if(!ub_openssl_lock_init()) 2518ed2b524SDag-Erling Smørgrav fatal_exit("could not init openssl locks"); 2528ed2b524SDag-Erling Smørgrav # endif 2538ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 2548ed2b524SDag-Erling Smørgrav if(NSS_NoDB_Init(NULL) != SECSuccess) 2558ed2b524SDag-Erling Smørgrav fatal_exit("could not init NSS"); 2568ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS */ 257b7579f77SDag-Erling Smørgrav #ifdef HAVE_TZSET 258b7579f77SDag-Erling Smørgrav /* init timezone info while we are not chrooted yet */ 259b7579f77SDag-Erling Smørgrav tzset(); 260b7579f77SDag-Erling Smørgrav #endif 261b7579f77SDag-Erling Smørgrav daemon->need_to_exit = 0; 262b7579f77SDag-Erling Smørgrav modstack_init(&daemon->mods); 263b7579f77SDag-Erling Smørgrav if(!(daemon->env = (struct module_env*)calloc(1, 264b7579f77SDag-Erling Smørgrav sizeof(*daemon->env)))) { 265b7579f77SDag-Erling Smørgrav free(daemon); 266b7579f77SDag-Erling Smørgrav return NULL; 267b7579f77SDag-Erling Smørgrav } 268335c7cdaSCy Schubert daemon->env->modstack = &daemon->mods; 269bc892140SDag-Erling Smørgrav /* init edns_known_options */ 270bc892140SDag-Erling Smørgrav if(!edns_known_options_init(daemon->env)) { 271bc892140SDag-Erling Smørgrav free(daemon->env); 272bc892140SDag-Erling Smørgrav free(daemon); 273bc892140SDag-Erling Smørgrav return NULL; 274bc892140SDag-Erling Smørgrav } 275b7579f77SDag-Erling Smørgrav alloc_init(&daemon->superalloc, NULL, 0); 276b7579f77SDag-Erling Smørgrav daemon->acl = acl_list_create(); 277b7579f77SDag-Erling Smørgrav if(!daemon->acl) { 278bc892140SDag-Erling Smørgrav edns_known_options_delete(daemon->env); 279b7579f77SDag-Erling Smørgrav free(daemon->env); 280b7579f77SDag-Erling Smørgrav free(daemon); 281b7579f77SDag-Erling Smørgrav return NULL; 282b7579f77SDag-Erling Smørgrav } 283865f46b2SCy Schubert daemon->acl_interface = acl_list_create(); 284865f46b2SCy Schubert if(!daemon->acl_interface) { 285865f46b2SCy Schubert acl_list_delete(daemon->acl); 286865f46b2SCy Schubert edns_known_options_delete(daemon->env); 287865f46b2SCy Schubert free(daemon->env); 288865f46b2SCy Schubert free(daemon); 289865f46b2SCy Schubert return NULL; 290865f46b2SCy Schubert } 2914c75e3aaSDag-Erling Smørgrav daemon->tcl = tcl_list_create(); 2924c75e3aaSDag-Erling Smørgrav if(!daemon->tcl) { 293865f46b2SCy Schubert acl_list_delete(daemon->acl_interface); 2944c75e3aaSDag-Erling Smørgrav acl_list_delete(daemon->acl); 2954c75e3aaSDag-Erling Smørgrav edns_known_options_delete(daemon->env); 2964c75e3aaSDag-Erling Smørgrav free(daemon->env); 2974c75e3aaSDag-Erling Smørgrav free(daemon); 2984c75e3aaSDag-Erling Smørgrav return NULL; 2994c75e3aaSDag-Erling Smørgrav } 30024e36522SCy Schubert listen_setup_locks(); 301b7579f77SDag-Erling Smørgrav if(gettimeofday(&daemon->time_boot, NULL) < 0) 302b7579f77SDag-Erling Smørgrav log_err("gettimeofday: %s", strerror(errno)); 303b7579f77SDag-Erling Smørgrav daemon->time_last_stat = daemon->time_boot; 30457bddd21SDag-Erling Smørgrav if((daemon->env->auth_zones = auth_zones_create()) == 0) { 305865f46b2SCy Schubert acl_list_delete(daemon->acl_interface); 30657bddd21SDag-Erling Smørgrav acl_list_delete(daemon->acl); 3074c75e3aaSDag-Erling Smørgrav tcl_list_delete(daemon->tcl); 30857bddd21SDag-Erling Smørgrav edns_known_options_delete(daemon->env); 30957bddd21SDag-Erling Smørgrav free(daemon->env); 31057bddd21SDag-Erling Smørgrav free(daemon); 31157bddd21SDag-Erling Smørgrav return NULL; 31257bddd21SDag-Erling Smørgrav } 313369c6923SCy Schubert if(!(daemon->env->edns_strings = edns_strings_create())) { 314c0caa2e2SCy Schubert auth_zones_delete(daemon->env->auth_zones); 315865f46b2SCy Schubert acl_list_delete(daemon->acl_interface); 316c0caa2e2SCy Schubert acl_list_delete(daemon->acl); 317c0caa2e2SCy Schubert tcl_list_delete(daemon->tcl); 318c0caa2e2SCy Schubert edns_known_options_delete(daemon->env); 319c0caa2e2SCy Schubert free(daemon->env); 320c0caa2e2SCy Schubert free(daemon); 321c0caa2e2SCy Schubert return NULL; 322c0caa2e2SCy Schubert } 323b7579f77SDag-Erling Smørgrav return daemon; 324b7579f77SDag-Erling Smørgrav } 325b7579f77SDag-Erling Smørgrav 326*be771a7bSCy Schubert int setup_acl_for_ports(struct acl_list* list, struct listen_port* port_list) 327865f46b2SCy Schubert { 328865f46b2SCy Schubert struct acl_addr* acl_node; 329865f46b2SCy Schubert for(; port_list; port_list=port_list->next) { 330865f46b2SCy Schubert if(!port_list->socket) { 331865f46b2SCy Schubert /* This is mainly for testbound where port_list is 332865f46b2SCy Schubert * empty. */ 333865f46b2SCy Schubert continue; 334865f46b2SCy Schubert } 335865f46b2SCy Schubert if(!(acl_node = acl_interface_insert(list, 336335c7cdaSCy Schubert (struct sockaddr_storage*)port_list->socket->addr, 337335c7cdaSCy Schubert port_list->socket->addrlen, 338865f46b2SCy Schubert acl_refuse))) { 339865f46b2SCy Schubert return 0; 340865f46b2SCy Schubert } 341865f46b2SCy Schubert port_list->socket->acl = acl_node; 342865f46b2SCy Schubert } 343865f46b2SCy Schubert return 1; 344865f46b2SCy Schubert } 345865f46b2SCy Schubert 346b7579f77SDag-Erling Smørgrav int 347b7579f77SDag-Erling Smørgrav daemon_open_shared_ports(struct daemon* daemon) 348b7579f77SDag-Erling Smørgrav { 349b7579f77SDag-Erling Smørgrav log_assert(daemon); 350b7579f77SDag-Erling Smørgrav if(daemon->cfg->port != daemon->listening_port) { 351c0caa2e2SCy Schubert char** resif = NULL; 352c0caa2e2SCy Schubert int num_resif = 0; 35317d15b25SDag-Erling Smørgrav size_t i; 35417d15b25SDag-Erling Smørgrav struct listen_port* p0; 355ff825849SDag-Erling Smørgrav daemon->reuseport = 0; 35617d15b25SDag-Erling Smørgrav /* free and close old ports */ 35717d15b25SDag-Erling Smørgrav if(daemon->ports != NULL) { 35817d15b25SDag-Erling Smørgrav for(i=0; i<daemon->num_ports; i++) 35917d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 36017d15b25SDag-Erling Smørgrav free(daemon->ports); 36117d15b25SDag-Erling Smørgrav daemon->ports = NULL; 36217d15b25SDag-Erling Smørgrav } 363865f46b2SCy Schubert /* clean acl_interface */ 364865f46b2SCy Schubert acl_interface_init(daemon->acl_interface); 3655469a995SCy Schubert if(!resolve_interface_names(daemon->cfg->ifs, 3665469a995SCy Schubert daemon->cfg->num_ifs, NULL, &resif, &num_resif)) 367c0caa2e2SCy Schubert return 0; 36817d15b25SDag-Erling Smørgrav /* see if we want to reuseport */ 369ff825849SDag-Erling Smørgrav #ifdef SO_REUSEPORT 37017d15b25SDag-Erling Smørgrav if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0) 371ff825849SDag-Erling Smørgrav daemon->reuseport = 1; 37217d15b25SDag-Erling Smørgrav #endif 37317d15b25SDag-Erling Smørgrav /* try to use reuseport */ 374865f46b2SCy Schubert p0 = listening_ports_open(daemon->cfg, resif, num_resif, 375865f46b2SCy Schubert &daemon->reuseport); 37617d15b25SDag-Erling Smørgrav if(!p0) { 37717d15b25SDag-Erling Smørgrav listening_ports_free(p0); 378c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 379b7579f77SDag-Erling Smørgrav return 0; 38017d15b25SDag-Erling Smørgrav } 381ff825849SDag-Erling Smørgrav if(daemon->reuseport) { 38217d15b25SDag-Erling Smørgrav /* reuseport was successful, allocate for it */ 38317d15b25SDag-Erling Smørgrav daemon->num_ports = (size_t)daemon->cfg->num_threads; 38417d15b25SDag-Erling Smørgrav } else { 38517d15b25SDag-Erling Smørgrav /* do the normal, singleportslist thing, 38617d15b25SDag-Erling Smørgrav * reuseport not enabled or did not work */ 38717d15b25SDag-Erling Smørgrav daemon->num_ports = 1; 38817d15b25SDag-Erling Smørgrav } 38917d15b25SDag-Erling Smørgrav if(!(daemon->ports = (struct listen_port**)calloc( 39017d15b25SDag-Erling Smørgrav daemon->num_ports, sizeof(*daemon->ports)))) { 39117d15b25SDag-Erling Smørgrav listening_ports_free(p0); 392c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 39317d15b25SDag-Erling Smørgrav return 0; 39417d15b25SDag-Erling Smørgrav } 39517d15b25SDag-Erling Smørgrav daemon->ports[0] = p0; 396865f46b2SCy Schubert if(!setup_acl_for_ports(daemon->acl_interface, 397865f46b2SCy Schubert daemon->ports[0])) { 398865f46b2SCy Schubert listening_ports_free(p0); 399865f46b2SCy Schubert config_del_strarray(resif, num_resif); 400865f46b2SCy Schubert return 0; 401865f46b2SCy Schubert } 402ff825849SDag-Erling Smørgrav if(daemon->reuseport) { 40317d15b25SDag-Erling Smørgrav /* continue to use reuseport */ 40417d15b25SDag-Erling Smørgrav for(i=1; i<daemon->num_ports; i++) { 40517d15b25SDag-Erling Smørgrav if(!(daemon->ports[i]= 40617d15b25SDag-Erling Smørgrav listening_ports_open(daemon->cfg, 407c0caa2e2SCy Schubert resif, num_resif, 408ff825849SDag-Erling Smørgrav &daemon->reuseport)) 409ff825849SDag-Erling Smørgrav || !daemon->reuseport ) { 41017d15b25SDag-Erling Smørgrav for(i=0; i<daemon->num_ports; i++) 41117d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 41217d15b25SDag-Erling Smørgrav free(daemon->ports); 41317d15b25SDag-Erling Smørgrav daemon->ports = NULL; 414c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 41517d15b25SDag-Erling Smørgrav return 0; 41617d15b25SDag-Erling Smørgrav } 417865f46b2SCy Schubert if(!setup_acl_for_ports(daemon->acl_interface, 418865f46b2SCy Schubert daemon->ports[i])) { 419865f46b2SCy Schubert for(i=0; i<daemon->num_ports; i++) 420865f46b2SCy Schubert listening_ports_free(daemon->ports[i]); 421865f46b2SCy Schubert free(daemon->ports); 422865f46b2SCy Schubert daemon->ports = NULL; 423865f46b2SCy Schubert config_del_strarray(resif, num_resif); 424865f46b2SCy Schubert return 0; 425865f46b2SCy Schubert } 42617d15b25SDag-Erling Smørgrav } 42717d15b25SDag-Erling Smørgrav } 428c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 429b7579f77SDag-Erling Smørgrav daemon->listening_port = daemon->cfg->port; 430b7579f77SDag-Erling Smørgrav } 431b7579f77SDag-Erling Smørgrav if(!daemon->cfg->remote_control_enable && daemon->rc_port) { 432b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 433b7579f77SDag-Erling Smørgrav daemon->rc_ports = NULL; 434b7579f77SDag-Erling Smørgrav daemon->rc_port = 0; 435b7579f77SDag-Erling Smørgrav } 436b7579f77SDag-Erling Smørgrav if(daemon->cfg->remote_control_enable && 437b7579f77SDag-Erling Smørgrav daemon->cfg->control_port != daemon->rc_port) { 438b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 439b7579f77SDag-Erling Smørgrav if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg))) 440b7579f77SDag-Erling Smørgrav return 0; 441b7579f77SDag-Erling Smørgrav daemon->rc_port = daemon->cfg->control_port; 442b7579f77SDag-Erling Smørgrav } 443b7579f77SDag-Erling Smørgrav return 1; 444b7579f77SDag-Erling Smørgrav } 445b7579f77SDag-Erling Smørgrav 44656850988SCy Schubert int 44756850988SCy Schubert daemon_privileged(struct daemon* daemon) 44856850988SCy Schubert { 44956850988SCy Schubert daemon->env->cfg = daemon->cfg; 45056850988SCy Schubert daemon->env->alloc = &daemon->superalloc; 45156850988SCy Schubert daemon->env->worker = NULL; 45256850988SCy Schubert if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf, 45356850988SCy Schubert daemon->env)) { 45456850988SCy Schubert fatal_exit("failed to startup modules"); 45556850988SCy Schubert } 45656850988SCy Schubert return 1; 45756850988SCy Schubert } 45856850988SCy Schubert 459b7579f77SDag-Erling Smørgrav /** 460b7579f77SDag-Erling Smørgrav * Setup modules. setup module stack. 461b7579f77SDag-Erling Smørgrav * @param daemon: the daemon 462b7579f77SDag-Erling Smørgrav */ 463b7579f77SDag-Erling Smørgrav static void daemon_setup_modules(struct daemon* daemon) 464b7579f77SDag-Erling Smørgrav { 465b7579f77SDag-Erling Smørgrav daemon->env->cfg = daemon->cfg; 466b7579f77SDag-Erling Smørgrav daemon->env->alloc = &daemon->superalloc; 467b7579f77SDag-Erling Smørgrav daemon->env->worker = NULL; 46856850988SCy Schubert if(daemon->mods_inited) { 46956850988SCy Schubert modstack_call_deinit(&daemon->mods, daemon->env); 470b7579f77SDag-Erling Smørgrav } 47156850988SCy Schubert daemon->env->need_to_validate = 0; /* set by module init below */ 47256850988SCy Schubert if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf, 47356850988SCy Schubert daemon->env)) { 47456850988SCy Schubert fatal_exit("failed to init modules"); 47556850988SCy Schubert } 47656850988SCy Schubert daemon->mods_inited = 1; 477bc892140SDag-Erling Smørgrav log_edns_known_options(VERB_ALGO, daemon->env); 478b7579f77SDag-Erling Smørgrav } 479b7579f77SDag-Erling Smørgrav 480b7579f77SDag-Erling Smørgrav /** 481b7579f77SDag-Erling Smørgrav * Obtain allowed port numbers, concatenate the list, and shuffle them 482b7579f77SDag-Erling Smørgrav * (ready to be handed out to threads). 483b7579f77SDag-Erling Smørgrav * @param daemon: the daemon. Uses rand and cfg. 484b7579f77SDag-Erling Smørgrav * @param shufport: the portlist output. 485b7579f77SDag-Erling Smørgrav * @return number of ports available. 486b7579f77SDag-Erling Smørgrav */ 487b7579f77SDag-Erling Smørgrav static int daemon_get_shufport(struct daemon* daemon, int* shufport) 488b7579f77SDag-Erling Smørgrav { 489b7579f77SDag-Erling Smørgrav int i, n, k, temp; 490b7579f77SDag-Erling Smørgrav int avail = 0; 491b7579f77SDag-Erling Smørgrav for(i=0; i<65536; i++) { 492b7579f77SDag-Erling Smørgrav if(daemon->cfg->outgoing_avail_ports[i]) { 493b7579f77SDag-Erling Smørgrav shufport[avail++] = daemon->cfg-> 494b7579f77SDag-Erling Smørgrav outgoing_avail_ports[i]; 495b7579f77SDag-Erling Smørgrav } 496b7579f77SDag-Erling Smørgrav } 497b7579f77SDag-Erling Smørgrav if(avail == 0) 498b7579f77SDag-Erling Smørgrav fatal_exit("no ports are permitted for UDP, add " 499b7579f77SDag-Erling Smørgrav "with outgoing-port-permit"); 500b7579f77SDag-Erling Smørgrav /* Knuth shuffle */ 501b7579f77SDag-Erling Smørgrav n = avail; 502b7579f77SDag-Erling Smørgrav while(--n > 0) { 503b7579f77SDag-Erling Smørgrav k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */ 504b7579f77SDag-Erling Smørgrav temp = shufport[k]; 505b7579f77SDag-Erling Smørgrav shufport[k] = shufport[n]; 506b7579f77SDag-Erling Smørgrav shufport[n] = temp; 507b7579f77SDag-Erling Smørgrav } 508b7579f77SDag-Erling Smørgrav return avail; 509b7579f77SDag-Erling Smørgrav } 510b7579f77SDag-Erling Smørgrav 511b7579f77SDag-Erling Smørgrav /** 5121838dec3SCy Schubert * Clear and delete per-worker alloc caches, and free memory maintained in 5131838dec3SCy Schubert * superalloc. 5141838dec3SCy Schubert * The rrset and message caches must be empty at the time of call. 5151838dec3SCy Schubert * @param daemon: the daemon that maintains the alloc caches to be cleared. 5161838dec3SCy Schubert */ 5171838dec3SCy Schubert static void 5181838dec3SCy Schubert daemon_clear_allocs(struct daemon* daemon) 5191838dec3SCy Schubert { 5201838dec3SCy Schubert int i; 5211838dec3SCy Schubert 52256850988SCy Schubert /* daemon->num may be different during reloads (after configuration 52356850988SCy Schubert * read). Use old_num which has the correct value used to setup the 52456850988SCy Schubert * worker_allocs */ 52556850988SCy Schubert for(i=0; i<daemon->old_num; i++) { 5261838dec3SCy Schubert alloc_clear(daemon->worker_allocs[i]); 5271838dec3SCy Schubert free(daemon->worker_allocs[i]); 5281838dec3SCy Schubert } 5291838dec3SCy Schubert free(daemon->worker_allocs); 5301838dec3SCy Schubert daemon->worker_allocs = NULL; 5311838dec3SCy Schubert 5321838dec3SCy Schubert alloc_clear_special(&daemon->superalloc); 5331838dec3SCy Schubert } 5341838dec3SCy Schubert 5351838dec3SCy Schubert /** 536b7579f77SDag-Erling Smørgrav * Allocate empty worker structures. With backptr and thread-number, 537b7579f77SDag-Erling Smørgrav * from 0..numthread initialised. Used as user arguments to new threads. 538b7579f77SDag-Erling Smørgrav * Creates the daemon random generator if it does not exist yet. 539b7579f77SDag-Erling Smørgrav * The random generator stays existing between reloads with a unique state. 540b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with (new) config settings. 541b7579f77SDag-Erling Smørgrav */ 542b7579f77SDag-Erling Smørgrav static void 543b7579f77SDag-Erling Smørgrav daemon_create_workers(struct daemon* daemon) 544b7579f77SDag-Erling Smørgrav { 545b7579f77SDag-Erling Smørgrav int i, numport; 546b7579f77SDag-Erling Smørgrav int* shufport; 547b7579f77SDag-Erling Smørgrav log_assert(daemon && daemon->cfg); 548b7579f77SDag-Erling Smørgrav if(!daemon->rand) { 5490eefd307SCy Schubert daemon->rand = ub_initstate(NULL); 550b7579f77SDag-Erling Smørgrav if(!daemon->rand) 551b7579f77SDag-Erling Smørgrav fatal_exit("could not init random generator"); 552b7579f77SDag-Erling Smørgrav hash_set_raninit((uint32_t)ub_random(daemon->rand)); 553971980c3SDag-Erling Smørgrav } 554b7579f77SDag-Erling Smørgrav shufport = (int*)calloc(65536, sizeof(int)); 555b7579f77SDag-Erling Smørgrav if(!shufport) 556b7579f77SDag-Erling Smørgrav fatal_exit("out of memory during daemon init"); 557b7579f77SDag-Erling Smørgrav numport = daemon_get_shufport(daemon, shufport); 558b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "total of %d outgoing ports available", numport); 559b7579f77SDag-Erling Smørgrav 56046d2f618SCy Schubert #ifdef HAVE_NGTCP2 56146d2f618SCy Schubert daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand); 56246d2f618SCy Schubert if(!daemon->doq_table) 56346d2f618SCy Schubert fatal_exit("could not create doq_table: out of memory"); 56446d2f618SCy Schubert #endif 56546d2f618SCy Schubert 566b7579f77SDag-Erling Smørgrav daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); 567b75612f8SDag-Erling Smørgrav if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) { 568b75612f8SDag-Erling Smørgrav log_warn("cannot reduce num-threads to %d because so-reuseport " 569b75612f8SDag-Erling Smørgrav "so continuing with %d threads.", (int)daemon->num, 570b75612f8SDag-Erling Smørgrav (int)daemon->num_ports); 571b75612f8SDag-Erling Smørgrav daemon->num = (int)daemon->num_ports; 572b75612f8SDag-Erling Smørgrav } 573b7579f77SDag-Erling Smørgrav daemon->workers = (struct worker**)calloc((size_t)daemon->num, 574b7579f77SDag-Erling Smørgrav sizeof(struct worker*)); 575b5663de9SDag-Erling Smørgrav if(!daemon->workers) 576b5663de9SDag-Erling Smørgrav fatal_exit("out of memory during daemon init"); 577ff825849SDag-Erling Smørgrav if(daemon->cfg->dnstap) { 578ff825849SDag-Erling Smørgrav #ifdef USE_DNSTAP 57925039b37SCy Schubert daemon->dtenv = dt_create(daemon->cfg); 580ff825849SDag-Erling Smørgrav if (!daemon->dtenv) 581ff825849SDag-Erling Smørgrav fatal_exit("dt_create failed"); 582ff825849SDag-Erling Smørgrav #else 583ff825849SDag-Erling Smørgrav fatal_exit("dnstap enabled in config but not built with dnstap support"); 584ff825849SDag-Erling Smørgrav #endif 585ff825849SDag-Erling Smørgrav } 586b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) { 587b7579f77SDag-Erling Smørgrav if(!(daemon->workers[i] = worker_create(daemon, i, 588b7579f77SDag-Erling Smørgrav shufport+numport*i/daemon->num, 589b7579f77SDag-Erling Smørgrav numport*(i+1)/daemon->num - numport*i/daemon->num))) 590b7579f77SDag-Erling Smørgrav /* the above is not ports/numthr, due to rounding */ 591b7579f77SDag-Erling Smørgrav fatal_exit("could not create worker"); 592b7579f77SDag-Erling Smørgrav } 5931838dec3SCy Schubert /* create per-worker alloc caches if not reusing existing ones. */ 5941838dec3SCy Schubert if(!daemon->worker_allocs) { 5951838dec3SCy Schubert daemon->worker_allocs = (struct alloc_cache**)calloc( 5961838dec3SCy Schubert (size_t)daemon->num, sizeof(struct alloc_cache*)); 5971838dec3SCy Schubert if(!daemon->worker_allocs) 5981838dec3SCy Schubert fatal_exit("could not allocate worker allocs"); 5991838dec3SCy Schubert for(i=0; i<daemon->num; i++) { 6001838dec3SCy Schubert struct alloc_cache* alloc = calloc(1, 6011838dec3SCy Schubert sizeof(struct alloc_cache)); 6021838dec3SCy Schubert if (!alloc) 6031838dec3SCy Schubert fatal_exit("could not allocate worker alloc"); 6041838dec3SCy Schubert alloc_init(alloc, &daemon->superalloc, i); 6051838dec3SCy Schubert daemon->worker_allocs[i] = alloc; 6061838dec3SCy Schubert } 6071838dec3SCy Schubert } 608b7579f77SDag-Erling Smørgrav free(shufport); 609b7579f77SDag-Erling Smørgrav } 610b7579f77SDag-Erling Smørgrav 611b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 612b7579f77SDag-Erling Smørgrav /** 613b7579f77SDag-Erling Smørgrav * Close all pipes except for the numbered thread. 614b7579f77SDag-Erling Smørgrav * @param daemon: daemon to close pipes in. 615b7579f77SDag-Erling Smørgrav * @param thr: thread number 0..num-1 of thread to skip. 616b7579f77SDag-Erling Smørgrav */ 617b7579f77SDag-Erling Smørgrav static void close_other_pipes(struct daemon* daemon, int thr) 618b7579f77SDag-Erling Smørgrav { 619b7579f77SDag-Erling Smørgrav int i; 620b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) 621b7579f77SDag-Erling Smørgrav if(i!=thr) { 622b7579f77SDag-Erling Smørgrav if(i==0) { 623b7579f77SDag-Erling Smørgrav /* only close read part, need to write stats */ 624b7579f77SDag-Erling Smørgrav tube_close_read(daemon->workers[i]->cmd); 625b7579f77SDag-Erling Smørgrav } else { 626b7579f77SDag-Erling Smørgrav /* complete close channel to others */ 627b7579f77SDag-Erling Smørgrav tube_delete(daemon->workers[i]->cmd); 628b7579f77SDag-Erling Smørgrav daemon->workers[i]->cmd = NULL; 629b7579f77SDag-Erling Smørgrav } 630b7579f77SDag-Erling Smørgrav } 631b7579f77SDag-Erling Smørgrav } 632b7579f77SDag-Erling Smørgrav #endif /* THREADS_DISABLED */ 633b7579f77SDag-Erling Smørgrav 634b7579f77SDag-Erling Smørgrav /** 635b7579f77SDag-Erling Smørgrav * Function to start one thread. 636b7579f77SDag-Erling Smørgrav * @param arg: user argument. 637b7579f77SDag-Erling Smørgrav * @return: void* user return value could be used for thread_join results. 638b7579f77SDag-Erling Smørgrav */ 639b7579f77SDag-Erling Smørgrav static void* 640b7579f77SDag-Erling Smørgrav thread_start(void* arg) 641b7579f77SDag-Erling Smørgrav { 642b7579f77SDag-Erling Smørgrav struct worker* worker = (struct worker*)arg; 64317d15b25SDag-Erling Smørgrav int port_num = 0; 644b7579f77SDag-Erling Smørgrav log_thread_set(&worker->thread_num); 645b7579f77SDag-Erling Smørgrav ub_thread_blocksigs(); 646b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 647b7579f77SDag-Erling Smørgrav /* close pipe ends used by main */ 648b7579f77SDag-Erling Smørgrav tube_close_write(worker->cmd); 649b7579f77SDag-Erling Smørgrav close_other_pipes(worker->daemon, worker->thread_num); 650b7579f77SDag-Erling Smørgrav #endif 651ff825849SDag-Erling Smørgrav #ifdef SO_REUSEPORT 65217d15b25SDag-Erling Smørgrav if(worker->daemon->cfg->so_reuseport) 653b75612f8SDag-Erling Smørgrav port_num = worker->thread_num % worker->daemon->num_ports; 65417d15b25SDag-Erling Smørgrav else 65517d15b25SDag-Erling Smørgrav port_num = 0; 65617d15b25SDag-Erling Smørgrav #endif 65717d15b25SDag-Erling Smørgrav if(!worker_init(worker, worker->daemon->cfg, 65817d15b25SDag-Erling Smørgrav worker->daemon->ports[port_num], 0)) 659b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize thread"); 660b7579f77SDag-Erling Smørgrav 661b7579f77SDag-Erling Smørgrav worker_work(worker); 662b7579f77SDag-Erling Smørgrav return NULL; 663b7579f77SDag-Erling Smørgrav } 664b7579f77SDag-Erling Smørgrav 665b7579f77SDag-Erling Smørgrav /** 666b7579f77SDag-Erling Smørgrav * Fork and init the other threads. Main thread returns for special handling. 667b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with other threads to fork. 668b7579f77SDag-Erling Smørgrav */ 669b7579f77SDag-Erling Smørgrav static void 670b7579f77SDag-Erling Smørgrav daemon_start_others(struct daemon* daemon) 671b7579f77SDag-Erling Smørgrav { 672b7579f77SDag-Erling Smørgrav int i; 673b7579f77SDag-Erling Smørgrav log_assert(daemon); 674b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "start threads"); 675b7579f77SDag-Erling Smørgrav /* skip i=0, is this thread */ 676b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 677b7579f77SDag-Erling Smørgrav ub_thread_create(&daemon->workers[i]->thr_id, 678b7579f77SDag-Erling Smørgrav thread_start, daemon->workers[i]); 679b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 680b7579f77SDag-Erling Smørgrav /* close pipe end of child */ 681b7579f77SDag-Erling Smørgrav tube_close_read(daemon->workers[i]->cmd); 682b7579f77SDag-Erling Smørgrav #endif /* no threads */ 683b7579f77SDag-Erling Smørgrav } 684b7579f77SDag-Erling Smørgrav } 685b7579f77SDag-Erling Smørgrav 686b7579f77SDag-Erling Smørgrav /** 687b7579f77SDag-Erling Smørgrav * Stop the other threads. 688b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with other threads. 689b7579f77SDag-Erling Smørgrav */ 690b7579f77SDag-Erling Smørgrav static void 691b7579f77SDag-Erling Smørgrav daemon_stop_others(struct daemon* daemon) 692b7579f77SDag-Erling Smørgrav { 693b7579f77SDag-Erling Smørgrav int i; 694b7579f77SDag-Erling Smørgrav log_assert(daemon); 695b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "stop threads"); 696b7579f77SDag-Erling Smørgrav /* skip i=0, is this thread */ 697b7579f77SDag-Erling Smørgrav /* use i=0 buffer for sending cmds; because we are #0 */ 698b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 699b7579f77SDag-Erling Smørgrav worker_send_cmd(daemon->workers[i], worker_cmd_quit); 700b7579f77SDag-Erling Smørgrav } 701b7579f77SDag-Erling Smørgrav /* wait for them to quit */ 702b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 703b7579f77SDag-Erling Smørgrav /* join it to make sure its dead */ 704b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "join %d", i); 705b7579f77SDag-Erling Smørgrav ub_thread_join(daemon->workers[i]->thr_id); 706b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "join success %d", i); 707b7579f77SDag-Erling Smørgrav } 708b7579f77SDag-Erling Smørgrav } 709b7579f77SDag-Erling Smørgrav 710b7579f77SDag-Erling Smørgrav void 711b7579f77SDag-Erling Smørgrav daemon_fork(struct daemon* daemon) 712b7579f77SDag-Erling Smørgrav { 71365b390aaSDag-Erling Smørgrav int have_view_respip_cfg = 0; 7140eefd307SCy Schubert #ifdef HAVE_SYSTEMD 7150eefd307SCy Schubert int ret; 7160eefd307SCy Schubert #endif 71765b390aaSDag-Erling Smørgrav 718b7579f77SDag-Erling Smørgrav log_assert(daemon); 719*be771a7bSCy Schubert if(!(daemon->env->views = views_create())) 720bc892140SDag-Erling Smørgrav fatal_exit("Could not create views: out of memory"); 721bc892140SDag-Erling Smørgrav /* create individual views and their localzone/data trees */ 722*be771a7bSCy Schubert if(!views_apply_cfg(daemon->env->views, daemon->cfg)) 723bc892140SDag-Erling Smørgrav fatal_exit("Could not set up views"); 724bc892140SDag-Erling Smørgrav 725*be771a7bSCy Schubert if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->env->views)) 726b7579f77SDag-Erling Smørgrav fatal_exit("Could not setup access control list"); 727865f46b2SCy Schubert if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg, 728*be771a7bSCy Schubert daemon->env->views)) 729865f46b2SCy Schubert fatal_exit("Could not setup interface control list"); 7304c75e3aaSDag-Erling Smørgrav if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg)) 7314c75e3aaSDag-Erling Smørgrav fatal_exit("Could not setup TCP connection limits"); 73265b390aaSDag-Erling Smørgrav if(daemon->cfg->dnscrypt) { 73365b390aaSDag-Erling Smørgrav #ifdef USE_DNSCRYPT 73465b390aaSDag-Erling Smørgrav daemon->dnscenv = dnsc_create(); 73565b390aaSDag-Erling Smørgrav if (!daemon->dnscenv) 73665b390aaSDag-Erling Smørgrav fatal_exit("dnsc_create failed"); 73765b390aaSDag-Erling Smørgrav dnsc_apply_cfg(daemon->dnscenv, daemon->cfg); 73865b390aaSDag-Erling Smørgrav #else 73965b390aaSDag-Erling Smørgrav fatal_exit("dnscrypt enabled in config but unbound was not built with " 74065b390aaSDag-Erling Smørgrav "dnscrypt support"); 74165b390aaSDag-Erling Smørgrav #endif 74265b390aaSDag-Erling Smørgrav } 74356850988SCy Schubert if(daemon->cfg->cookie_secret_file && 74456850988SCy Schubert daemon->cfg->cookie_secret_file[0]) { 74556850988SCy Schubert if(!(daemon->cookie_secrets = cookie_secrets_create())) 74656850988SCy Schubert fatal_exit("Could not create cookie_secrets: out of memory"); 74756850988SCy Schubert if(!cookie_secrets_apply_cfg(daemon->cookie_secrets, 74856850988SCy Schubert daemon->cfg->cookie_secret_file)) 74956850988SCy Schubert fatal_exit("Could not setup cookie_secrets"); 75056850988SCy Schubert } 751bc892140SDag-Erling Smørgrav /* create global local_zones */ 752b7579f77SDag-Erling Smørgrav if(!(daemon->local_zones = local_zones_create())) 753b7579f77SDag-Erling Smørgrav fatal_exit("Could not create local zones: out of memory"); 754b7579f77SDag-Erling Smørgrav if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) 755b7579f77SDag-Erling Smørgrav fatal_exit("Could not set up local zones"); 756335c7cdaSCy Schubert if(!(daemon->env->fwds = forwards_create()) || 757335c7cdaSCy Schubert !forwards_apply_cfg(daemon->env->fwds, daemon->cfg)) 758335c7cdaSCy Schubert fatal_exit("Could not set forward zones"); 759335c7cdaSCy Schubert if(!(daemon->env->hints = hints_create()) || 760335c7cdaSCy Schubert !hints_apply_cfg(daemon->env->hints, daemon->cfg)) 761335c7cdaSCy Schubert fatal_exit("Could not set root or stub hints"); 762b7579f77SDag-Erling Smørgrav 76365b390aaSDag-Erling Smørgrav /* process raw response-ip configuration data */ 764*be771a7bSCy Schubert if(!(daemon->env->respip_set = respip_set_create())) 76565b390aaSDag-Erling Smørgrav fatal_exit("Could not create response IP set"); 766*be771a7bSCy Schubert if(!respip_global_apply_cfg(daemon->env->respip_set, daemon->cfg)) 76765b390aaSDag-Erling Smørgrav fatal_exit("Could not set up response IP set"); 768*be771a7bSCy Schubert if(!respip_views_apply_cfg(daemon->env->views, daemon->cfg, 76965b390aaSDag-Erling Smørgrav &have_view_respip_cfg)) 77065b390aaSDag-Erling Smørgrav fatal_exit("Could not set up per-view response IP sets"); 771*be771a7bSCy Schubert daemon->use_response_ip = !respip_set_is_empty( 772*be771a7bSCy Schubert daemon->env->respip_set) || have_view_respip_cfg; 77365b390aaSDag-Erling Smørgrav 7745469a995SCy Schubert /* setup modules */ 7755469a995SCy Schubert daemon_setup_modules(daemon); 7765469a995SCy Schubert 77757bddd21SDag-Erling Smørgrav /* read auth zonefiles */ 778091e9e46SCy Schubert if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1, 7795469a995SCy Schubert &daemon->use_rpz, daemon->env, &daemon->mods)) 78057bddd21SDag-Erling Smørgrav fatal_exit("auth_zones could not be setup"); 78157bddd21SDag-Erling Smørgrav 782369c6923SCy Schubert /* Set-up EDNS strings */ 783369c6923SCy Schubert if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg)) 784369c6923SCy Schubert fatal_exit("Could not set up EDNS strings"); 785c0caa2e2SCy Schubert 786335c7cdaSCy Schubert #ifdef USE_CACHEDB 787335c7cdaSCy Schubert daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods, 788335c7cdaSCy Schubert daemon->env); 789335c7cdaSCy Schubert #endif 79065b390aaSDag-Erling Smørgrav /* response-ip-xxx options don't work as expected without the respip 79165b390aaSDag-Erling Smørgrav * module. To avoid run-time operational surprise we reject such 79265b390aaSDag-Erling Smørgrav * configuration. */ 79365b390aaSDag-Erling Smørgrav if(daemon->use_response_ip && 79465b390aaSDag-Erling Smørgrav modstack_find(&daemon->mods, "respip") < 0) 79565b390aaSDag-Erling Smørgrav fatal_exit("response-ip options require respip module"); 796091e9e46SCy Schubert /* RPZ response ip triggers don't work as expected without the respip 797091e9e46SCy Schubert * module. To avoid run-time operational surprise we reject such 798091e9e46SCy Schubert * configuration. */ 799091e9e46SCy Schubert if(daemon->use_rpz && 800091e9e46SCy Schubert modstack_find(&daemon->mods, "respip") < 0) 801091e9e46SCy Schubert fatal_exit("RPZ requires the respip module"); 80265b390aaSDag-Erling Smørgrav 803b7579f77SDag-Erling Smørgrav /* first create all the worker structures, so we can pass 804b7579f77SDag-Erling Smørgrav * them to the newly created threads. 805b7579f77SDag-Erling Smørgrav */ 806b7579f77SDag-Erling Smørgrav daemon_create_workers(daemon); 807b7579f77SDag-Erling Smørgrav 808b7579f77SDag-Erling Smørgrav #if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) 809b7579f77SDag-Erling Smørgrav /* in libev the first inited base gets signals */ 81017d15b25SDag-Erling Smørgrav if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) 811b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize main thread"); 812b7579f77SDag-Erling Smørgrav #endif 813b7579f77SDag-Erling Smørgrav 814b7579f77SDag-Erling Smørgrav /* Now create the threads and init the workers. 815b7579f77SDag-Erling Smørgrav * By the way, this is thread #0 (the main thread). 816b7579f77SDag-Erling Smørgrav */ 817b7579f77SDag-Erling Smørgrav daemon_start_others(daemon); 818b7579f77SDag-Erling Smørgrav 819b7579f77SDag-Erling Smørgrav /* Special handling for the main thread. This is the thread 820b7579f77SDag-Erling Smørgrav * that handles signals and remote control. 821b7579f77SDag-Erling Smørgrav */ 822b7579f77SDag-Erling Smørgrav #if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) 823b7579f77SDag-Erling Smørgrav /* libevent has the last inited base get signals (or any base) */ 82417d15b25SDag-Erling Smørgrav if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) 825b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize main thread"); 826b7579f77SDag-Erling Smørgrav #endif 827b7579f77SDag-Erling Smørgrav signal_handling_playback(daemon->workers[0]); 828b7579f77SDag-Erling Smørgrav 82965b390aaSDag-Erling Smørgrav if (!shm_main_init(daemon)) 83065b390aaSDag-Erling Smørgrav log_warn("SHM has failed"); 83165b390aaSDag-Erling Smørgrav 832b7579f77SDag-Erling Smørgrav /* Start resolver service on main thread. */ 8333005e0a3SDag-Erling Smørgrav #ifdef HAVE_SYSTEMD 8340eefd307SCy Schubert ret = sd_notify(0, "READY=1"); 8350eefd307SCy Schubert if(ret <= 0 && getenv("NOTIFY_SOCKET")) 8360eefd307SCy Schubert fatal_exit("sd_notify failed %s: %s. Make sure that unbound has " 8370eefd307SCy Schubert "access/permission to use the socket presented by systemd.", 8380eefd307SCy Schubert getenv("NOTIFY_SOCKET"), 8390eefd307SCy Schubert (ret==0?"no $NOTIFY_SOCKET": strerror(-ret))); 8403005e0a3SDag-Erling Smørgrav #endif 841b7579f77SDag-Erling Smørgrav log_info("start of service (%s).", PACKAGE_STRING); 842b7579f77SDag-Erling Smørgrav worker_work(daemon->workers[0]); 8433005e0a3SDag-Erling Smørgrav #ifdef HAVE_SYSTEMD 8444c75e3aaSDag-Erling Smørgrav if (daemon->workers[0]->need_to_exit) 8453005e0a3SDag-Erling Smørgrav sd_notify(0, "STOPPING=1"); 8464c75e3aaSDag-Erling Smørgrav else 8474c75e3aaSDag-Erling Smørgrav sd_notify(0, "RELOADING=1"); 8483005e0a3SDag-Erling Smørgrav #endif 849b7579f77SDag-Erling Smørgrav log_info("service stopped (%s).", PACKAGE_STRING); 850b7579f77SDag-Erling Smørgrav 851b7579f77SDag-Erling Smørgrav /* we exited! a signal happened! Stop other threads */ 852b7579f77SDag-Erling Smørgrav daemon_stop_others(daemon); 853b7579f77SDag-Erling Smørgrav 85465b390aaSDag-Erling Smørgrav /* Shutdown SHM */ 85565b390aaSDag-Erling Smørgrav shm_main_shutdown(daemon); 85665b390aaSDag-Erling Smørgrav 8571838dec3SCy Schubert daemon->reuse_cache = daemon->workers[0]->reuse_cache; 858b7579f77SDag-Erling Smørgrav daemon->need_to_exit = daemon->workers[0]->need_to_exit; 859b7579f77SDag-Erling Smørgrav } 860b7579f77SDag-Erling Smørgrav 861b7579f77SDag-Erling Smørgrav void 862b7579f77SDag-Erling Smørgrav daemon_cleanup(struct daemon* daemon) 863b7579f77SDag-Erling Smørgrav { 864b7579f77SDag-Erling Smørgrav int i; 865b7579f77SDag-Erling Smørgrav log_assert(daemon); 866b7579f77SDag-Erling Smørgrav /* before stopping main worker, handle signals ourselves, so we 867b7579f77SDag-Erling Smørgrav don't die on multiple reload signals for example. */ 868b7579f77SDag-Erling Smørgrav signal_handling_record(); 869b7579f77SDag-Erling Smørgrav log_thread_set(NULL); 870b7579f77SDag-Erling Smørgrav /* clean up caches because 871b7579f77SDag-Erling Smørgrav * a) RRset IDs will be recycled after a reload, causing collisions 8721838dec3SCy Schubert * b) validation config can change, thus rrset, msg, keycache clear 8731838dec3SCy Schubert * 8741838dec3SCy Schubert * If we are trying to keep the cache as long as possible, we should 8751838dec3SCy Schubert * defer the cleanup until we know whether the new configuration allows 8761838dec3SCy Schubert * the reuse. (If we're exiting, cleanup should be done here). */ 8771838dec3SCy Schubert if(!daemon->reuse_cache || daemon->need_to_exit) { 878b7579f77SDag-Erling Smørgrav slabhash_clear(&daemon->env->rrset_cache->table); 879b7579f77SDag-Erling Smørgrav slabhash_clear(daemon->env->msg_cache); 8801838dec3SCy Schubert } 8811838dec3SCy Schubert daemon->old_num = daemon->num; /* save the current num */ 882335c7cdaSCy Schubert forwards_delete(daemon->env->fwds); 883335c7cdaSCy Schubert daemon->env->fwds = NULL; 884335c7cdaSCy Schubert hints_delete(daemon->env->hints); 885335c7cdaSCy Schubert daemon->env->hints = NULL; 886b7579f77SDag-Erling Smørgrav local_zones_delete(daemon->local_zones); 887b7579f77SDag-Erling Smørgrav daemon->local_zones = NULL; 888*be771a7bSCy Schubert respip_set_delete(daemon->env->respip_set); 889*be771a7bSCy Schubert daemon->env->respip_set = NULL; 890*be771a7bSCy Schubert views_delete(daemon->env->views); 891*be771a7bSCy Schubert daemon->env->views = NULL; 89257bddd21SDag-Erling Smørgrav if(daemon->env->auth_zones) 89357bddd21SDag-Erling Smørgrav auth_zones_cleanup(daemon->env->auth_zones); 89456850988SCy Schubert /* key cache is cleared by module deinit during next daemon_fork() */ 895b7579f77SDag-Erling Smørgrav daemon_remote_clear(daemon->rc); 896*be771a7bSCy Schubert if(daemon->fast_reload_thread) 897*be771a7bSCy Schubert fast_reload_thread_stop(daemon->fast_reload_thread); 898*be771a7bSCy Schubert if(daemon->fast_reload_printq_list) 899*be771a7bSCy Schubert fast_reload_printq_list_delete(daemon->fast_reload_printq_list); 900b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) 901b7579f77SDag-Erling Smørgrav worker_delete(daemon->workers[i]); 902b7579f77SDag-Erling Smørgrav free(daemon->workers); 903b7579f77SDag-Erling Smørgrav daemon->workers = NULL; 9041838dec3SCy Schubert /* Unless we're trying to keep the cache, worker alloc_caches should be 9051838dec3SCy Schubert * cleared and freed here. We do this after deleting workers to 9061838dec3SCy Schubert * guarantee that the alloc caches are valid throughout the lifetime 9071838dec3SCy Schubert * of workers. */ 9081838dec3SCy Schubert if(!daemon->reuse_cache || daemon->need_to_exit) 9091838dec3SCy Schubert daemon_clear_allocs(daemon); 910b7579f77SDag-Erling Smørgrav daemon->num = 0; 911ff825849SDag-Erling Smørgrav #ifdef USE_DNSTAP 912ff825849SDag-Erling Smørgrav dt_delete(daemon->dtenv); 9130fb34990SDag-Erling Smørgrav daemon->dtenv = NULL; 914ff825849SDag-Erling Smørgrav #endif 915971980c3SDag-Erling Smørgrav #ifdef USE_DNSCRYPT 916971980c3SDag-Erling Smørgrav dnsc_delete(daemon->dnscenv); 9170fb34990SDag-Erling Smørgrav daemon->dnscenv = NULL; 918971980c3SDag-Erling Smørgrav #endif 91946d2f618SCy Schubert #ifdef HAVE_NGTCP2 92046d2f618SCy Schubert doq_table_delete(daemon->doq_table); 92146d2f618SCy Schubert daemon->doq_table = NULL; 92246d2f618SCy Schubert #endif 923b7579f77SDag-Erling Smørgrav daemon->cfg = NULL; 924b7579f77SDag-Erling Smørgrav } 925b7579f77SDag-Erling Smørgrav 926b7579f77SDag-Erling Smørgrav void 927b7579f77SDag-Erling Smørgrav daemon_delete(struct daemon* daemon) 928b7579f77SDag-Erling Smørgrav { 92917d15b25SDag-Erling Smørgrav size_t i; 930b7579f77SDag-Erling Smørgrav if(!daemon) 931b7579f77SDag-Erling Smørgrav return; 93256850988SCy Schubert modstack_call_deinit(&daemon->mods, daemon->env); 93356850988SCy Schubert modstack_call_destartup(&daemon->mods, daemon->env); 93456850988SCy Schubert modstack_free(&daemon->mods); 935b7579f77SDag-Erling Smørgrav daemon_remote_delete(daemon->rc); 93617d15b25SDag-Erling Smørgrav for(i = 0; i < daemon->num_ports; i++) 93717d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 93817d15b25SDag-Erling Smørgrav free(daemon->ports); 939b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 940b7579f77SDag-Erling Smørgrav if(daemon->env) { 941b7579f77SDag-Erling Smørgrav slabhash_delete(daemon->env->msg_cache); 942b7579f77SDag-Erling Smørgrav rrset_cache_delete(daemon->env->rrset_cache); 943b7579f77SDag-Erling Smørgrav infra_delete(daemon->env->infra_cache); 944bc892140SDag-Erling Smørgrav edns_known_options_delete(daemon->env); 945369c6923SCy Schubert edns_strings_delete(daemon->env->edns_strings); 94657bddd21SDag-Erling Smørgrav auth_zones_delete(daemon->env->auth_zones); 947b7579f77SDag-Erling Smørgrav } 948b7579f77SDag-Erling Smørgrav ub_randfree(daemon->rand); 949b7579f77SDag-Erling Smørgrav alloc_clear(&daemon->superalloc); 950b7579f77SDag-Erling Smørgrav acl_list_delete(daemon->acl); 951865f46b2SCy Schubert acl_list_delete(daemon->acl_interface); 9524c75e3aaSDag-Erling Smørgrav tcl_list_delete(daemon->tcl); 95356850988SCy Schubert cookie_secrets_delete(daemon->cookie_secrets); 95424e36522SCy Schubert listen_desetup_locks(); 955b7579f77SDag-Erling Smørgrav free(daemon->chroot); 956b7579f77SDag-Erling Smørgrav free(daemon->pidfile); 957*be771a7bSCy Schubert free(daemon->cfgfile); 958b7579f77SDag-Erling Smørgrav free(daemon->env); 9598ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 960e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(); 961*be771a7bSCy Schubert SSL_CTX_free((SSL_CTX*)daemon->listen_dot_sslctx); 962*be771a7bSCy Schubert SSL_CTX_free((SSL_CTX*)daemon->listen_doh_sslctx); 963*be771a7bSCy Schubert SSL_CTX_free((SSL_CTX*)daemon->connect_dot_sslctx); 964*be771a7bSCy Schubert #endif 965*be771a7bSCy Schubert #ifdef HAVE_NGTCP2 966*be771a7bSCy Schubert SSL_CTX_free((SSL_CTX*)daemon->listen_quic_sslctx); 9678ed2b524SDag-Erling Smørgrav #endif 968b7579f77SDag-Erling Smørgrav free(daemon); 969b7579f77SDag-Erling Smørgrav /* lex cleanup */ 970b7579f77SDag-Erling Smørgrav ub_c_lex_destroy(); 971b7579f77SDag-Erling Smørgrav /* libcrypto cleanup */ 9728ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 9730a92a9fcSCy Schubert # if defined(USE_GOST) 97417d15b25SDag-Erling Smørgrav sldns_key_EVP_unload_gost(); 975b7579f77SDag-Erling Smørgrav # endif 976b7579f77SDag-Erling Smørgrav # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE 977b7579f77SDag-Erling Smørgrav # ifndef S_SPLINT_S 978e2d15004SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 979b7579f77SDag-Erling Smørgrav sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); 980b7579f77SDag-Erling Smørgrav # endif 981b7579f77SDag-Erling Smørgrav # endif 982e2d15004SDag-Erling Smørgrav # endif 983b7579f77SDag-Erling Smørgrav # ifdef HAVE_OPENSSL_CONFIG 984b7579f77SDag-Erling Smørgrav EVP_cleanup(); 98525039b37SCy Schubert # if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE) && defined(HAVE_ENGINE_CLEANUP) 986b7579f77SDag-Erling Smørgrav ENGINE_cleanup(); 987e2d15004SDag-Erling Smørgrav # endif 988b7579f77SDag-Erling Smørgrav CONF_modules_free(); 989b7579f77SDag-Erling Smørgrav # endif 990b5663de9SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 991b7579f77SDag-Erling Smørgrav CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ 992b5663de9SDag-Erling Smørgrav # endif 993b5663de9SDag-Erling Smørgrav # ifdef HAVE_ERR_FREE_STRINGS 994b7579f77SDag-Erling Smørgrav ERR_free_strings(); 995b5663de9SDag-Erling Smørgrav # endif 996e2d15004SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 997b7579f77SDag-Erling Smørgrav RAND_cleanup(); 998e2d15004SDag-Erling Smørgrav # endif 9998ed2b524SDag-Erling Smørgrav # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 10008ed2b524SDag-Erling Smørgrav ub_openssl_lock_delete(); 10018ed2b524SDag-Erling Smørgrav # endif 100257bddd21SDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM 100357bddd21SDag-Erling Smørgrav _ARC4_LOCK_DESTROY(); 100457bddd21SDag-Erling Smørgrav #endif 10058ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 10068ed2b524SDag-Erling Smørgrav NSS_Shutdown(); 10078ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS */ 1008b7579f77SDag-Erling Smørgrav checklock_stop(); 1009b7579f77SDag-Erling Smørgrav #ifdef USE_WINSOCK 1010b7579f77SDag-Erling Smørgrav if(WSACleanup() != 0) { 1011b7579f77SDag-Erling Smørgrav log_err("Could not WSACleanup: %s", 1012b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 1013b7579f77SDag-Erling Smørgrav } 1014b7579f77SDag-Erling Smørgrav #endif 1015b7579f77SDag-Erling Smørgrav } 1016b7579f77SDag-Erling Smørgrav 1017b7579f77SDag-Erling Smørgrav void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg) 1018b7579f77SDag-Erling Smørgrav { 10191838dec3SCy Schubert int new_num = cfg->num_threads?cfg->num_threads:1; 10201838dec3SCy Schubert 1021b7579f77SDag-Erling Smørgrav daemon->cfg = cfg; 1022b7579f77SDag-Erling Smørgrav config_apply(cfg); 10231838dec3SCy Schubert 10241838dec3SCy Schubert /* If this is a reload and we deferred the decision on whether to 10251838dec3SCy Schubert * reuse the alloc, RRset, and message caches, then check to see if 10261838dec3SCy Schubert * it's safe to keep the caches: 10271838dec3SCy Schubert * - changing the number of threads is obviously incompatible with 10281838dec3SCy Schubert * keeping the per-thread alloc caches. It also means we have to 10291838dec3SCy Schubert * clear RRset and message caches. (note that 'new_num' may be 10301838dec3SCy Schubert * adjusted in daemon_create_workers, but for our purpose we can 10311838dec3SCy Schubert * simply compare it with 'old_num'; if they are equal here, 10321838dec3SCy Schubert * 'new_num' won't be adjusted to a different value than 'old_num'). 10331838dec3SCy Schubert * - changing RRset cache size effectively clears any remaining cache 10341838dec3SCy Schubert * entries. We could keep their keys in alloc caches, but it would 10351838dec3SCy Schubert * be more consistent with the sense of the change to clear allocs 10361838dec3SCy Schubert * and free memory. To do so we also have to clear message cache. 10371838dec3SCy Schubert * - only changing message cache size does not necessarily affect 10381838dec3SCy Schubert * RRset or alloc cache. But almost all new subsequent queries will 10391838dec3SCy Schubert * require recursive resolution anyway, so it doesn't help much to 10401838dec3SCy Schubert * just keep RRset and alloc caches. For simplicity we clear/free 10411838dec3SCy Schubert * the other two, too. */ 10421838dec3SCy Schubert if(daemon->worker_allocs && 10431838dec3SCy Schubert (new_num != daemon->old_num || 10441838dec3SCy Schubert !slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, 10451838dec3SCy Schubert cfg->msg_cache_slabs) || 10461838dec3SCy Schubert !slabhash_is_size(&daemon->env->rrset_cache->table, 10471838dec3SCy Schubert cfg->rrset_cache_size, cfg->rrset_cache_slabs))) 10481838dec3SCy Schubert { 10491838dec3SCy Schubert log_warn("cannot reuse caches due to critical config change"); 10501838dec3SCy Schubert slabhash_clear(&daemon->env->rrset_cache->table); 10511838dec3SCy Schubert slabhash_clear(daemon->env->msg_cache); 10521838dec3SCy Schubert daemon_clear_allocs(daemon); 10531838dec3SCy Schubert } 10541838dec3SCy Schubert 10554c75e3aaSDag-Erling Smørgrav if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, 10564c75e3aaSDag-Erling Smørgrav cfg->msg_cache_slabs)) { 1057b7579f77SDag-Erling Smørgrav slabhash_delete(daemon->env->msg_cache); 1058b7579f77SDag-Erling Smørgrav daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, 1059b7579f77SDag-Erling Smørgrav HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, 1060b7579f77SDag-Erling Smørgrav msgreply_sizefunc, query_info_compare, 1061b7579f77SDag-Erling Smørgrav query_entry_delete, reply_info_delete, NULL); 1062b7579f77SDag-Erling Smørgrav if(!daemon->env->msg_cache) { 1063b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1064b7579f77SDag-Erling Smørgrav } 1065b7579f77SDag-Erling Smørgrav } 1066b7579f77SDag-Erling Smørgrav if((daemon->env->rrset_cache = rrset_cache_adjust( 1067b7579f77SDag-Erling Smørgrav daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0) 1068b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1069b7579f77SDag-Erling Smørgrav if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache, 1070b7579f77SDag-Erling Smørgrav cfg))==0) 1071b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1072b7579f77SDag-Erling Smørgrav } 1073