xref: /freebsd-src/contrib/unbound/daemon/daemon.c (revision 46d2f61818f594174cafe31ee338c6e083fa1876)
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