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 326865f46b2SCy Schubert static int setup_acl_for_ports(struct acl_list* list, 327865f46b2SCy Schubert struct listen_port* port_list) 328865f46b2SCy Schubert { 329865f46b2SCy Schubert struct acl_addr* acl_node; 330865f46b2SCy Schubert for(; port_list; port_list=port_list->next) { 331865f46b2SCy Schubert if(!port_list->socket) { 332865f46b2SCy Schubert /* This is mainly for testbound where port_list is 333865f46b2SCy Schubert * empty. */ 334865f46b2SCy Schubert continue; 335865f46b2SCy Schubert } 336865f46b2SCy Schubert if(!(acl_node = acl_interface_insert(list, 337335c7cdaSCy Schubert (struct sockaddr_storage*)port_list->socket->addr, 338335c7cdaSCy Schubert port_list->socket->addrlen, 339865f46b2SCy Schubert acl_refuse))) { 340865f46b2SCy Schubert return 0; 341865f46b2SCy Schubert } 342865f46b2SCy Schubert port_list->socket->acl = acl_node; 343865f46b2SCy Schubert } 344865f46b2SCy Schubert return 1; 345865f46b2SCy Schubert } 346865f46b2SCy Schubert 347b7579f77SDag-Erling Smørgrav int 348b7579f77SDag-Erling Smørgrav daemon_open_shared_ports(struct daemon* daemon) 349b7579f77SDag-Erling Smørgrav { 350b7579f77SDag-Erling Smørgrav log_assert(daemon); 351b7579f77SDag-Erling Smørgrav if(daemon->cfg->port != daemon->listening_port) { 352c0caa2e2SCy Schubert char** resif = NULL; 353c0caa2e2SCy Schubert int num_resif = 0; 35417d15b25SDag-Erling Smørgrav size_t i; 35517d15b25SDag-Erling Smørgrav struct listen_port* p0; 356ff825849SDag-Erling Smørgrav daemon->reuseport = 0; 35717d15b25SDag-Erling Smørgrav /* free and close old ports */ 35817d15b25SDag-Erling Smørgrav if(daemon->ports != NULL) { 35917d15b25SDag-Erling Smørgrav for(i=0; i<daemon->num_ports; i++) 36017d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 36117d15b25SDag-Erling Smørgrav free(daemon->ports); 36217d15b25SDag-Erling Smørgrav daemon->ports = NULL; 36317d15b25SDag-Erling Smørgrav } 364865f46b2SCy Schubert /* clean acl_interface */ 365865f46b2SCy Schubert acl_interface_init(daemon->acl_interface); 3665469a995SCy Schubert if(!resolve_interface_names(daemon->cfg->ifs, 3675469a995SCy Schubert daemon->cfg->num_ifs, NULL, &resif, &num_resif)) 368c0caa2e2SCy Schubert return 0; 36917d15b25SDag-Erling Smørgrav /* see if we want to reuseport */ 370ff825849SDag-Erling Smørgrav #ifdef SO_REUSEPORT 37117d15b25SDag-Erling Smørgrav if(daemon->cfg->so_reuseport && daemon->cfg->num_threads > 0) 372ff825849SDag-Erling Smørgrav daemon->reuseport = 1; 37317d15b25SDag-Erling Smørgrav #endif 37417d15b25SDag-Erling Smørgrav /* try to use reuseport */ 375865f46b2SCy Schubert p0 = listening_ports_open(daemon->cfg, resif, num_resif, 376865f46b2SCy Schubert &daemon->reuseport); 37717d15b25SDag-Erling Smørgrav if(!p0) { 37817d15b25SDag-Erling Smørgrav listening_ports_free(p0); 379c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 380b7579f77SDag-Erling Smørgrav return 0; 38117d15b25SDag-Erling Smørgrav } 382ff825849SDag-Erling Smørgrav if(daemon->reuseport) { 38317d15b25SDag-Erling Smørgrav /* reuseport was successful, allocate for it */ 38417d15b25SDag-Erling Smørgrav daemon->num_ports = (size_t)daemon->cfg->num_threads; 38517d15b25SDag-Erling Smørgrav } else { 38617d15b25SDag-Erling Smørgrav /* do the normal, singleportslist thing, 38717d15b25SDag-Erling Smørgrav * reuseport not enabled or did not work */ 38817d15b25SDag-Erling Smørgrav daemon->num_ports = 1; 38917d15b25SDag-Erling Smørgrav } 39017d15b25SDag-Erling Smørgrav if(!(daemon->ports = (struct listen_port**)calloc( 39117d15b25SDag-Erling Smørgrav daemon->num_ports, sizeof(*daemon->ports)))) { 39217d15b25SDag-Erling Smørgrav listening_ports_free(p0); 393c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 39417d15b25SDag-Erling Smørgrav return 0; 39517d15b25SDag-Erling Smørgrav } 39617d15b25SDag-Erling Smørgrav daemon->ports[0] = p0; 397865f46b2SCy Schubert if(!setup_acl_for_ports(daemon->acl_interface, 398865f46b2SCy Schubert daemon->ports[0])) { 399865f46b2SCy Schubert listening_ports_free(p0); 400865f46b2SCy Schubert config_del_strarray(resif, num_resif); 401865f46b2SCy Schubert return 0; 402865f46b2SCy Schubert } 403ff825849SDag-Erling Smørgrav if(daemon->reuseport) { 40417d15b25SDag-Erling Smørgrav /* continue to use reuseport */ 40517d15b25SDag-Erling Smørgrav for(i=1; i<daemon->num_ports; i++) { 40617d15b25SDag-Erling Smørgrav if(!(daemon->ports[i]= 40717d15b25SDag-Erling Smørgrav listening_ports_open(daemon->cfg, 408c0caa2e2SCy Schubert resif, num_resif, 409ff825849SDag-Erling Smørgrav &daemon->reuseport)) 410ff825849SDag-Erling Smørgrav || !daemon->reuseport ) { 41117d15b25SDag-Erling Smørgrav for(i=0; i<daemon->num_ports; i++) 41217d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 41317d15b25SDag-Erling Smørgrav free(daemon->ports); 41417d15b25SDag-Erling Smørgrav daemon->ports = NULL; 415c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 41617d15b25SDag-Erling Smørgrav return 0; 41717d15b25SDag-Erling Smørgrav } 418865f46b2SCy Schubert if(!setup_acl_for_ports(daemon->acl_interface, 419865f46b2SCy Schubert daemon->ports[i])) { 420865f46b2SCy Schubert for(i=0; i<daemon->num_ports; i++) 421865f46b2SCy Schubert listening_ports_free(daemon->ports[i]); 422865f46b2SCy Schubert free(daemon->ports); 423865f46b2SCy Schubert daemon->ports = NULL; 424865f46b2SCy Schubert config_del_strarray(resif, num_resif); 425865f46b2SCy Schubert return 0; 426865f46b2SCy Schubert } 42717d15b25SDag-Erling Smørgrav } 42817d15b25SDag-Erling Smørgrav } 429c0caa2e2SCy Schubert config_del_strarray(resif, num_resif); 430b7579f77SDag-Erling Smørgrav daemon->listening_port = daemon->cfg->port; 431b7579f77SDag-Erling Smørgrav } 432b7579f77SDag-Erling Smørgrav if(!daemon->cfg->remote_control_enable && daemon->rc_port) { 433b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 434b7579f77SDag-Erling Smørgrav daemon->rc_ports = NULL; 435b7579f77SDag-Erling Smørgrav daemon->rc_port = 0; 436b7579f77SDag-Erling Smørgrav } 437b7579f77SDag-Erling Smørgrav if(daemon->cfg->remote_control_enable && 438b7579f77SDag-Erling Smørgrav daemon->cfg->control_port != daemon->rc_port) { 439b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 440b7579f77SDag-Erling Smørgrav if(!(daemon->rc_ports=daemon_remote_open_ports(daemon->cfg))) 441b7579f77SDag-Erling Smørgrav return 0; 442b7579f77SDag-Erling Smørgrav daemon->rc_port = daemon->cfg->control_port; 443b7579f77SDag-Erling Smørgrav } 444b7579f77SDag-Erling Smørgrav return 1; 445b7579f77SDag-Erling Smørgrav } 446b7579f77SDag-Erling Smørgrav 44756850988SCy Schubert int 44856850988SCy Schubert daemon_privileged(struct daemon* daemon) 44956850988SCy Schubert { 45056850988SCy Schubert daemon->env->cfg = daemon->cfg; 45156850988SCy Schubert daemon->env->alloc = &daemon->superalloc; 45256850988SCy Schubert daemon->env->worker = NULL; 45356850988SCy Schubert if(!modstack_call_startup(&daemon->mods, daemon->cfg->module_conf, 45456850988SCy Schubert daemon->env)) { 45556850988SCy Schubert fatal_exit("failed to startup modules"); 45656850988SCy Schubert } 45756850988SCy Schubert return 1; 45856850988SCy Schubert } 45956850988SCy Schubert 460b7579f77SDag-Erling Smørgrav /** 461b7579f77SDag-Erling Smørgrav * Setup modules. setup module stack. 462b7579f77SDag-Erling Smørgrav * @param daemon: the daemon 463b7579f77SDag-Erling Smørgrav */ 464b7579f77SDag-Erling Smørgrav static void daemon_setup_modules(struct daemon* daemon) 465b7579f77SDag-Erling Smørgrav { 466b7579f77SDag-Erling Smørgrav daemon->env->cfg = daemon->cfg; 467b7579f77SDag-Erling Smørgrav daemon->env->alloc = &daemon->superalloc; 468b7579f77SDag-Erling Smørgrav daemon->env->worker = NULL; 46956850988SCy Schubert if(daemon->mods_inited) { 47056850988SCy Schubert modstack_call_deinit(&daemon->mods, daemon->env); 471b7579f77SDag-Erling Smørgrav } 47256850988SCy Schubert daemon->env->need_to_validate = 0; /* set by module init below */ 47356850988SCy Schubert if(!modstack_call_init(&daemon->mods, daemon->cfg->module_conf, 47456850988SCy Schubert daemon->env)) { 47556850988SCy Schubert fatal_exit("failed to init modules"); 47656850988SCy Schubert } 47756850988SCy Schubert daemon->mods_inited = 1; 478bc892140SDag-Erling Smørgrav log_edns_known_options(VERB_ALGO, daemon->env); 479b7579f77SDag-Erling Smørgrav } 480b7579f77SDag-Erling Smørgrav 481b7579f77SDag-Erling Smørgrav /** 482b7579f77SDag-Erling Smørgrav * Obtain allowed port numbers, concatenate the list, and shuffle them 483b7579f77SDag-Erling Smørgrav * (ready to be handed out to threads). 484b7579f77SDag-Erling Smørgrav * @param daemon: the daemon. Uses rand and cfg. 485b7579f77SDag-Erling Smørgrav * @param shufport: the portlist output. 486b7579f77SDag-Erling Smørgrav * @return number of ports available. 487b7579f77SDag-Erling Smørgrav */ 488b7579f77SDag-Erling Smørgrav static int daemon_get_shufport(struct daemon* daemon, int* shufport) 489b7579f77SDag-Erling Smørgrav { 490b7579f77SDag-Erling Smørgrav int i, n, k, temp; 491b7579f77SDag-Erling Smørgrav int avail = 0; 492b7579f77SDag-Erling Smørgrav for(i=0; i<65536; i++) { 493b7579f77SDag-Erling Smørgrav if(daemon->cfg->outgoing_avail_ports[i]) { 494b7579f77SDag-Erling Smørgrav shufport[avail++] = daemon->cfg-> 495b7579f77SDag-Erling Smørgrav outgoing_avail_ports[i]; 496b7579f77SDag-Erling Smørgrav } 497b7579f77SDag-Erling Smørgrav } 498b7579f77SDag-Erling Smørgrav if(avail == 0) 499b7579f77SDag-Erling Smørgrav fatal_exit("no ports are permitted for UDP, add " 500b7579f77SDag-Erling Smørgrav "with outgoing-port-permit"); 501b7579f77SDag-Erling Smørgrav /* Knuth shuffle */ 502b7579f77SDag-Erling Smørgrav n = avail; 503b7579f77SDag-Erling Smørgrav while(--n > 0) { 504b7579f77SDag-Erling Smørgrav k = ub_random_max(daemon->rand, n+1); /* 0<= k<= n */ 505b7579f77SDag-Erling Smørgrav temp = shufport[k]; 506b7579f77SDag-Erling Smørgrav shufport[k] = shufport[n]; 507b7579f77SDag-Erling Smørgrav shufport[n] = temp; 508b7579f77SDag-Erling Smørgrav } 509b7579f77SDag-Erling Smørgrav return avail; 510b7579f77SDag-Erling Smørgrav } 511b7579f77SDag-Erling Smørgrav 512b7579f77SDag-Erling Smørgrav /** 5131838dec3SCy Schubert * Clear and delete per-worker alloc caches, and free memory maintained in 5141838dec3SCy Schubert * superalloc. 5151838dec3SCy Schubert * The rrset and message caches must be empty at the time of call. 5161838dec3SCy Schubert * @param daemon: the daemon that maintains the alloc caches to be cleared. 5171838dec3SCy Schubert */ 5181838dec3SCy Schubert static void 5191838dec3SCy Schubert daemon_clear_allocs(struct daemon* daemon) 5201838dec3SCy Schubert { 5211838dec3SCy Schubert int i; 5221838dec3SCy Schubert 52356850988SCy Schubert /* daemon->num may be different during reloads (after configuration 52456850988SCy Schubert * read). Use old_num which has the correct value used to setup the 52556850988SCy Schubert * worker_allocs */ 52656850988SCy Schubert for(i=0; i<daemon->old_num; i++) { 5271838dec3SCy Schubert alloc_clear(daemon->worker_allocs[i]); 5281838dec3SCy Schubert free(daemon->worker_allocs[i]); 5291838dec3SCy Schubert } 5301838dec3SCy Schubert free(daemon->worker_allocs); 5311838dec3SCy Schubert daemon->worker_allocs = NULL; 5321838dec3SCy Schubert 5331838dec3SCy Schubert alloc_clear_special(&daemon->superalloc); 5341838dec3SCy Schubert } 5351838dec3SCy Schubert 5361838dec3SCy Schubert /** 537b7579f77SDag-Erling Smørgrav * Allocate empty worker structures. With backptr and thread-number, 538b7579f77SDag-Erling Smørgrav * from 0..numthread initialised. Used as user arguments to new threads. 539b7579f77SDag-Erling Smørgrav * Creates the daemon random generator if it does not exist yet. 540b7579f77SDag-Erling Smørgrav * The random generator stays existing between reloads with a unique state. 541b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with (new) config settings. 542b7579f77SDag-Erling Smørgrav */ 543b7579f77SDag-Erling Smørgrav static void 544b7579f77SDag-Erling Smørgrav daemon_create_workers(struct daemon* daemon) 545b7579f77SDag-Erling Smørgrav { 546b7579f77SDag-Erling Smørgrav int i, numport; 547b7579f77SDag-Erling Smørgrav int* shufport; 548b7579f77SDag-Erling Smørgrav log_assert(daemon && daemon->cfg); 549b7579f77SDag-Erling Smørgrav if(!daemon->rand) { 5500eefd307SCy Schubert daemon->rand = ub_initstate(NULL); 551b7579f77SDag-Erling Smørgrav if(!daemon->rand) 552b7579f77SDag-Erling Smørgrav fatal_exit("could not init random generator"); 553b7579f77SDag-Erling Smørgrav hash_set_raninit((uint32_t)ub_random(daemon->rand)); 554971980c3SDag-Erling Smørgrav } 555b7579f77SDag-Erling Smørgrav shufport = (int*)calloc(65536, sizeof(int)); 556b7579f77SDag-Erling Smørgrav if(!shufport) 557b7579f77SDag-Erling Smørgrav fatal_exit("out of memory during daemon init"); 558b7579f77SDag-Erling Smørgrav numport = daemon_get_shufport(daemon, shufport); 559b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "total of %d outgoing ports available", numport); 560b7579f77SDag-Erling Smørgrav 561*46d2f618SCy Schubert #ifdef HAVE_NGTCP2 562*46d2f618SCy Schubert daemon->doq_table = doq_table_create(daemon->cfg, daemon->rand); 563*46d2f618SCy Schubert if(!daemon->doq_table) 564*46d2f618SCy Schubert fatal_exit("could not create doq_table: out of memory"); 565*46d2f618SCy Schubert #endif 566*46d2f618SCy Schubert 567b7579f77SDag-Erling Smørgrav daemon->num = (daemon->cfg->num_threads?daemon->cfg->num_threads:1); 568b75612f8SDag-Erling Smørgrav if(daemon->reuseport && (int)daemon->num < (int)daemon->num_ports) { 569b75612f8SDag-Erling Smørgrav log_warn("cannot reduce num-threads to %d because so-reuseport " 570b75612f8SDag-Erling Smørgrav "so continuing with %d threads.", (int)daemon->num, 571b75612f8SDag-Erling Smørgrav (int)daemon->num_ports); 572b75612f8SDag-Erling Smørgrav daemon->num = (int)daemon->num_ports; 573b75612f8SDag-Erling Smørgrav } 574b7579f77SDag-Erling Smørgrav daemon->workers = (struct worker**)calloc((size_t)daemon->num, 575b7579f77SDag-Erling Smørgrav sizeof(struct worker*)); 576b5663de9SDag-Erling Smørgrav if(!daemon->workers) 577b5663de9SDag-Erling Smørgrav fatal_exit("out of memory during daemon init"); 578ff825849SDag-Erling Smørgrav if(daemon->cfg->dnstap) { 579ff825849SDag-Erling Smørgrav #ifdef USE_DNSTAP 58025039b37SCy Schubert daemon->dtenv = dt_create(daemon->cfg); 581ff825849SDag-Erling Smørgrav if (!daemon->dtenv) 582ff825849SDag-Erling Smørgrav fatal_exit("dt_create failed"); 583ff825849SDag-Erling Smørgrav #else 584ff825849SDag-Erling Smørgrav fatal_exit("dnstap enabled in config but not built with dnstap support"); 585ff825849SDag-Erling Smørgrav #endif 586ff825849SDag-Erling Smørgrav } 587b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) { 588b7579f77SDag-Erling Smørgrav if(!(daemon->workers[i] = worker_create(daemon, i, 589b7579f77SDag-Erling Smørgrav shufport+numport*i/daemon->num, 590b7579f77SDag-Erling Smørgrav numport*(i+1)/daemon->num - numport*i/daemon->num))) 591b7579f77SDag-Erling Smørgrav /* the above is not ports/numthr, due to rounding */ 592b7579f77SDag-Erling Smørgrav fatal_exit("could not create worker"); 593b7579f77SDag-Erling Smørgrav } 5941838dec3SCy Schubert /* create per-worker alloc caches if not reusing existing ones. */ 5951838dec3SCy Schubert if(!daemon->worker_allocs) { 5961838dec3SCy Schubert daemon->worker_allocs = (struct alloc_cache**)calloc( 5971838dec3SCy Schubert (size_t)daemon->num, sizeof(struct alloc_cache*)); 5981838dec3SCy Schubert if(!daemon->worker_allocs) 5991838dec3SCy Schubert fatal_exit("could not allocate worker allocs"); 6001838dec3SCy Schubert for(i=0; i<daemon->num; i++) { 6011838dec3SCy Schubert struct alloc_cache* alloc = calloc(1, 6021838dec3SCy Schubert sizeof(struct alloc_cache)); 6031838dec3SCy Schubert if (!alloc) 6041838dec3SCy Schubert fatal_exit("could not allocate worker alloc"); 6051838dec3SCy Schubert alloc_init(alloc, &daemon->superalloc, i); 6061838dec3SCy Schubert daemon->worker_allocs[i] = alloc; 6071838dec3SCy Schubert } 6081838dec3SCy Schubert } 609b7579f77SDag-Erling Smørgrav free(shufport); 610b7579f77SDag-Erling Smørgrav } 611b7579f77SDag-Erling Smørgrav 612b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 613b7579f77SDag-Erling Smørgrav /** 614b7579f77SDag-Erling Smørgrav * Close all pipes except for the numbered thread. 615b7579f77SDag-Erling Smørgrav * @param daemon: daemon to close pipes in. 616b7579f77SDag-Erling Smørgrav * @param thr: thread number 0..num-1 of thread to skip. 617b7579f77SDag-Erling Smørgrav */ 618b7579f77SDag-Erling Smørgrav static void close_other_pipes(struct daemon* daemon, int thr) 619b7579f77SDag-Erling Smørgrav { 620b7579f77SDag-Erling Smørgrav int i; 621b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) 622b7579f77SDag-Erling Smørgrav if(i!=thr) { 623b7579f77SDag-Erling Smørgrav if(i==0) { 624b7579f77SDag-Erling Smørgrav /* only close read part, need to write stats */ 625b7579f77SDag-Erling Smørgrav tube_close_read(daemon->workers[i]->cmd); 626b7579f77SDag-Erling Smørgrav } else { 627b7579f77SDag-Erling Smørgrav /* complete close channel to others */ 628b7579f77SDag-Erling Smørgrav tube_delete(daemon->workers[i]->cmd); 629b7579f77SDag-Erling Smørgrav daemon->workers[i]->cmd = NULL; 630b7579f77SDag-Erling Smørgrav } 631b7579f77SDag-Erling Smørgrav } 632b7579f77SDag-Erling Smørgrav } 633b7579f77SDag-Erling Smørgrav #endif /* THREADS_DISABLED */ 634b7579f77SDag-Erling Smørgrav 635b7579f77SDag-Erling Smørgrav /** 636b7579f77SDag-Erling Smørgrav * Function to start one thread. 637b7579f77SDag-Erling Smørgrav * @param arg: user argument. 638b7579f77SDag-Erling Smørgrav * @return: void* user return value could be used for thread_join results. 639b7579f77SDag-Erling Smørgrav */ 640b7579f77SDag-Erling Smørgrav static void* 641b7579f77SDag-Erling Smørgrav thread_start(void* arg) 642b7579f77SDag-Erling Smørgrav { 643b7579f77SDag-Erling Smørgrav struct worker* worker = (struct worker*)arg; 64417d15b25SDag-Erling Smørgrav int port_num = 0; 645b7579f77SDag-Erling Smørgrav log_thread_set(&worker->thread_num); 646b7579f77SDag-Erling Smørgrav ub_thread_blocksigs(); 647b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 648b7579f77SDag-Erling Smørgrav /* close pipe ends used by main */ 649b7579f77SDag-Erling Smørgrav tube_close_write(worker->cmd); 650b7579f77SDag-Erling Smørgrav close_other_pipes(worker->daemon, worker->thread_num); 651b7579f77SDag-Erling Smørgrav #endif 652ff825849SDag-Erling Smørgrav #ifdef SO_REUSEPORT 65317d15b25SDag-Erling Smørgrav if(worker->daemon->cfg->so_reuseport) 654b75612f8SDag-Erling Smørgrav port_num = worker->thread_num % worker->daemon->num_ports; 65517d15b25SDag-Erling Smørgrav else 65617d15b25SDag-Erling Smørgrav port_num = 0; 65717d15b25SDag-Erling Smørgrav #endif 65817d15b25SDag-Erling Smørgrav if(!worker_init(worker, worker->daemon->cfg, 65917d15b25SDag-Erling Smørgrav worker->daemon->ports[port_num], 0)) 660b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize thread"); 661b7579f77SDag-Erling Smørgrav 662b7579f77SDag-Erling Smørgrav worker_work(worker); 663b7579f77SDag-Erling Smørgrav return NULL; 664b7579f77SDag-Erling Smørgrav } 665b7579f77SDag-Erling Smørgrav 666b7579f77SDag-Erling Smørgrav /** 667b7579f77SDag-Erling Smørgrav * Fork and init the other threads. Main thread returns for special handling. 668b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with other threads to fork. 669b7579f77SDag-Erling Smørgrav */ 670b7579f77SDag-Erling Smørgrav static void 671b7579f77SDag-Erling Smørgrav daemon_start_others(struct daemon* daemon) 672b7579f77SDag-Erling Smørgrav { 673b7579f77SDag-Erling Smørgrav int i; 674b7579f77SDag-Erling Smørgrav log_assert(daemon); 675b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "start threads"); 676b7579f77SDag-Erling Smørgrav /* skip i=0, is this thread */ 677b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 678b7579f77SDag-Erling Smørgrav ub_thread_create(&daemon->workers[i]->thr_id, 679b7579f77SDag-Erling Smørgrav thread_start, daemon->workers[i]); 680b7579f77SDag-Erling Smørgrav #ifdef THREADS_DISABLED 681b7579f77SDag-Erling Smørgrav /* close pipe end of child */ 682b7579f77SDag-Erling Smørgrav tube_close_read(daemon->workers[i]->cmd); 683b7579f77SDag-Erling Smørgrav #endif /* no threads */ 684b7579f77SDag-Erling Smørgrav } 685b7579f77SDag-Erling Smørgrav } 686b7579f77SDag-Erling Smørgrav 687b7579f77SDag-Erling Smørgrav /** 688b7579f77SDag-Erling Smørgrav * Stop the other threads. 689b7579f77SDag-Erling Smørgrav * @param daemon: the daemon with other threads. 690b7579f77SDag-Erling Smørgrav */ 691b7579f77SDag-Erling Smørgrav static void 692b7579f77SDag-Erling Smørgrav daemon_stop_others(struct daemon* daemon) 693b7579f77SDag-Erling Smørgrav { 694b7579f77SDag-Erling Smørgrav int i; 695b7579f77SDag-Erling Smørgrav log_assert(daemon); 696b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "stop threads"); 697b7579f77SDag-Erling Smørgrav /* skip i=0, is this thread */ 698b7579f77SDag-Erling Smørgrav /* use i=0 buffer for sending cmds; because we are #0 */ 699b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 700b7579f77SDag-Erling Smørgrav worker_send_cmd(daemon->workers[i], worker_cmd_quit); 701b7579f77SDag-Erling Smørgrav } 702b7579f77SDag-Erling Smørgrav /* wait for them to quit */ 703b7579f77SDag-Erling Smørgrav for(i=1; i<daemon->num; i++) { 704b7579f77SDag-Erling Smørgrav /* join it to make sure its dead */ 705b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "join %d", i); 706b7579f77SDag-Erling Smørgrav ub_thread_join(daemon->workers[i]->thr_id); 707b7579f77SDag-Erling Smørgrav verbose(VERB_ALGO, "join success %d", i); 708b7579f77SDag-Erling Smørgrav } 709b7579f77SDag-Erling Smørgrav } 710b7579f77SDag-Erling Smørgrav 711b7579f77SDag-Erling Smørgrav void 712b7579f77SDag-Erling Smørgrav daemon_fork(struct daemon* daemon) 713b7579f77SDag-Erling Smørgrav { 71465b390aaSDag-Erling Smørgrav int have_view_respip_cfg = 0; 7150eefd307SCy Schubert #ifdef HAVE_SYSTEMD 7160eefd307SCy Schubert int ret; 7170eefd307SCy Schubert #endif 71865b390aaSDag-Erling Smørgrav 719b7579f77SDag-Erling Smørgrav log_assert(daemon); 720bc892140SDag-Erling Smørgrav if(!(daemon->views = views_create())) 721bc892140SDag-Erling Smørgrav fatal_exit("Could not create views: out of memory"); 722bc892140SDag-Erling Smørgrav /* create individual views and their localzone/data trees */ 723bc892140SDag-Erling Smørgrav if(!views_apply_cfg(daemon->views, daemon->cfg)) 724bc892140SDag-Erling Smørgrav fatal_exit("Could not set up views"); 725bc892140SDag-Erling Smørgrav 726bc892140SDag-Erling Smørgrav if(!acl_list_apply_cfg(daemon->acl, daemon->cfg, daemon->views)) 727b7579f77SDag-Erling Smørgrav fatal_exit("Could not setup access control list"); 728865f46b2SCy Schubert if(!acl_interface_apply_cfg(daemon->acl_interface, daemon->cfg, 729865f46b2SCy Schubert daemon->views)) 730865f46b2SCy Schubert fatal_exit("Could not setup interface control list"); 7314c75e3aaSDag-Erling Smørgrav if(!tcl_list_apply_cfg(daemon->tcl, daemon->cfg)) 7324c75e3aaSDag-Erling Smørgrav fatal_exit("Could not setup TCP connection limits"); 73365b390aaSDag-Erling Smørgrav if(daemon->cfg->dnscrypt) { 73465b390aaSDag-Erling Smørgrav #ifdef USE_DNSCRYPT 73565b390aaSDag-Erling Smørgrav daemon->dnscenv = dnsc_create(); 73665b390aaSDag-Erling Smørgrav if (!daemon->dnscenv) 73765b390aaSDag-Erling Smørgrav fatal_exit("dnsc_create failed"); 73865b390aaSDag-Erling Smørgrav dnsc_apply_cfg(daemon->dnscenv, daemon->cfg); 73965b390aaSDag-Erling Smørgrav #else 74065b390aaSDag-Erling Smørgrav fatal_exit("dnscrypt enabled in config but unbound was not built with " 74165b390aaSDag-Erling Smørgrav "dnscrypt support"); 74265b390aaSDag-Erling Smørgrav #endif 74365b390aaSDag-Erling Smørgrav } 74456850988SCy Schubert if(daemon->cfg->cookie_secret_file && 74556850988SCy Schubert daemon->cfg->cookie_secret_file[0]) { 74656850988SCy Schubert if(!(daemon->cookie_secrets = cookie_secrets_create())) 74756850988SCy Schubert fatal_exit("Could not create cookie_secrets: out of memory"); 74856850988SCy Schubert if(!cookie_secrets_apply_cfg(daemon->cookie_secrets, 74956850988SCy Schubert daemon->cfg->cookie_secret_file)) 75056850988SCy Schubert fatal_exit("Could not setup cookie_secrets"); 75156850988SCy Schubert } 752bc892140SDag-Erling Smørgrav /* create global local_zones */ 753b7579f77SDag-Erling Smørgrav if(!(daemon->local_zones = local_zones_create())) 754b7579f77SDag-Erling Smørgrav fatal_exit("Could not create local zones: out of memory"); 755b7579f77SDag-Erling Smørgrav if(!local_zones_apply_cfg(daemon->local_zones, daemon->cfg)) 756b7579f77SDag-Erling Smørgrav fatal_exit("Could not set up local zones"); 757335c7cdaSCy Schubert if(!(daemon->env->fwds = forwards_create()) || 758335c7cdaSCy Schubert !forwards_apply_cfg(daemon->env->fwds, daemon->cfg)) 759335c7cdaSCy Schubert fatal_exit("Could not set forward zones"); 760335c7cdaSCy Schubert if(!(daemon->env->hints = hints_create()) || 761335c7cdaSCy Schubert !hints_apply_cfg(daemon->env->hints, daemon->cfg)) 762335c7cdaSCy Schubert fatal_exit("Could not set root or stub hints"); 763b7579f77SDag-Erling Smørgrav 76465b390aaSDag-Erling Smørgrav /* process raw response-ip configuration data */ 76565b390aaSDag-Erling Smørgrav if(!(daemon->respip_set = respip_set_create())) 76665b390aaSDag-Erling Smørgrav fatal_exit("Could not create response IP set"); 76765b390aaSDag-Erling Smørgrav if(!respip_global_apply_cfg(daemon->respip_set, daemon->cfg)) 76865b390aaSDag-Erling Smørgrav fatal_exit("Could not set up response IP set"); 76965b390aaSDag-Erling Smørgrav if(!respip_views_apply_cfg(daemon->views, daemon->cfg, 77065b390aaSDag-Erling Smørgrav &have_view_respip_cfg)) 77165b390aaSDag-Erling Smørgrav fatal_exit("Could not set up per-view response IP sets"); 77265b390aaSDag-Erling Smørgrav daemon->use_response_ip = !respip_set_is_empty(daemon->respip_set) || 77365b390aaSDag-Erling Smørgrav have_view_respip_cfg; 77465b390aaSDag-Erling Smørgrav 7755469a995SCy Schubert /* setup modules */ 7765469a995SCy Schubert daemon_setup_modules(daemon); 7775469a995SCy Schubert 77857bddd21SDag-Erling Smørgrav /* read auth zonefiles */ 779091e9e46SCy Schubert if(!auth_zones_apply_cfg(daemon->env->auth_zones, daemon->cfg, 1, 7805469a995SCy Schubert &daemon->use_rpz, daemon->env, &daemon->mods)) 78157bddd21SDag-Erling Smørgrav fatal_exit("auth_zones could not be setup"); 78257bddd21SDag-Erling Smørgrav 783369c6923SCy Schubert /* Set-up EDNS strings */ 784369c6923SCy Schubert if(!edns_strings_apply_cfg(daemon->env->edns_strings, daemon->cfg)) 785369c6923SCy Schubert fatal_exit("Could not set up EDNS strings"); 786c0caa2e2SCy Schubert 787335c7cdaSCy Schubert #ifdef USE_CACHEDB 788335c7cdaSCy Schubert daemon->env->cachedb_enabled = cachedb_is_enabled(&daemon->mods, 789335c7cdaSCy Schubert daemon->env); 790335c7cdaSCy Schubert #endif 79165b390aaSDag-Erling Smørgrav /* response-ip-xxx options don't work as expected without the respip 79265b390aaSDag-Erling Smørgrav * module. To avoid run-time operational surprise we reject such 79365b390aaSDag-Erling Smørgrav * configuration. */ 79465b390aaSDag-Erling Smørgrav if(daemon->use_response_ip && 79565b390aaSDag-Erling Smørgrav modstack_find(&daemon->mods, "respip") < 0) 79665b390aaSDag-Erling Smørgrav fatal_exit("response-ip options require respip module"); 797091e9e46SCy Schubert /* RPZ response ip triggers don't work as expected without the respip 798091e9e46SCy Schubert * module. To avoid run-time operational surprise we reject such 799091e9e46SCy Schubert * configuration. */ 800091e9e46SCy Schubert if(daemon->use_rpz && 801091e9e46SCy Schubert modstack_find(&daemon->mods, "respip") < 0) 802091e9e46SCy Schubert fatal_exit("RPZ requires the respip module"); 80365b390aaSDag-Erling Smørgrav 804b7579f77SDag-Erling Smørgrav /* first create all the worker structures, so we can pass 805b7579f77SDag-Erling Smørgrav * them to the newly created threads. 806b7579f77SDag-Erling Smørgrav */ 807b7579f77SDag-Erling Smørgrav daemon_create_workers(daemon); 808b7579f77SDag-Erling Smørgrav 809b7579f77SDag-Erling Smørgrav #if defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP) 810b7579f77SDag-Erling Smørgrav /* in libev the first inited base gets signals */ 81117d15b25SDag-Erling Smørgrav if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) 812b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize main thread"); 813b7579f77SDag-Erling Smørgrav #endif 814b7579f77SDag-Erling Smørgrav 815b7579f77SDag-Erling Smørgrav /* Now create the threads and init the workers. 816b7579f77SDag-Erling Smørgrav * By the way, this is thread #0 (the main thread). 817b7579f77SDag-Erling Smørgrav */ 818b7579f77SDag-Erling Smørgrav daemon_start_others(daemon); 819b7579f77SDag-Erling Smørgrav 820b7579f77SDag-Erling Smørgrav /* Special handling for the main thread. This is the thread 821b7579f77SDag-Erling Smørgrav * that handles signals and remote control. 822b7579f77SDag-Erling Smørgrav */ 823b7579f77SDag-Erling Smørgrav #if !(defined(HAVE_EV_LOOP) || defined(HAVE_EV_DEFAULT_LOOP)) 824b7579f77SDag-Erling Smørgrav /* libevent has the last inited base get signals (or any base) */ 82517d15b25SDag-Erling Smørgrav if(!worker_init(daemon->workers[0], daemon->cfg, daemon->ports[0], 1)) 826b7579f77SDag-Erling Smørgrav fatal_exit("Could not initialize main thread"); 827b7579f77SDag-Erling Smørgrav #endif 828b7579f77SDag-Erling Smørgrav signal_handling_playback(daemon->workers[0]); 829b7579f77SDag-Erling Smørgrav 83065b390aaSDag-Erling Smørgrav if (!shm_main_init(daemon)) 83165b390aaSDag-Erling Smørgrav log_warn("SHM has failed"); 83265b390aaSDag-Erling Smørgrav 833b7579f77SDag-Erling Smørgrav /* Start resolver service on main thread. */ 8343005e0a3SDag-Erling Smørgrav #ifdef HAVE_SYSTEMD 8350eefd307SCy Schubert ret = sd_notify(0, "READY=1"); 8360eefd307SCy Schubert if(ret <= 0 && getenv("NOTIFY_SOCKET")) 8370eefd307SCy Schubert fatal_exit("sd_notify failed %s: %s. Make sure that unbound has " 8380eefd307SCy Schubert "access/permission to use the socket presented by systemd.", 8390eefd307SCy Schubert getenv("NOTIFY_SOCKET"), 8400eefd307SCy Schubert (ret==0?"no $NOTIFY_SOCKET": strerror(-ret))); 8413005e0a3SDag-Erling Smørgrav #endif 842b7579f77SDag-Erling Smørgrav log_info("start of service (%s).", PACKAGE_STRING); 843b7579f77SDag-Erling Smørgrav worker_work(daemon->workers[0]); 8443005e0a3SDag-Erling Smørgrav #ifdef HAVE_SYSTEMD 8454c75e3aaSDag-Erling Smørgrav if (daemon->workers[0]->need_to_exit) 8463005e0a3SDag-Erling Smørgrav sd_notify(0, "STOPPING=1"); 8474c75e3aaSDag-Erling Smørgrav else 8484c75e3aaSDag-Erling Smørgrav sd_notify(0, "RELOADING=1"); 8493005e0a3SDag-Erling Smørgrav #endif 850b7579f77SDag-Erling Smørgrav log_info("service stopped (%s).", PACKAGE_STRING); 851b7579f77SDag-Erling Smørgrav 852b7579f77SDag-Erling Smørgrav /* we exited! a signal happened! Stop other threads */ 853b7579f77SDag-Erling Smørgrav daemon_stop_others(daemon); 854b7579f77SDag-Erling Smørgrav 85565b390aaSDag-Erling Smørgrav /* Shutdown SHM */ 85665b390aaSDag-Erling Smørgrav shm_main_shutdown(daemon); 85765b390aaSDag-Erling Smørgrav 8581838dec3SCy Schubert daemon->reuse_cache = daemon->workers[0]->reuse_cache; 859b7579f77SDag-Erling Smørgrav daemon->need_to_exit = daemon->workers[0]->need_to_exit; 860b7579f77SDag-Erling Smørgrav } 861b7579f77SDag-Erling Smørgrav 862b7579f77SDag-Erling Smørgrav void 863b7579f77SDag-Erling Smørgrav daemon_cleanup(struct daemon* daemon) 864b7579f77SDag-Erling Smørgrav { 865b7579f77SDag-Erling Smørgrav int i; 866b7579f77SDag-Erling Smørgrav log_assert(daemon); 867b7579f77SDag-Erling Smørgrav /* before stopping main worker, handle signals ourselves, so we 868b7579f77SDag-Erling Smørgrav don't die on multiple reload signals for example. */ 869b7579f77SDag-Erling Smørgrav signal_handling_record(); 870b7579f77SDag-Erling Smørgrav log_thread_set(NULL); 871b7579f77SDag-Erling Smørgrav /* clean up caches because 872b7579f77SDag-Erling Smørgrav * a) RRset IDs will be recycled after a reload, causing collisions 8731838dec3SCy Schubert * b) validation config can change, thus rrset, msg, keycache clear 8741838dec3SCy Schubert * 8751838dec3SCy Schubert * If we are trying to keep the cache as long as possible, we should 8761838dec3SCy Schubert * defer the cleanup until we know whether the new configuration allows 8771838dec3SCy Schubert * the reuse. (If we're exiting, cleanup should be done here). */ 8781838dec3SCy Schubert if(!daemon->reuse_cache || daemon->need_to_exit) { 879b7579f77SDag-Erling Smørgrav slabhash_clear(&daemon->env->rrset_cache->table); 880b7579f77SDag-Erling Smørgrav slabhash_clear(daemon->env->msg_cache); 8811838dec3SCy Schubert } 8821838dec3SCy Schubert daemon->old_num = daemon->num; /* save the current num */ 883335c7cdaSCy Schubert forwards_delete(daemon->env->fwds); 884335c7cdaSCy Schubert daemon->env->fwds = NULL; 885335c7cdaSCy Schubert hints_delete(daemon->env->hints); 886335c7cdaSCy Schubert daemon->env->hints = NULL; 887b7579f77SDag-Erling Smørgrav local_zones_delete(daemon->local_zones); 888b7579f77SDag-Erling Smørgrav daemon->local_zones = NULL; 88965b390aaSDag-Erling Smørgrav respip_set_delete(daemon->respip_set); 89065b390aaSDag-Erling Smørgrav daemon->respip_set = NULL; 891bc892140SDag-Erling Smørgrav views_delete(daemon->views); 892bc892140SDag-Erling Smørgrav daemon->views = NULL; 89357bddd21SDag-Erling Smørgrav if(daemon->env->auth_zones) 89457bddd21SDag-Erling Smørgrav auth_zones_cleanup(daemon->env->auth_zones); 89556850988SCy Schubert /* key cache is cleared by module deinit during next daemon_fork() */ 896b7579f77SDag-Erling Smørgrav daemon_remote_clear(daemon->rc); 897b7579f77SDag-Erling Smørgrav for(i=0; i<daemon->num; i++) 898b7579f77SDag-Erling Smørgrav worker_delete(daemon->workers[i]); 899b7579f77SDag-Erling Smørgrav free(daemon->workers); 900b7579f77SDag-Erling Smørgrav daemon->workers = NULL; 9011838dec3SCy Schubert /* Unless we're trying to keep the cache, worker alloc_caches should be 9021838dec3SCy Schubert * cleared and freed here. We do this after deleting workers to 9031838dec3SCy Schubert * guarantee that the alloc caches are valid throughout the lifetime 9041838dec3SCy Schubert * of workers. */ 9051838dec3SCy Schubert if(!daemon->reuse_cache || daemon->need_to_exit) 9061838dec3SCy Schubert daemon_clear_allocs(daemon); 907b7579f77SDag-Erling Smørgrav daemon->num = 0; 908ff825849SDag-Erling Smørgrav #ifdef USE_DNSTAP 909ff825849SDag-Erling Smørgrav dt_delete(daemon->dtenv); 9100fb34990SDag-Erling Smørgrav daemon->dtenv = NULL; 911ff825849SDag-Erling Smørgrav #endif 912971980c3SDag-Erling Smørgrav #ifdef USE_DNSCRYPT 913971980c3SDag-Erling Smørgrav dnsc_delete(daemon->dnscenv); 9140fb34990SDag-Erling Smørgrav daemon->dnscenv = NULL; 915971980c3SDag-Erling Smørgrav #endif 916*46d2f618SCy Schubert #ifdef HAVE_NGTCP2 917*46d2f618SCy Schubert doq_table_delete(daemon->doq_table); 918*46d2f618SCy Schubert daemon->doq_table = NULL; 919*46d2f618SCy Schubert #endif 920b7579f77SDag-Erling Smørgrav daemon->cfg = NULL; 921b7579f77SDag-Erling Smørgrav } 922b7579f77SDag-Erling Smørgrav 923b7579f77SDag-Erling Smørgrav void 924b7579f77SDag-Erling Smørgrav daemon_delete(struct daemon* daemon) 925b7579f77SDag-Erling Smørgrav { 92617d15b25SDag-Erling Smørgrav size_t i; 927b7579f77SDag-Erling Smørgrav if(!daemon) 928b7579f77SDag-Erling Smørgrav return; 92956850988SCy Schubert modstack_call_deinit(&daemon->mods, daemon->env); 93056850988SCy Schubert modstack_call_destartup(&daemon->mods, daemon->env); 93156850988SCy Schubert modstack_free(&daemon->mods); 932b7579f77SDag-Erling Smørgrav daemon_remote_delete(daemon->rc); 93317d15b25SDag-Erling Smørgrav for(i = 0; i < daemon->num_ports; i++) 93417d15b25SDag-Erling Smørgrav listening_ports_free(daemon->ports[i]); 93517d15b25SDag-Erling Smørgrav free(daemon->ports); 936b7579f77SDag-Erling Smørgrav listening_ports_free(daemon->rc_ports); 937b7579f77SDag-Erling Smørgrav if(daemon->env) { 938b7579f77SDag-Erling Smørgrav slabhash_delete(daemon->env->msg_cache); 939b7579f77SDag-Erling Smørgrav rrset_cache_delete(daemon->env->rrset_cache); 940b7579f77SDag-Erling Smørgrav infra_delete(daemon->env->infra_cache); 941bc892140SDag-Erling Smørgrav edns_known_options_delete(daemon->env); 942369c6923SCy Schubert edns_strings_delete(daemon->env->edns_strings); 94357bddd21SDag-Erling Smørgrav auth_zones_delete(daemon->env->auth_zones); 944b7579f77SDag-Erling Smørgrav } 945b7579f77SDag-Erling Smørgrav ub_randfree(daemon->rand); 946b7579f77SDag-Erling Smørgrav alloc_clear(&daemon->superalloc); 947b7579f77SDag-Erling Smørgrav acl_list_delete(daemon->acl); 948865f46b2SCy Schubert acl_list_delete(daemon->acl_interface); 9494c75e3aaSDag-Erling Smørgrav tcl_list_delete(daemon->tcl); 95056850988SCy Schubert cookie_secrets_delete(daemon->cookie_secrets); 95124e36522SCy Schubert listen_desetup_locks(); 952b7579f77SDag-Erling Smørgrav free(daemon->chroot); 953b7579f77SDag-Erling Smørgrav free(daemon->pidfile); 954b7579f77SDag-Erling Smørgrav free(daemon->env); 9558ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 956e86b9096SDag-Erling Smørgrav listen_sslctx_delete_ticket_keys(); 957b7579f77SDag-Erling Smørgrav SSL_CTX_free((SSL_CTX*)daemon->listen_sslctx); 958b7579f77SDag-Erling Smørgrav SSL_CTX_free((SSL_CTX*)daemon->connect_sslctx); 9598ed2b524SDag-Erling Smørgrav #endif 960b7579f77SDag-Erling Smørgrav free(daemon); 961b7579f77SDag-Erling Smørgrav /* lex cleanup */ 962b7579f77SDag-Erling Smørgrav ub_c_lex_destroy(); 963b7579f77SDag-Erling Smørgrav /* libcrypto cleanup */ 9648ed2b524SDag-Erling Smørgrav #ifdef HAVE_SSL 9650a92a9fcSCy Schubert # if defined(USE_GOST) 96617d15b25SDag-Erling Smørgrav sldns_key_EVP_unload_gost(); 967b7579f77SDag-Erling Smørgrav # endif 968b7579f77SDag-Erling Smørgrav # if HAVE_DECL_SSL_COMP_GET_COMPRESSION_METHODS && HAVE_DECL_SK_SSL_COMP_POP_FREE 969b7579f77SDag-Erling Smørgrav # ifndef S_SPLINT_S 970e2d15004SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 971b7579f77SDag-Erling Smørgrav sk_SSL_COMP_pop_free(comp_meth, (void(*)())CRYPTO_free); 972b7579f77SDag-Erling Smørgrav # endif 973b7579f77SDag-Erling Smørgrav # endif 974e2d15004SDag-Erling Smørgrav # endif 975b7579f77SDag-Erling Smørgrav # ifdef HAVE_OPENSSL_CONFIG 976b7579f77SDag-Erling Smørgrav EVP_cleanup(); 97725039b37SCy Schubert # if (OPENSSL_VERSION_NUMBER < 0x10100000) && !defined(OPENSSL_NO_ENGINE) && defined(HAVE_ENGINE_CLEANUP) 978b7579f77SDag-Erling Smørgrav ENGINE_cleanup(); 979e2d15004SDag-Erling Smørgrav # endif 980b7579f77SDag-Erling Smørgrav CONF_modules_free(); 981b7579f77SDag-Erling Smørgrav # endif 982b5663de9SDag-Erling Smørgrav # ifdef HAVE_CRYPTO_CLEANUP_ALL_EX_DATA 983b7579f77SDag-Erling Smørgrav CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */ 984b5663de9SDag-Erling Smørgrav # endif 985b5663de9SDag-Erling Smørgrav # ifdef HAVE_ERR_FREE_STRINGS 986b7579f77SDag-Erling Smørgrav ERR_free_strings(); 987b5663de9SDag-Erling Smørgrav # endif 988e2d15004SDag-Erling Smørgrav # if OPENSSL_VERSION_NUMBER < 0x10100000 989b7579f77SDag-Erling Smørgrav RAND_cleanup(); 990e2d15004SDag-Erling Smørgrav # endif 9918ed2b524SDag-Erling Smørgrav # if defined(HAVE_SSL) && defined(OPENSSL_THREADS) && !defined(THREADS_DISABLED) 9928ed2b524SDag-Erling Smørgrav ub_openssl_lock_delete(); 9938ed2b524SDag-Erling Smørgrav # endif 99457bddd21SDag-Erling Smørgrav #ifndef HAVE_ARC4RANDOM 99557bddd21SDag-Erling Smørgrav _ARC4_LOCK_DESTROY(); 99657bddd21SDag-Erling Smørgrav #endif 9978ed2b524SDag-Erling Smørgrav #elif defined(HAVE_NSS) 9988ed2b524SDag-Erling Smørgrav NSS_Shutdown(); 9998ed2b524SDag-Erling Smørgrav #endif /* HAVE_SSL or HAVE_NSS */ 1000b7579f77SDag-Erling Smørgrav checklock_stop(); 1001b7579f77SDag-Erling Smørgrav #ifdef USE_WINSOCK 1002b7579f77SDag-Erling Smørgrav if(WSACleanup() != 0) { 1003b7579f77SDag-Erling Smørgrav log_err("Could not WSACleanup: %s", 1004b7579f77SDag-Erling Smørgrav wsa_strerror(WSAGetLastError())); 1005b7579f77SDag-Erling Smørgrav } 1006b7579f77SDag-Erling Smørgrav #endif 1007b7579f77SDag-Erling Smørgrav } 1008b7579f77SDag-Erling Smørgrav 1009b7579f77SDag-Erling Smørgrav void daemon_apply_cfg(struct daemon* daemon, struct config_file* cfg) 1010b7579f77SDag-Erling Smørgrav { 10111838dec3SCy Schubert int new_num = cfg->num_threads?cfg->num_threads:1; 10121838dec3SCy Schubert 1013b7579f77SDag-Erling Smørgrav daemon->cfg = cfg; 1014b7579f77SDag-Erling Smørgrav config_apply(cfg); 10151838dec3SCy Schubert 10161838dec3SCy Schubert /* If this is a reload and we deferred the decision on whether to 10171838dec3SCy Schubert * reuse the alloc, RRset, and message caches, then check to see if 10181838dec3SCy Schubert * it's safe to keep the caches: 10191838dec3SCy Schubert * - changing the number of threads is obviously incompatible with 10201838dec3SCy Schubert * keeping the per-thread alloc caches. It also means we have to 10211838dec3SCy Schubert * clear RRset and message caches. (note that 'new_num' may be 10221838dec3SCy Schubert * adjusted in daemon_create_workers, but for our purpose we can 10231838dec3SCy Schubert * simply compare it with 'old_num'; if they are equal here, 10241838dec3SCy Schubert * 'new_num' won't be adjusted to a different value than 'old_num'). 10251838dec3SCy Schubert * - changing RRset cache size effectively clears any remaining cache 10261838dec3SCy Schubert * entries. We could keep their keys in alloc caches, but it would 10271838dec3SCy Schubert * be more consistent with the sense of the change to clear allocs 10281838dec3SCy Schubert * and free memory. To do so we also have to clear message cache. 10291838dec3SCy Schubert * - only changing message cache size does not necessarily affect 10301838dec3SCy Schubert * RRset or alloc cache. But almost all new subsequent queries will 10311838dec3SCy Schubert * require recursive resolution anyway, so it doesn't help much to 10321838dec3SCy Schubert * just keep RRset and alloc caches. For simplicity we clear/free 10331838dec3SCy Schubert * the other two, too. */ 10341838dec3SCy Schubert if(daemon->worker_allocs && 10351838dec3SCy Schubert (new_num != daemon->old_num || 10361838dec3SCy Schubert !slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, 10371838dec3SCy Schubert cfg->msg_cache_slabs) || 10381838dec3SCy Schubert !slabhash_is_size(&daemon->env->rrset_cache->table, 10391838dec3SCy Schubert cfg->rrset_cache_size, cfg->rrset_cache_slabs))) 10401838dec3SCy Schubert { 10411838dec3SCy Schubert log_warn("cannot reuse caches due to critical config change"); 10421838dec3SCy Schubert slabhash_clear(&daemon->env->rrset_cache->table); 10431838dec3SCy Schubert slabhash_clear(daemon->env->msg_cache); 10441838dec3SCy Schubert daemon_clear_allocs(daemon); 10451838dec3SCy Schubert } 10461838dec3SCy Schubert 10474c75e3aaSDag-Erling Smørgrav if(!slabhash_is_size(daemon->env->msg_cache, cfg->msg_cache_size, 10484c75e3aaSDag-Erling Smørgrav cfg->msg_cache_slabs)) { 1049b7579f77SDag-Erling Smørgrav slabhash_delete(daemon->env->msg_cache); 1050b7579f77SDag-Erling Smørgrav daemon->env->msg_cache = slabhash_create(cfg->msg_cache_slabs, 1051b7579f77SDag-Erling Smørgrav HASH_DEFAULT_STARTARRAY, cfg->msg_cache_size, 1052b7579f77SDag-Erling Smørgrav msgreply_sizefunc, query_info_compare, 1053b7579f77SDag-Erling Smørgrav query_entry_delete, reply_info_delete, NULL); 1054b7579f77SDag-Erling Smørgrav if(!daemon->env->msg_cache) { 1055b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1056b7579f77SDag-Erling Smørgrav } 1057b7579f77SDag-Erling Smørgrav } 1058b7579f77SDag-Erling Smørgrav if((daemon->env->rrset_cache = rrset_cache_adjust( 1059b7579f77SDag-Erling Smørgrav daemon->env->rrset_cache, cfg, &daemon->superalloc)) == 0) 1060b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1061b7579f77SDag-Erling Smørgrav if((daemon->env->infra_cache = infra_adjust(daemon->env->infra_cache, 1062b7579f77SDag-Erling Smørgrav cfg))==0) 1063b7579f77SDag-Erling Smørgrav fatal_exit("malloc failure updating config settings"); 1064b7579f77SDag-Erling Smørgrav } 1065