xref: /minix3/external/bsd/bind/dist/bin/named/main.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: main.c,v 1.18 2015/07/08 17:28:55 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /*! \file */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek #include <config.h>
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <ctype.h>
25*00b67f09SDavid van Moolenbroek #include <stdlib.h>
26*00b67f09SDavid van Moolenbroek #include <string.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/app.h>
29*00b67f09SDavid van Moolenbroek #include <isc/backtrace.h>
30*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
31*00b67f09SDavid van Moolenbroek #include <isc/dir.h>
32*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
33*00b67f09SDavid van Moolenbroek #include <isc/file.h>
34*00b67f09SDavid van Moolenbroek #include <isc/hash.h>
35*00b67f09SDavid van Moolenbroek #include <isc/os.h>
36*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
37*00b67f09SDavid van Moolenbroek #include <isc/print.h>
38*00b67f09SDavid van Moolenbroek #include <isc/resource.h>
39*00b67f09SDavid van Moolenbroek #include <isc/stdio.h>
40*00b67f09SDavid van Moolenbroek #include <isc/string.h>
41*00b67f09SDavid van Moolenbroek #include <isc/task.h>
42*00b67f09SDavid van Moolenbroek #include <isc/timer.h>
43*00b67f09SDavid van Moolenbroek #include <isc/util.h>
44*00b67f09SDavid van Moolenbroek 
45*00b67f09SDavid van Moolenbroek #include <isccc/result.h>
46*00b67f09SDavid van Moolenbroek 
47*00b67f09SDavid van Moolenbroek #include <dns/dispatch.h>
48*00b67f09SDavid van Moolenbroek #include <dns/name.h>
49*00b67f09SDavid van Moolenbroek #include <dns/result.h>
50*00b67f09SDavid van Moolenbroek #include <dns/view.h>
51*00b67f09SDavid van Moolenbroek 
52*00b67f09SDavid van Moolenbroek #include <dst/result.h>
53*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
54*00b67f09SDavid van Moolenbroek #include <pk11/result.h>
55*00b67f09SDavid van Moolenbroek #endif
56*00b67f09SDavid van Moolenbroek 
57*00b67f09SDavid van Moolenbroek #include <dlz/dlz_dlopen_driver.h>
58*00b67f09SDavid van Moolenbroek 
59*00b67f09SDavid van Moolenbroek #ifdef HAVE_GPERFTOOLS_PROFILER
60*00b67f09SDavid van Moolenbroek #include <gperftools/profiler.h>
61*00b67f09SDavid van Moolenbroek #endif
62*00b67f09SDavid van Moolenbroek 
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek /*
65*00b67f09SDavid van Moolenbroek  * Defining NS_MAIN provides storage declarations (rather than extern)
66*00b67f09SDavid van Moolenbroek  * for variables in named/globals.h.
67*00b67f09SDavid van Moolenbroek  */
68*00b67f09SDavid van Moolenbroek #define NS_MAIN 1
69*00b67f09SDavid van Moolenbroek 
70*00b67f09SDavid van Moolenbroek #include <named/builtin.h>
71*00b67f09SDavid van Moolenbroek #include <named/control.h>
72*00b67f09SDavid van Moolenbroek #include <named/globals.h>	/* Explicit, though named/log.h includes it. */
73*00b67f09SDavid van Moolenbroek #include <named/interfacemgr.h>
74*00b67f09SDavid van Moolenbroek #include <named/log.h>
75*00b67f09SDavid van Moolenbroek #include <named/os.h>
76*00b67f09SDavid van Moolenbroek #include <named/server.h>
77*00b67f09SDavid van Moolenbroek #include <named/lwresd.h>
78*00b67f09SDavid van Moolenbroek #include <named/main.h>
79*00b67f09SDavid van Moolenbroek #include <named/seccomp.h>
80*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
81*00b67f09SDavid van Moolenbroek #include <named/ns_smf_globals.h>
82*00b67f09SDavid van Moolenbroek #endif
83*00b67f09SDavid van Moolenbroek 
84*00b67f09SDavid van Moolenbroek #ifdef OPENSSL
85*00b67f09SDavid van Moolenbroek #include <openssl/opensslv.h>
86*00b67f09SDavid van Moolenbroek #include <openssl/crypto.h>
87*00b67f09SDavid van Moolenbroek #endif
88*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBXML2
89*00b67f09SDavid van Moolenbroek #include <libxml/xmlversion.h>
90*00b67f09SDavid van Moolenbroek #endif
91*00b67f09SDavid van Moolenbroek 
92*00b67f09SDavid van Moolenbroek #include "pfilter.h"
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek /*
95*00b67f09SDavid van Moolenbroek  * Include header files for database drivers here.
96*00b67f09SDavid van Moolenbroek  */
97*00b67f09SDavid van Moolenbroek /* #include "xxdb.h" */
98*00b67f09SDavid van Moolenbroek 
99*00b67f09SDavid van Moolenbroek #ifdef CONTRIB_DLZ
100*00b67f09SDavid van Moolenbroek /*
101*00b67f09SDavid van Moolenbroek  * Include contributed DLZ drivers if appropriate.
102*00b67f09SDavid van Moolenbroek  */
103*00b67f09SDavid van Moolenbroek #include <dlz/dlz_drivers.h>
104*00b67f09SDavid van Moolenbroek #endif
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek /*
107*00b67f09SDavid van Moolenbroek  * The maximum number of stack frames to dump on assertion failure.
108*00b67f09SDavid van Moolenbroek  */
109*00b67f09SDavid van Moolenbroek #ifndef BACKTRACE_MAXFRAME
110*00b67f09SDavid van Moolenbroek #define BACKTRACE_MAXFRAME 128
111*00b67f09SDavid van Moolenbroek #endif
112*00b67f09SDavid van Moolenbroek 
113*00b67f09SDavid van Moolenbroek extern int isc_dscp_check_value;
114*00b67f09SDavid van Moolenbroek extern unsigned int dns_zone_mkey_hour;
115*00b67f09SDavid van Moolenbroek extern unsigned int dns_zone_mkey_day;
116*00b67f09SDavid van Moolenbroek extern unsigned int dns_zone_mkey_month;
117*00b67f09SDavid van Moolenbroek 
118*00b67f09SDavid van Moolenbroek static isc_boolean_t	want_stats = ISC_FALSE;
119*00b67f09SDavid van Moolenbroek static char		program_name[ISC_DIR_NAMEMAX] = "named";
120*00b67f09SDavid van Moolenbroek static char		absolute_conffile[ISC_DIR_PATHMAX];
121*00b67f09SDavid van Moolenbroek static char		saved_command_line[512];
122*00b67f09SDavid van Moolenbroek static char		version[512];
123*00b67f09SDavid van Moolenbroek static unsigned int	maxsocks = 0;
124*00b67f09SDavid van Moolenbroek static int		maxudp = 0;
125*00b67f09SDavid van Moolenbroek 
126*00b67f09SDavid van Moolenbroek void
ns_main_earlywarning(const char * format,...)127*00b67f09SDavid van Moolenbroek ns_main_earlywarning(const char *format, ...) {
128*00b67f09SDavid van Moolenbroek 	va_list args;
129*00b67f09SDavid van Moolenbroek 
130*00b67f09SDavid van Moolenbroek 	va_start(args, format);
131*00b67f09SDavid van Moolenbroek 	if (ns_g_lctx != NULL) {
132*00b67f09SDavid van Moolenbroek 		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
133*00b67f09SDavid van Moolenbroek 			       NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
134*00b67f09SDavid van Moolenbroek 			       format, args);
135*00b67f09SDavid van Moolenbroek 	} else {
136*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s: ", program_name);
137*00b67f09SDavid van Moolenbroek 		vfprintf(stderr, format, args);
138*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "\n");
139*00b67f09SDavid van Moolenbroek 		fflush(stderr);
140*00b67f09SDavid van Moolenbroek 	}
141*00b67f09SDavid van Moolenbroek 	va_end(args);
142*00b67f09SDavid van Moolenbroek }
143*00b67f09SDavid van Moolenbroek 
144*00b67f09SDavid van Moolenbroek void
ns_main_earlyfatal(const char * format,...)145*00b67f09SDavid van Moolenbroek ns_main_earlyfatal(const char *format, ...) {
146*00b67f09SDavid van Moolenbroek 	va_list args;
147*00b67f09SDavid van Moolenbroek 
148*00b67f09SDavid van Moolenbroek 	va_start(args, format);
149*00b67f09SDavid van Moolenbroek 	if (ns_g_lctx != NULL) {
150*00b67f09SDavid van Moolenbroek 		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
151*00b67f09SDavid van Moolenbroek 			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
152*00b67f09SDavid van Moolenbroek 			       format, args);
153*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
154*00b67f09SDavid van Moolenbroek 			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
155*00b67f09SDavid van Moolenbroek 			       "exiting (due to early fatal error)");
156*00b67f09SDavid van Moolenbroek 	} else {
157*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s: ", program_name);
158*00b67f09SDavid van Moolenbroek 		vfprintf(stderr, format, args);
159*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "\n");
160*00b67f09SDavid van Moolenbroek 		fflush(stderr);
161*00b67f09SDavid van Moolenbroek 	}
162*00b67f09SDavid van Moolenbroek 	va_end(args);
163*00b67f09SDavid van Moolenbroek 
164*00b67f09SDavid van Moolenbroek 	exit(1);
165*00b67f09SDavid van Moolenbroek }
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek ISC_PLATFORM_NORETURN_PRE static void
168*00b67f09SDavid van Moolenbroek assertion_failed(const char *file, int line, isc_assertiontype_t type,
169*00b67f09SDavid van Moolenbroek 		 const char *cond) ISC_PLATFORM_NORETURN_POST;
170*00b67f09SDavid van Moolenbroek 
171*00b67f09SDavid van Moolenbroek static void
assertion_failed(const char * file,int line,isc_assertiontype_t type,const char * cond)172*00b67f09SDavid van Moolenbroek assertion_failed(const char *file, int line, isc_assertiontype_t type,
173*00b67f09SDavid van Moolenbroek 		 const char *cond)
174*00b67f09SDavid van Moolenbroek {
175*00b67f09SDavid van Moolenbroek 	void *tracebuf[BACKTRACE_MAXFRAME];
176*00b67f09SDavid van Moolenbroek 	int i, nframes;
177*00b67f09SDavid van Moolenbroek 	isc_result_t result;
178*00b67f09SDavid van Moolenbroek 	const char *logsuffix = "";
179*00b67f09SDavid van Moolenbroek 	const char *fname;
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek 	/*
182*00b67f09SDavid van Moolenbroek 	 * Handle assertion failures.
183*00b67f09SDavid van Moolenbroek 	 */
184*00b67f09SDavid van Moolenbroek 
185*00b67f09SDavid van Moolenbroek 	if (ns_g_lctx != NULL) {
186*00b67f09SDavid van Moolenbroek 		/*
187*00b67f09SDavid van Moolenbroek 		 * Reset the assertion callback in case it is the log
188*00b67f09SDavid van Moolenbroek 		 * routines causing the assertion.
189*00b67f09SDavid van Moolenbroek 		 */
190*00b67f09SDavid van Moolenbroek 		isc_assertion_setcallback(NULL);
191*00b67f09SDavid van Moolenbroek 
192*00b67f09SDavid van Moolenbroek 		result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME,
193*00b67f09SDavid van Moolenbroek 						&nframes);
194*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS && nframes > 0)
195*00b67f09SDavid van Moolenbroek 			logsuffix = ", back trace";
196*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
197*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
198*00b67f09SDavid van Moolenbroek 			      "%s:%d: %s(%s) failed%s", file, line,
199*00b67f09SDavid van Moolenbroek 			      isc_assertion_typetotext(type), cond, logsuffix);
200*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
201*00b67f09SDavid van Moolenbroek 			for (i = 0; i < nframes; i++) {
202*00b67f09SDavid van Moolenbroek 				unsigned long offset;
203*00b67f09SDavid van Moolenbroek 
204*00b67f09SDavid van Moolenbroek 				fname = NULL;
205*00b67f09SDavid van Moolenbroek 				result = isc_backtrace_getsymbol(tracebuf[i],
206*00b67f09SDavid van Moolenbroek 								 &fname,
207*00b67f09SDavid van Moolenbroek 								 &offset);
208*00b67f09SDavid van Moolenbroek 				if (result == ISC_R_SUCCESS) {
209*00b67f09SDavid van Moolenbroek 					isc_log_write(ns_g_lctx,
210*00b67f09SDavid van Moolenbroek 						      NS_LOGCATEGORY_GENERAL,
211*00b67f09SDavid van Moolenbroek 						      NS_LOGMODULE_MAIN,
212*00b67f09SDavid van Moolenbroek 						      ISC_LOG_CRITICAL,
213*00b67f09SDavid van Moolenbroek 						      "#%d %p in %s()+0x%lx", i,
214*00b67f09SDavid van Moolenbroek 						      tracebuf[i], fname,
215*00b67f09SDavid van Moolenbroek 						      offset);
216*00b67f09SDavid van Moolenbroek 				} else {
217*00b67f09SDavid van Moolenbroek 					isc_log_write(ns_g_lctx,
218*00b67f09SDavid van Moolenbroek 						      NS_LOGCATEGORY_GENERAL,
219*00b67f09SDavid van Moolenbroek 						      NS_LOGMODULE_MAIN,
220*00b67f09SDavid van Moolenbroek 						      ISC_LOG_CRITICAL,
221*00b67f09SDavid van Moolenbroek 						      "#%d %p in ??", i,
222*00b67f09SDavid van Moolenbroek 						      tracebuf[i]);
223*00b67f09SDavid van Moolenbroek 				}
224*00b67f09SDavid van Moolenbroek 			}
225*00b67f09SDavid van Moolenbroek 		}
226*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
227*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
228*00b67f09SDavid van Moolenbroek 			      "exiting (due to assertion failure)");
229*00b67f09SDavid van Moolenbroek 	} else {
230*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s:%d: %s(%s) failed\n",
231*00b67f09SDavid van Moolenbroek 			file, line, isc_assertion_typetotext(type), cond);
232*00b67f09SDavid van Moolenbroek 		fflush(stderr);
233*00b67f09SDavid van Moolenbroek 	}
234*00b67f09SDavid van Moolenbroek 
235*00b67f09SDavid van Moolenbroek 	if (ns_g_coreok)
236*00b67f09SDavid van Moolenbroek 		abort();
237*00b67f09SDavid van Moolenbroek 	exit(1);
238*00b67f09SDavid van Moolenbroek }
239*00b67f09SDavid van Moolenbroek 
240*00b67f09SDavid van Moolenbroek ISC_PLATFORM_NORETURN_PRE static void
241*00b67f09SDavid van Moolenbroek library_fatal_error(const char *file, int line, const char *format,
242*00b67f09SDavid van Moolenbroek 		    va_list args)
243*00b67f09SDavid van Moolenbroek ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST;
244*00b67f09SDavid van Moolenbroek 
245*00b67f09SDavid van Moolenbroek static void
library_fatal_error(const char * file,int line,const char * format,va_list args)246*00b67f09SDavid van Moolenbroek library_fatal_error(const char *file, int line, const char *format,
247*00b67f09SDavid van Moolenbroek 		    va_list args)
248*00b67f09SDavid van Moolenbroek {
249*00b67f09SDavid van Moolenbroek 	/*
250*00b67f09SDavid van Moolenbroek 	 * Handle isc_error_fatal() calls from our libraries.
251*00b67f09SDavid van Moolenbroek 	 */
252*00b67f09SDavid van Moolenbroek 
253*00b67f09SDavid van Moolenbroek 	if (ns_g_lctx != NULL) {
254*00b67f09SDavid van Moolenbroek 		/*
255*00b67f09SDavid van Moolenbroek 		 * Reset the error callback in case it is the log
256*00b67f09SDavid van Moolenbroek 		 * routines causing the assertion.
257*00b67f09SDavid van Moolenbroek 		 */
258*00b67f09SDavid van Moolenbroek 		isc_error_setfatal(NULL);
259*00b67f09SDavid van Moolenbroek 
260*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
261*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
262*00b67f09SDavid van Moolenbroek 			      "%s:%d: fatal error:", file, line);
263*00b67f09SDavid van Moolenbroek 		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
264*00b67f09SDavid van Moolenbroek 			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
265*00b67f09SDavid van Moolenbroek 			       format, args);
266*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
267*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
268*00b67f09SDavid van Moolenbroek 			      "exiting (due to fatal error in library)");
269*00b67f09SDavid van Moolenbroek 	} else {
270*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s:%d: fatal error: ", file, line);
271*00b67f09SDavid van Moolenbroek 		vfprintf(stderr, format, args);
272*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "\n");
273*00b67f09SDavid van Moolenbroek 		fflush(stderr);
274*00b67f09SDavid van Moolenbroek 	}
275*00b67f09SDavid van Moolenbroek 
276*00b67f09SDavid van Moolenbroek 	if (ns_g_coreok)
277*00b67f09SDavid van Moolenbroek 		abort();
278*00b67f09SDavid van Moolenbroek 	exit(1);
279*00b67f09SDavid van Moolenbroek }
280*00b67f09SDavid van Moolenbroek 
281*00b67f09SDavid van Moolenbroek static void
282*00b67f09SDavid van Moolenbroek library_unexpected_error(const char *file, int line, const char *format,
283*00b67f09SDavid van Moolenbroek 			 va_list args) ISC_FORMAT_PRINTF(3, 0);
284*00b67f09SDavid van Moolenbroek 
285*00b67f09SDavid van Moolenbroek static void
library_unexpected_error(const char * file,int line,const char * format,va_list args)286*00b67f09SDavid van Moolenbroek library_unexpected_error(const char *file, int line, const char *format,
287*00b67f09SDavid van Moolenbroek 			 va_list args)
288*00b67f09SDavid van Moolenbroek {
289*00b67f09SDavid van Moolenbroek 	/*
290*00b67f09SDavid van Moolenbroek 	 * Handle isc_error_unexpected() calls from our libraries.
291*00b67f09SDavid van Moolenbroek 	 */
292*00b67f09SDavid van Moolenbroek 
293*00b67f09SDavid van Moolenbroek 	if (ns_g_lctx != NULL) {
294*00b67f09SDavid van Moolenbroek 		char fmt[2048];
295*00b67f09SDavid van Moolenbroek 		snprintf(fmt, sizeof(fmt),
296*00b67f09SDavid van Moolenbroek 		    "%s:%d: unexpected error: %s", file, line, format);
297*00b67f09SDavid van Moolenbroek 		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
298*00b67f09SDavid van Moolenbroek 			       NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
299*00b67f09SDavid van Moolenbroek 			       fmt, args);
300*00b67f09SDavid van Moolenbroek 	} else {
301*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "%s:%d: fatal error: ", file, line);
302*00b67f09SDavid van Moolenbroek 		vfprintf(stderr, format, args);
303*00b67f09SDavid van Moolenbroek 		fprintf(stderr, "\n");
304*00b67f09SDavid van Moolenbroek 		fflush(stderr);
305*00b67f09SDavid van Moolenbroek 	}
306*00b67f09SDavid van Moolenbroek }
307*00b67f09SDavid van Moolenbroek 
308*00b67f09SDavid van Moolenbroek static void
lwresd_usage(void)309*00b67f09SDavid van Moolenbroek lwresd_usage(void) {
310*00b67f09SDavid van Moolenbroek 	fprintf(stderr,
311*00b67f09SDavid van Moolenbroek 		"usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] "
312*00b67f09SDavid van Moolenbroek 		"[-d debuglevel]\n"
313*00b67f09SDavid van Moolenbroek 		"              [-f|-g] [-n number_of_cpus] [-p port] "
314*00b67f09SDavid van Moolenbroek 		"[-P listen-port] [-s]\n"
315*00b67f09SDavid van Moolenbroek 		"              [-t chrootdir] [-u username] [-i pidfile]\n"
316*00b67f09SDavid van Moolenbroek 		"              [-m {usage|trace|record|size|mctx}]\n");
317*00b67f09SDavid van Moolenbroek }
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek static void
usage(void)320*00b67f09SDavid van Moolenbroek usage(void) {
321*00b67f09SDavid van Moolenbroek 	if (ns_g_lwresdonly) {
322*00b67f09SDavid van Moolenbroek 		lwresd_usage();
323*00b67f09SDavid van Moolenbroek 		return;
324*00b67f09SDavid van Moolenbroek 	}
325*00b67f09SDavid van Moolenbroek 	fprintf(stderr,
326*00b67f09SDavid van Moolenbroek 		"usage: named [-4|-6] [-c conffile] [-d debuglevel] "
327*00b67f09SDavid van Moolenbroek 		"[-E engine] [-f|-g]\n"
328*00b67f09SDavid van Moolenbroek 		"             [-n number_of_cpus] [-p port] [-s] "
329*00b67f09SDavid van Moolenbroek 		"[-t chrootdir] [-u username]\n"
330*00b67f09SDavid van Moolenbroek 		"             [-m {usage|trace|record|size|mctx}]\n");
331*00b67f09SDavid van Moolenbroek }
332*00b67f09SDavid van Moolenbroek 
333*00b67f09SDavid van Moolenbroek static void
save_command_line(int argc,char * argv[])334*00b67f09SDavid van Moolenbroek save_command_line(int argc, char *argv[]) {
335*00b67f09SDavid van Moolenbroek 	int i;
336*00b67f09SDavid van Moolenbroek 	char *src;
337*00b67f09SDavid van Moolenbroek 	char *dst;
338*00b67f09SDavid van Moolenbroek 	char *eob;
339*00b67f09SDavid van Moolenbroek 	const char truncated[] = "...";
340*00b67f09SDavid van Moolenbroek 	isc_boolean_t quoted = ISC_FALSE;
341*00b67f09SDavid van Moolenbroek 
342*00b67f09SDavid van Moolenbroek 	dst = saved_command_line;
343*00b67f09SDavid van Moolenbroek 	eob = saved_command_line + sizeof(saved_command_line);
344*00b67f09SDavid van Moolenbroek 
345*00b67f09SDavid van Moolenbroek 	for (i = 1; i < argc && dst < eob; i++) {
346*00b67f09SDavid van Moolenbroek 		*dst++ = ' ';
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 		src = argv[i];
349*00b67f09SDavid van Moolenbroek 		while (*src != '\0' && dst < eob) {
350*00b67f09SDavid van Moolenbroek 			/*
351*00b67f09SDavid van Moolenbroek 			 * This won't perfectly produce a shell-independent
352*00b67f09SDavid van Moolenbroek 			 * pastable command line in all circumstances, but
353*00b67f09SDavid van Moolenbroek 			 * comes close, and for practical purposes will
354*00b67f09SDavid van Moolenbroek 			 * nearly always be fine.
355*00b67f09SDavid van Moolenbroek 			 */
356*00b67f09SDavid van Moolenbroek 			if (quoted || isalnum(*src & 0xff) ||
357*00b67f09SDavid van Moolenbroek 			    *src == '-' || *src == '_' ||
358*00b67f09SDavid van Moolenbroek 			    *src == '.' || *src == '/') {
359*00b67f09SDavid van Moolenbroek 				*dst++ = *src++;
360*00b67f09SDavid van Moolenbroek 				quoted = ISC_FALSE;
361*00b67f09SDavid van Moolenbroek 			} else {
362*00b67f09SDavid van Moolenbroek 				*dst++ = '\\';
363*00b67f09SDavid van Moolenbroek 				quoted = ISC_TRUE;
364*00b67f09SDavid van Moolenbroek 			}
365*00b67f09SDavid van Moolenbroek 		}
366*00b67f09SDavid van Moolenbroek 	}
367*00b67f09SDavid van Moolenbroek 
368*00b67f09SDavid van Moolenbroek 	INSIST(sizeof(saved_command_line) >= sizeof(truncated));
369*00b67f09SDavid van Moolenbroek 
370*00b67f09SDavid van Moolenbroek 	if (dst == eob)
371*00b67f09SDavid van Moolenbroek 		strcpy(eob - sizeof(truncated), truncated);
372*00b67f09SDavid van Moolenbroek 	else
373*00b67f09SDavid van Moolenbroek 		*dst = '\0';
374*00b67f09SDavid van Moolenbroek }
375*00b67f09SDavid van Moolenbroek 
376*00b67f09SDavid van Moolenbroek static int
parse_int(char * arg,const char * desc)377*00b67f09SDavid van Moolenbroek parse_int(char *arg, const char *desc) {
378*00b67f09SDavid van Moolenbroek 	char *endp;
379*00b67f09SDavid van Moolenbroek 	int tmp;
380*00b67f09SDavid van Moolenbroek 	long int ltmp;
381*00b67f09SDavid van Moolenbroek 
382*00b67f09SDavid van Moolenbroek 	ltmp = strtol(arg, &endp, 10);
383*00b67f09SDavid van Moolenbroek 	tmp = (int) ltmp;
384*00b67f09SDavid van Moolenbroek 	if (*endp != '\0')
385*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("%s '%s' must be numeric", desc, arg);
386*00b67f09SDavid van Moolenbroek 	if (tmp < 0 || tmp != ltmp)
387*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("%s '%s' out of range", desc, arg);
388*00b67f09SDavid van Moolenbroek 	return (tmp);
389*00b67f09SDavid van Moolenbroek }
390*00b67f09SDavid van Moolenbroek 
391*00b67f09SDavid van Moolenbroek static struct flag_def {
392*00b67f09SDavid van Moolenbroek 	const char *name;
393*00b67f09SDavid van Moolenbroek 	unsigned int value;
394*00b67f09SDavid van Moolenbroek } mem_debug_flags[] = {
395*00b67f09SDavid van Moolenbroek 	{ "trace",  ISC_MEM_DEBUGTRACE },
396*00b67f09SDavid van Moolenbroek 	{ "record", ISC_MEM_DEBUGRECORD },
397*00b67f09SDavid van Moolenbroek 	{ "usage", ISC_MEM_DEBUGUSAGE },
398*00b67f09SDavid van Moolenbroek 	{ "size", ISC_MEM_DEBUGSIZE },
399*00b67f09SDavid van Moolenbroek 	{ "mctx", ISC_MEM_DEBUGCTX },
400*00b67f09SDavid van Moolenbroek 	{ NULL, 0 }
401*00b67f09SDavid van Moolenbroek };
402*00b67f09SDavid van Moolenbroek 
403*00b67f09SDavid van Moolenbroek static void
set_flags(const char * arg,struct flag_def * defs,unsigned int * ret)404*00b67f09SDavid van Moolenbroek set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) {
405*00b67f09SDavid van Moolenbroek 	for (;;) {
406*00b67f09SDavid van Moolenbroek 		const struct flag_def *def;
407*00b67f09SDavid van Moolenbroek 		const char *end = strchr(arg, ',');
408*00b67f09SDavid van Moolenbroek 		int arglen;
409*00b67f09SDavid van Moolenbroek 		if (end == NULL)
410*00b67f09SDavid van Moolenbroek 			end = arg + strlen(arg);
411*00b67f09SDavid van Moolenbroek 		arglen = (int)(end - arg);
412*00b67f09SDavid van Moolenbroek 		for (def = defs; def->name != NULL; def++) {
413*00b67f09SDavid van Moolenbroek 			if (arglen == (int)strlen(def->name) &&
414*00b67f09SDavid van Moolenbroek 			    memcmp(arg, def->name, arglen) == 0) {
415*00b67f09SDavid van Moolenbroek 				*ret |= def->value;
416*00b67f09SDavid van Moolenbroek 				goto found;
417*00b67f09SDavid van Moolenbroek 			}
418*00b67f09SDavid van Moolenbroek 		}
419*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
420*00b67f09SDavid van Moolenbroek 	 found:
421*00b67f09SDavid van Moolenbroek 		if (*end == '\0')
422*00b67f09SDavid van Moolenbroek 			break;
423*00b67f09SDavid van Moolenbroek 		arg = end + 1;
424*00b67f09SDavid van Moolenbroek 	}
425*00b67f09SDavid van Moolenbroek }
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek static void
parse_command_line(int argc,char * argv[])428*00b67f09SDavid van Moolenbroek parse_command_line(int argc, char *argv[]) {
429*00b67f09SDavid van Moolenbroek 	int ch;
430*00b67f09SDavid van Moolenbroek 	int port;
431*00b67f09SDavid van Moolenbroek 	const char *p;
432*00b67f09SDavid van Moolenbroek 
433*00b67f09SDavid van Moolenbroek 	save_command_line(argc, argv);
434*00b67f09SDavid van Moolenbroek 
435*00b67f09SDavid van Moolenbroek 	/* PLEASE keep options synchronized when main is hooked! */
436*00b67f09SDavid van Moolenbroek #define CMDLINE_FLAGS "46c:C:d:D:E:fFgi:lm:n:N:p:P:sS:t:T:U:u:vVx:"
437*00b67f09SDavid van Moolenbroek 	isc_commandline_errprint = ISC_FALSE;
438*00b67f09SDavid van Moolenbroek 	while ((ch = isc_commandline_parse(argc, argv, CMDLINE_FLAGS)) != -1) {
439*00b67f09SDavid van Moolenbroek 		switch (ch) {
440*00b67f09SDavid van Moolenbroek 		case '4':
441*00b67f09SDavid van Moolenbroek 			if (ns_g_disable4)
442*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("cannot specify -4 and -6");
443*00b67f09SDavid van Moolenbroek 			if (isc_net_probeipv4() != ISC_R_SUCCESS)
444*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("IPv4 not supported by OS");
445*00b67f09SDavid van Moolenbroek 			isc_net_disableipv6();
446*00b67f09SDavid van Moolenbroek 			ns_g_disable6 = ISC_TRUE;
447*00b67f09SDavid van Moolenbroek 			break;
448*00b67f09SDavid van Moolenbroek 		case '6':
449*00b67f09SDavid van Moolenbroek 			if (ns_g_disable6)
450*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("cannot specify -4 and -6");
451*00b67f09SDavid van Moolenbroek 			if (isc_net_probeipv6() != ISC_R_SUCCESS)
452*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("IPv6 not supported by OS");
453*00b67f09SDavid van Moolenbroek 			isc_net_disableipv4();
454*00b67f09SDavid van Moolenbroek 			ns_g_disable4 = ISC_TRUE;
455*00b67f09SDavid van Moolenbroek 			break;
456*00b67f09SDavid van Moolenbroek 		case 'c':
457*00b67f09SDavid van Moolenbroek 			ns_g_conffile = isc_commandline_argument;
458*00b67f09SDavid van Moolenbroek 			lwresd_g_conffile = isc_commandline_argument;
459*00b67f09SDavid van Moolenbroek 			if (lwresd_g_useresolvconf)
460*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("cannot specify -c and -C");
461*00b67f09SDavid van Moolenbroek 			ns_g_conffileset = ISC_TRUE;
462*00b67f09SDavid van Moolenbroek 			break;
463*00b67f09SDavid van Moolenbroek 		case 'C':
464*00b67f09SDavid van Moolenbroek 			lwresd_g_resolvconffile = isc_commandline_argument;
465*00b67f09SDavid van Moolenbroek 			if (ns_g_conffileset)
466*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("cannot specify -c and -C");
467*00b67f09SDavid van Moolenbroek 			lwresd_g_useresolvconf = ISC_TRUE;
468*00b67f09SDavid van Moolenbroek 			break;
469*00b67f09SDavid van Moolenbroek 		case 'd':
470*00b67f09SDavid van Moolenbroek 			ns_g_debuglevel = parse_int(isc_commandline_argument,
471*00b67f09SDavid van Moolenbroek 						    "debug level");
472*00b67f09SDavid van Moolenbroek 			break;
473*00b67f09SDavid van Moolenbroek 		case 'D':
474*00b67f09SDavid van Moolenbroek 			/* Descriptive comment for 'ps'. */
475*00b67f09SDavid van Moolenbroek 			break;
476*00b67f09SDavid van Moolenbroek 		case 'E':
477*00b67f09SDavid van Moolenbroek 			ns_g_engine = isc_commandline_argument;
478*00b67f09SDavid van Moolenbroek 			break;
479*00b67f09SDavid van Moolenbroek 		case 'f':
480*00b67f09SDavid van Moolenbroek 			ns_g_foreground = ISC_TRUE;
481*00b67f09SDavid van Moolenbroek 			break;
482*00b67f09SDavid van Moolenbroek 		case 'g':
483*00b67f09SDavid van Moolenbroek 			ns_g_foreground = ISC_TRUE;
484*00b67f09SDavid van Moolenbroek 			ns_g_logstderr = ISC_TRUE;
485*00b67f09SDavid van Moolenbroek 			break;
486*00b67f09SDavid van Moolenbroek 		/* XXXBEW -i should be removed */
487*00b67f09SDavid van Moolenbroek 		case 'i':
488*00b67f09SDavid van Moolenbroek 			lwresd_g_defaultpidfile = isc_commandline_argument;
489*00b67f09SDavid van Moolenbroek 			break;
490*00b67f09SDavid van Moolenbroek 		case 'l':
491*00b67f09SDavid van Moolenbroek 			ns_g_lwresdonly = ISC_TRUE;
492*00b67f09SDavid van Moolenbroek 			break;
493*00b67f09SDavid van Moolenbroek 		case 'm':
494*00b67f09SDavid van Moolenbroek 			set_flags(isc_commandline_argument, mem_debug_flags,
495*00b67f09SDavid van Moolenbroek 				  &isc_mem_debugging);
496*00b67f09SDavid van Moolenbroek 			break;
497*00b67f09SDavid van Moolenbroek 		case 'N': /* Deprecated. */
498*00b67f09SDavid van Moolenbroek 		case 'n':
499*00b67f09SDavid van Moolenbroek 			ns_g_cpus = parse_int(isc_commandline_argument,
500*00b67f09SDavid van Moolenbroek 					      "number of cpus");
501*00b67f09SDavid van Moolenbroek 			if (ns_g_cpus == 0)
502*00b67f09SDavid van Moolenbroek 				ns_g_cpus = 1;
503*00b67f09SDavid van Moolenbroek 			break;
504*00b67f09SDavid van Moolenbroek 		case 'p':
505*00b67f09SDavid van Moolenbroek 			port = parse_int(isc_commandline_argument, "port");
506*00b67f09SDavid van Moolenbroek 			if (port < 1 || port > 65535)
507*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("port '%s' out of range",
508*00b67f09SDavid van Moolenbroek 						   isc_commandline_argument);
509*00b67f09SDavid van Moolenbroek 			ns_g_port = port;
510*00b67f09SDavid van Moolenbroek 			break;
511*00b67f09SDavid van Moolenbroek 		/* XXXBEW Should -P be removed? */
512*00b67f09SDavid van Moolenbroek 		case 'P':
513*00b67f09SDavid van Moolenbroek 			port = parse_int(isc_commandline_argument, "port");
514*00b67f09SDavid van Moolenbroek 			if (port < 1 || port > 65535)
515*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("port '%s' out of range",
516*00b67f09SDavid van Moolenbroek 						   isc_commandline_argument);
517*00b67f09SDavid van Moolenbroek 			lwresd_g_listenport = port;
518*00b67f09SDavid van Moolenbroek 			break;
519*00b67f09SDavid van Moolenbroek 		case 's':
520*00b67f09SDavid van Moolenbroek 			/* XXXRTH temporary syntax */
521*00b67f09SDavid van Moolenbroek 			want_stats = ISC_TRUE;
522*00b67f09SDavid van Moolenbroek 			break;
523*00b67f09SDavid van Moolenbroek 		case 'S':
524*00b67f09SDavid van Moolenbroek 			maxsocks = parse_int(isc_commandline_argument,
525*00b67f09SDavid van Moolenbroek 					     "max number of sockets");
526*00b67f09SDavid van Moolenbroek 			break;
527*00b67f09SDavid van Moolenbroek 		case 't':
528*00b67f09SDavid van Moolenbroek 			/* XXXJAB should we make a copy? */
529*00b67f09SDavid van Moolenbroek 			ns_g_chrootdir = isc_commandline_argument;
530*00b67f09SDavid van Moolenbroek 			break;
531*00b67f09SDavid van Moolenbroek 		case 'T':	/* NOT DOCUMENTED */
532*00b67f09SDavid van Moolenbroek 			/*
533*00b67f09SDavid van Moolenbroek 			 * force the server to behave (or misbehave) in
534*00b67f09SDavid van Moolenbroek 			 * specified ways for testing purposes.
535*00b67f09SDavid van Moolenbroek 			 *
536*00b67f09SDavid van Moolenbroek 			 * clienttest: make clients single shot with their
537*00b67f09SDavid van Moolenbroek 			 * 	       own memory context.
538*00b67f09SDavid van Moolenbroek 			 * delay=xxxx: delay client responses by xxxx ms to
539*00b67f09SDavid van Moolenbroek 			 *	       simulate remote servers.
540*00b67f09SDavid van Moolenbroek 			 * dscp=x:     check that dscp values are as
541*00b67f09SDavid van Moolenbroek 			 * 	       expected and assert otherwise.
542*00b67f09SDavid van Moolenbroek 			 */
543*00b67f09SDavid van Moolenbroek 			if (!strcmp(isc_commandline_argument, "clienttest"))
544*00b67f09SDavid van Moolenbroek 				ns_g_clienttest = ISC_TRUE;
545*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "nosoa"))
546*00b67f09SDavid van Moolenbroek 				ns_g_nosoa = ISC_TRUE;
547*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "noaa"))
548*00b67f09SDavid van Moolenbroek 				ns_g_noaa = ISC_TRUE;
549*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "maxudp512"))
550*00b67f09SDavid van Moolenbroek 				maxudp = 512;
551*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "maxudp1460"))
552*00b67f09SDavid van Moolenbroek 				maxudp = 1460;
553*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "dropedns"))
554*00b67f09SDavid van Moolenbroek 				ns_g_dropedns = ISC_TRUE;
555*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "noedns"))
556*00b67f09SDavid van Moolenbroek 				ns_g_noedns = ISC_TRUE;
557*00b67f09SDavid van Moolenbroek 			else if (!strncmp(isc_commandline_argument,
558*00b67f09SDavid van Moolenbroek 					  "maxudp=", 7))
559*00b67f09SDavid van Moolenbroek 				maxudp = atoi(isc_commandline_argument + 7);
560*00b67f09SDavid van Moolenbroek 			else if (!strncmp(isc_commandline_argument,
561*00b67f09SDavid van Moolenbroek 					  "delay=", 6))
562*00b67f09SDavid van Moolenbroek 				ns_g_delay = atoi(isc_commandline_argument + 6);
563*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "nosyslog"))
564*00b67f09SDavid van Moolenbroek 				ns_g_nosyslog = ISC_TRUE;
565*00b67f09SDavid van Moolenbroek 			else if (!strcmp(isc_commandline_argument, "nonearest"))
566*00b67f09SDavid van Moolenbroek 				ns_g_nonearest = ISC_TRUE;
567*00b67f09SDavid van Moolenbroek 			else if (!strncmp(isc_commandline_argument, "dscp=", 5))
568*00b67f09SDavid van Moolenbroek 				isc_dscp_check_value =
569*00b67f09SDavid van Moolenbroek 					   atoi(isc_commandline_argument + 5);
570*00b67f09SDavid van Moolenbroek 			else if (!strncmp(isc_commandline_argument,
571*00b67f09SDavid van Moolenbroek 					  "mkeytimers=", 11))
572*00b67f09SDavid van Moolenbroek 			{
573*00b67f09SDavid van Moolenbroek 				p = strtok(isc_commandline_argument + 11, "/");
574*00b67f09SDavid van Moolenbroek 				if (p == NULL)
575*00b67f09SDavid van Moolenbroek 					ns_main_earlyfatal("bad mkeytimer");
576*00b67f09SDavid van Moolenbroek 				dns_zone_mkey_hour = atoi(p);
577*00b67f09SDavid van Moolenbroek 				if (dns_zone_mkey_hour == 0)
578*00b67f09SDavid van Moolenbroek 					ns_main_earlyfatal("bad mkeytimer");
579*00b67f09SDavid van Moolenbroek 
580*00b67f09SDavid van Moolenbroek 				p = strtok(NULL, "/");
581*00b67f09SDavid van Moolenbroek 				if (p == NULL) {
582*00b67f09SDavid van Moolenbroek 					dns_zone_mkey_day =
583*00b67f09SDavid van Moolenbroek 						(24 * dns_zone_mkey_hour);
584*00b67f09SDavid van Moolenbroek 					dns_zone_mkey_month =
585*00b67f09SDavid van Moolenbroek 						(30 * dns_zone_mkey_day);
586*00b67f09SDavid van Moolenbroek 					break;
587*00b67f09SDavid van Moolenbroek 				}
588*00b67f09SDavid van Moolenbroek 				dns_zone_mkey_day = atoi(p);
589*00b67f09SDavid van Moolenbroek 				if (dns_zone_mkey_day < dns_zone_mkey_hour)
590*00b67f09SDavid van Moolenbroek 					ns_main_earlyfatal("bad mkeytimer");
591*00b67f09SDavid van Moolenbroek 
592*00b67f09SDavid van Moolenbroek 				p = strtok(NULL, "/");
593*00b67f09SDavid van Moolenbroek 				if (p == NULL) {
594*00b67f09SDavid van Moolenbroek 					dns_zone_mkey_month =
595*00b67f09SDavid van Moolenbroek 						(30 * dns_zone_mkey_day);
596*00b67f09SDavid van Moolenbroek 					break;
597*00b67f09SDavid van Moolenbroek 				}
598*00b67f09SDavid van Moolenbroek 				dns_zone_mkey_month = atoi(p);
599*00b67f09SDavid van Moolenbroek 				if (dns_zone_mkey_month < dns_zone_mkey_day)
600*00b67f09SDavid van Moolenbroek 					ns_main_earlyfatal("bad mkeytimer");
601*00b67f09SDavid van Moolenbroek 			} else if (!strcmp(isc_commandline_argument, "notcp"))
602*00b67f09SDavid van Moolenbroek 				ns_g_notcp = ISC_TRUE;
603*00b67f09SDavid van Moolenbroek 			else
604*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "unknown -T flag '%s\n",
605*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
606*00b67f09SDavid van Moolenbroek 			break;
607*00b67f09SDavid van Moolenbroek 		case 'U':
608*00b67f09SDavid van Moolenbroek 			ns_g_udpdisp = parse_int(isc_commandline_argument,
609*00b67f09SDavid van Moolenbroek 						 "number of UDP listeners "
610*00b67f09SDavid van Moolenbroek 						 "per interface");
611*00b67f09SDavid van Moolenbroek 			break;
612*00b67f09SDavid van Moolenbroek 		case 'u':
613*00b67f09SDavid van Moolenbroek 			ns_g_username = isc_commandline_argument;
614*00b67f09SDavid van Moolenbroek 			break;
615*00b67f09SDavid van Moolenbroek 		case 'v':
616*00b67f09SDavid van Moolenbroek 			printf("%s %s", ns_g_product, ns_g_version);
617*00b67f09SDavid van Moolenbroek 			if (*ns_g_description != 0)
618*00b67f09SDavid van Moolenbroek 				printf(" %s", ns_g_description);
619*00b67f09SDavid van Moolenbroek 			printf("\n");
620*00b67f09SDavid van Moolenbroek 			exit(0);
621*00b67f09SDavid van Moolenbroek 		case 'V':
622*00b67f09SDavid van Moolenbroek 			printf("%s %s", ns_g_product, ns_g_version);
623*00b67f09SDavid van Moolenbroek 			if (*ns_g_description != 0)
624*00b67f09SDavid van Moolenbroek 				printf(" %s", ns_g_description);
625*00b67f09SDavid van Moolenbroek 			printf(" <id:%s> built by %s with %s\n", ns_g_srcid,
626*00b67f09SDavid van Moolenbroek 			       ns_g_builder, ns_g_configargs);
627*00b67f09SDavid van Moolenbroek #ifdef __clang__
628*00b67f09SDavid van Moolenbroek 			printf("compiled by CLANG %s\n", __VERSION__);
629*00b67f09SDavid van Moolenbroek #else
630*00b67f09SDavid van Moolenbroek #if defined(__ICC) || defined(__INTEL_COMPILER)
631*00b67f09SDavid van Moolenbroek 			printf("compiled by ICC %s\n", __VERSION__);
632*00b67f09SDavid van Moolenbroek #else
633*00b67f09SDavid van Moolenbroek #ifdef __GNUC__
634*00b67f09SDavid van Moolenbroek 			printf("compiled by GCC %s\n", __VERSION__);
635*00b67f09SDavid van Moolenbroek #endif
636*00b67f09SDavid van Moolenbroek #endif
637*00b67f09SDavid van Moolenbroek #endif
638*00b67f09SDavid van Moolenbroek #ifdef _MSC_VER
639*00b67f09SDavid van Moolenbroek 			printf("compiled by MSVC %d\n", _MSC_VER);
640*00b67f09SDavid van Moolenbroek #endif
641*00b67f09SDavid van Moolenbroek #ifdef __SUNPRO_C
642*00b67f09SDavid van Moolenbroek 			printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
643*00b67f09SDavid van Moolenbroek #endif
644*00b67f09SDavid van Moolenbroek #ifdef OPENSSL
645*00b67f09SDavid van Moolenbroek 			printf("compiled with OpenSSL version: %s\n",
646*00b67f09SDavid van Moolenbroek 			       OPENSSL_VERSION_TEXT);
647*00b67f09SDavid van Moolenbroek #ifndef WIN32
648*00b67f09SDavid van Moolenbroek 			printf("linked to OpenSSL version: %s\n",
649*00b67f09SDavid van Moolenbroek 			       SSLeay_version(SSLEAY_VERSION));
650*00b67f09SDavid van Moolenbroek #endif
651*00b67f09SDavid van Moolenbroek #endif
652*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBXML2
653*00b67f09SDavid van Moolenbroek 			printf("compiled with libxml2 version: %s\n",
654*00b67f09SDavid van Moolenbroek 			       LIBXML_DOTTED_VERSION);
655*00b67f09SDavid van Moolenbroek #ifndef WIN32
656*00b67f09SDavid van Moolenbroek 			printf("linked to libxml2 version: %s\n",
657*00b67f09SDavid van Moolenbroek 			       xmlParserVersion);
658*00b67f09SDavid van Moolenbroek #endif
659*00b67f09SDavid van Moolenbroek #endif
660*00b67f09SDavid van Moolenbroek 			exit(0);
661*00b67f09SDavid van Moolenbroek 		case 'F':
662*00b67f09SDavid van Moolenbroek 			/* Reserved for FIPS mode */
663*00b67f09SDavid van Moolenbroek 			/* FALLTHROUGH */
664*00b67f09SDavid van Moolenbroek 		case '?':
665*00b67f09SDavid van Moolenbroek 			usage();
666*00b67f09SDavid van Moolenbroek 			if (isc_commandline_option == '?')
667*00b67f09SDavid van Moolenbroek 				exit(0);
668*00b67f09SDavid van Moolenbroek 			p = strchr(CMDLINE_FLAGS, isc_commandline_option);
669*00b67f09SDavid van Moolenbroek 			if (p == NULL || *++p != ':')
670*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("unknown option '-%c'",
671*00b67f09SDavid van Moolenbroek 						   isc_commandline_option);
672*00b67f09SDavid van Moolenbroek 			else
673*00b67f09SDavid van Moolenbroek 				ns_main_earlyfatal("option '-%c' requires "
674*00b67f09SDavid van Moolenbroek 						   "an argument",
675*00b67f09SDavid van Moolenbroek 						   isc_commandline_option);
676*00b67f09SDavid van Moolenbroek 			/* FALLTHROUGH */
677*00b67f09SDavid van Moolenbroek 		default:
678*00b67f09SDavid van Moolenbroek 			ns_main_earlyfatal("parsing options returned %d", ch);
679*00b67f09SDavid van Moolenbroek 		}
680*00b67f09SDavid van Moolenbroek 	}
681*00b67f09SDavid van Moolenbroek 
682*00b67f09SDavid van Moolenbroek 	argc -= isc_commandline_index;
683*00b67f09SDavid van Moolenbroek 	argv += isc_commandline_index;
684*00b67f09SDavid van Moolenbroek 	POST(argv);
685*00b67f09SDavid van Moolenbroek 
686*00b67f09SDavid van Moolenbroek 	if (argc > 0) {
687*00b67f09SDavid van Moolenbroek 		usage();
688*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("extra command line arguments");
689*00b67f09SDavid van Moolenbroek 	}
690*00b67f09SDavid van Moolenbroek }
691*00b67f09SDavid van Moolenbroek 
692*00b67f09SDavid van Moolenbroek static isc_result_t
create_managers(void)693*00b67f09SDavid van Moolenbroek create_managers(void) {
694*00b67f09SDavid van Moolenbroek 	isc_result_t result;
695*00b67f09SDavid van Moolenbroek 	unsigned int socks;
696*00b67f09SDavid van Moolenbroek 
697*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
698*00b67f09SDavid van Moolenbroek 	if (ns_g_cpus == 0)
699*00b67f09SDavid van Moolenbroek 		ns_g_cpus = ns_g_cpus_detected;
700*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
701*00b67f09SDavid van Moolenbroek 		      ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
702*00b67f09SDavid van Moolenbroek 		      ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s",
703*00b67f09SDavid van Moolenbroek 		      ns_g_cpus, ns_g_cpus == 1 ? "" : "s");
704*00b67f09SDavid van Moolenbroek #else
705*00b67f09SDavid van Moolenbroek 	ns_g_cpus = 1;
706*00b67f09SDavid van Moolenbroek #endif
707*00b67f09SDavid van Moolenbroek #ifdef WIN32
708*00b67f09SDavid van Moolenbroek 	ns_g_udpdisp = 1;
709*00b67f09SDavid van Moolenbroek #else
710*00b67f09SDavid van Moolenbroek 	if (ns_g_udpdisp == 0) {
711*00b67f09SDavid van Moolenbroek 		if (ns_g_cpus_detected == 1)
712*00b67f09SDavid van Moolenbroek 			ns_g_udpdisp = 1;
713*00b67f09SDavid van Moolenbroek 		else if (ns_g_cpus_detected < 4)
714*00b67f09SDavid van Moolenbroek 			ns_g_udpdisp = 2;
715*00b67f09SDavid van Moolenbroek 		else
716*00b67f09SDavid van Moolenbroek 			ns_g_udpdisp = ns_g_cpus_detected / 2;
717*00b67f09SDavid van Moolenbroek 	}
718*00b67f09SDavid van Moolenbroek 	if (ns_g_udpdisp > ns_g_cpus)
719*00b67f09SDavid van Moolenbroek 		ns_g_udpdisp = ns_g_cpus;
720*00b67f09SDavid van Moolenbroek #endif
721*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
722*00b67f09SDavid van Moolenbroek 		      ISC_LOG_INFO, "using %u UDP listener%s per interface",
723*00b67f09SDavid van Moolenbroek 		      ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s");
724*00b67f09SDavid van Moolenbroek 
725*00b67f09SDavid van Moolenbroek 	result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
726*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
727*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
728*00b67f09SDavid van Moolenbroek 				 "isc_taskmgr_create() failed: %s",
729*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
730*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
731*00b67f09SDavid van Moolenbroek 	}
732*00b67f09SDavid van Moolenbroek 
733*00b67f09SDavid van Moolenbroek 	result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
734*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
735*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
736*00b67f09SDavid van Moolenbroek 				 "isc_timermgr_create() failed: %s",
737*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
738*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
739*00b67f09SDavid van Moolenbroek 	}
740*00b67f09SDavid van Moolenbroek 
741*00b67f09SDavid van Moolenbroek 	result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks);
742*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
743*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
744*00b67f09SDavid van Moolenbroek 				 "isc_socketmgr_create() failed: %s",
745*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
746*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
747*00b67f09SDavid van Moolenbroek 	}
748*00b67f09SDavid van Moolenbroek 	isc__socketmgr_maxudp(ns_g_socketmgr, maxudp);
749*00b67f09SDavid van Moolenbroek 	result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
750*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS) {
751*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
752*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_SERVER,
753*00b67f09SDavid van Moolenbroek 			      ISC_LOG_INFO, "using up to %u sockets", socks);
754*00b67f09SDavid van Moolenbroek 	}
755*00b67f09SDavid van Moolenbroek 
756*00b67f09SDavid van Moolenbroek 	result = isc_entropy_create(ns_g_mctx, &ns_g_entropy);
757*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
758*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
759*00b67f09SDavid van Moolenbroek 				 "isc_entropy_create() failed: %s",
760*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
761*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
762*00b67f09SDavid van Moolenbroek 	}
763*00b67f09SDavid van Moolenbroek 
764*00b67f09SDavid van Moolenbroek 	result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE);
765*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS) {
766*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
767*00b67f09SDavid van Moolenbroek 				 "isc_hash_create() failed: %s",
768*00b67f09SDavid van Moolenbroek 				 isc_result_totext(result));
769*00b67f09SDavid van Moolenbroek 		return (ISC_R_UNEXPECTED);
770*00b67f09SDavid van Moolenbroek 	}
771*00b67f09SDavid van Moolenbroek 
772*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
773*00b67f09SDavid van Moolenbroek }
774*00b67f09SDavid van Moolenbroek 
775*00b67f09SDavid van Moolenbroek static void
destroy_managers(void)776*00b67f09SDavid van Moolenbroek destroy_managers(void) {
777*00b67f09SDavid van Moolenbroek 	ns_lwresd_shutdown();
778*00b67f09SDavid van Moolenbroek 
779*00b67f09SDavid van Moolenbroek 	isc_entropy_detach(&ns_g_entropy);
780*00b67f09SDavid van Moolenbroek 	if (ns_g_fallbackentropy != NULL)
781*00b67f09SDavid van Moolenbroek 		isc_entropy_detach(&ns_g_fallbackentropy);
782*00b67f09SDavid van Moolenbroek 
783*00b67f09SDavid van Moolenbroek 	/*
784*00b67f09SDavid van Moolenbroek 	 * isc_taskmgr_destroy() will block until all tasks have exited,
785*00b67f09SDavid van Moolenbroek 	 */
786*00b67f09SDavid van Moolenbroek 	isc_taskmgr_destroy(&ns_g_taskmgr);
787*00b67f09SDavid van Moolenbroek 	isc_timermgr_destroy(&ns_g_timermgr);
788*00b67f09SDavid van Moolenbroek 	isc_socketmgr_destroy(&ns_g_socketmgr);
789*00b67f09SDavid van Moolenbroek 
790*00b67f09SDavid van Moolenbroek 	/*
791*00b67f09SDavid van Moolenbroek 	 * isc_hash_destroy() cannot be called as long as a resolver may be
792*00b67f09SDavid van Moolenbroek 	 * running.  Calling this after isc_taskmgr_destroy() ensures the
793*00b67f09SDavid van Moolenbroek 	 * call is safe.
794*00b67f09SDavid van Moolenbroek 	 */
795*00b67f09SDavid van Moolenbroek 	isc_hash_destroy();
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek 
798*00b67f09SDavid van Moolenbroek static void
dump_symboltable(void)799*00b67f09SDavid van Moolenbroek dump_symboltable(void) {
800*00b67f09SDavid van Moolenbroek 	int i;
801*00b67f09SDavid van Moolenbroek 	isc_result_t result;
802*00b67f09SDavid van Moolenbroek 	const char *fname;
803*00b67f09SDavid van Moolenbroek 	const void *addr;
804*00b67f09SDavid van Moolenbroek 
805*00b67f09SDavid van Moolenbroek 	if (isc__backtrace_nsymbols == 0)
806*00b67f09SDavid van Moolenbroek 		return;
807*00b67f09SDavid van Moolenbroek 
808*00b67f09SDavid van Moolenbroek 	if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99)))
809*00b67f09SDavid van Moolenbroek 		return;
810*00b67f09SDavid van Moolenbroek 
811*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
812*00b67f09SDavid van Moolenbroek 		      ISC_LOG_DEBUG(99), "Symbol table:");
813*00b67f09SDavid van Moolenbroek 
814*00b67f09SDavid van Moolenbroek 	for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) {
815*00b67f09SDavid van Moolenbroek 		addr = NULL;
816*00b67f09SDavid van Moolenbroek 		fname = NULL;
817*00b67f09SDavid van Moolenbroek 		result = isc_backtrace_getsymbolfromindex(i, &addr, &fname);
818*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
819*00b67f09SDavid van Moolenbroek 			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
820*00b67f09SDavid van Moolenbroek 				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99),
821*00b67f09SDavid van Moolenbroek 				      "[%d] %p %s", i, addr, fname);
822*00b67f09SDavid van Moolenbroek 		}
823*00b67f09SDavid van Moolenbroek 	}
824*00b67f09SDavid van Moolenbroek }
825*00b67f09SDavid van Moolenbroek 
826*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSECCOMP
827*00b67f09SDavid van Moolenbroek static void
setup_seccomp()828*00b67f09SDavid van Moolenbroek setup_seccomp() {
829*00b67f09SDavid van Moolenbroek 	scmp_filter_ctx ctx;
830*00b67f09SDavid van Moolenbroek 	unsigned int i;
831*00b67f09SDavid van Moolenbroek 	int ret;
832*00b67f09SDavid van Moolenbroek 
833*00b67f09SDavid van Moolenbroek 	/* Make sure the lists are in sync */
834*00b67f09SDavid van Moolenbroek 	INSIST((sizeof(scmp_syscalls) / sizeof(int)) ==
835*00b67f09SDavid van Moolenbroek 	       (sizeof(scmp_syscall_names) / sizeof(const char *)));
836*00b67f09SDavid van Moolenbroek 
837*00b67f09SDavid van Moolenbroek 	ctx = seccomp_init(SCMP_ACT_KILL);
838*00b67f09SDavid van Moolenbroek 	if (ctx == NULL) {
839*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
840*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
841*00b67f09SDavid van Moolenbroek 			      "libseccomp activation failed");
842*00b67f09SDavid van Moolenbroek 		return;
843*00b67f09SDavid van Moolenbroek 	}
844*00b67f09SDavid van Moolenbroek 
845*00b67f09SDavid van Moolenbroek 	for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) {
846*00b67f09SDavid van Moolenbroek 		ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
847*00b67f09SDavid van Moolenbroek 				       scmp_syscalls[i], 0);
848*00b67f09SDavid van Moolenbroek 		if (ret < 0)
849*00b67f09SDavid van Moolenbroek 			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
850*00b67f09SDavid van Moolenbroek 				      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
851*00b67f09SDavid van Moolenbroek 				      "libseccomp rule failed: %s",
852*00b67f09SDavid van Moolenbroek 				      scmp_syscall_names[i]);
853*00b67f09SDavid van Moolenbroek 
854*00b67f09SDavid van Moolenbroek 		else
855*00b67f09SDavid van Moolenbroek 			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
856*00b67f09SDavid van Moolenbroek 				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9),
857*00b67f09SDavid van Moolenbroek 				      "added libseccomp rule: %s",
858*00b67f09SDavid van Moolenbroek 				      scmp_syscall_names[i]);
859*00b67f09SDavid van Moolenbroek 	}
860*00b67f09SDavid van Moolenbroek 
861*00b67f09SDavid van Moolenbroek 	ret = seccomp_load(ctx);
862*00b67f09SDavid van Moolenbroek 	if (ret < 0) {
863*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
864*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
865*00b67f09SDavid van Moolenbroek 			      "libseccomp unable to load filter");
866*00b67f09SDavid van Moolenbroek 	} else {
867*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
868*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
869*00b67f09SDavid van Moolenbroek 			      "libseccomp sandboxing active");
870*00b67f09SDavid van Moolenbroek 	}
871*00b67f09SDavid van Moolenbroek 
872*00b67f09SDavid van Moolenbroek 	/*
873*00b67f09SDavid van Moolenbroek 	 * Release filter in ctx. Filters already loaded are not
874*00b67f09SDavid van Moolenbroek 	 * affected.
875*00b67f09SDavid van Moolenbroek 	 */
876*00b67f09SDavid van Moolenbroek 	seccomp_release(ctx);
877*00b67f09SDavid van Moolenbroek }
878*00b67f09SDavid van Moolenbroek #endif /* HAVE_LIBSECCOMP */
879*00b67f09SDavid van Moolenbroek 
880*00b67f09SDavid van Moolenbroek static void
setup(void)881*00b67f09SDavid van Moolenbroek setup(void) {
882*00b67f09SDavid van Moolenbroek 	isc_result_t result;
883*00b67f09SDavid van Moolenbroek 	isc_resourcevalue_t old_openfiles;
884*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
885*00b67f09SDavid van Moolenbroek 	char *instance = NULL;
886*00b67f09SDavid van Moolenbroek #endif
887*00b67f09SDavid van Moolenbroek 
888*00b67f09SDavid van Moolenbroek 	/*
889*00b67f09SDavid van Moolenbroek 	 * Get the user and group information before changing the root
890*00b67f09SDavid van Moolenbroek 	 * directory, so the administrator does not need to keep a copy
891*00b67f09SDavid van Moolenbroek 	 * of the user and group databases in the chroot'ed environment.
892*00b67f09SDavid van Moolenbroek 	 */
893*00b67f09SDavid van Moolenbroek 	ns_os_inituserinfo(ns_g_username);
894*00b67f09SDavid van Moolenbroek 
895*00b67f09SDavid van Moolenbroek 	/*
896*00b67f09SDavid van Moolenbroek 	 * Initialize time conversion information
897*00b67f09SDavid van Moolenbroek 	 */
898*00b67f09SDavid van Moolenbroek 	ns_os_tzset();
899*00b67f09SDavid van Moolenbroek 
900*00b67f09SDavid van Moolenbroek 	ns_os_opendevnull();
901*00b67f09SDavid van Moolenbroek 
902*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
903*00b67f09SDavid van Moolenbroek 	/* Check if named is under smf control, before chroot. */
904*00b67f09SDavid van Moolenbroek 	result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
905*00b67f09SDavid van Moolenbroek 	/* We don't care about instance, just check if we got one. */
906*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS)
907*00b67f09SDavid van Moolenbroek 		ns_smf_got_instance = 1;
908*00b67f09SDavid van Moolenbroek 	else
909*00b67f09SDavid van Moolenbroek 		ns_smf_got_instance = 0;
910*00b67f09SDavid van Moolenbroek 	if (instance != NULL)
911*00b67f09SDavid van Moolenbroek 		isc_mem_free(ns_g_mctx, instance);
912*00b67f09SDavid van Moolenbroek #endif /* HAVE_LIBSCF */
913*00b67f09SDavid van Moolenbroek 
914*00b67f09SDavid van Moolenbroek #ifdef PATH_RANDOMDEV
915*00b67f09SDavid van Moolenbroek 	/*
916*00b67f09SDavid van Moolenbroek 	 * Initialize system's random device as fallback entropy source
917*00b67f09SDavid van Moolenbroek 	 * if running chroot'ed.
918*00b67f09SDavid van Moolenbroek 	 */
919*00b67f09SDavid van Moolenbroek 	if (ns_g_chrootdir != NULL) {
920*00b67f09SDavid van Moolenbroek 		result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
921*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
922*00b67f09SDavid van Moolenbroek 			ns_main_earlyfatal("isc_entropy_create() failed: %s",
923*00b67f09SDavid van Moolenbroek 					   isc_result_totext(result));
924*00b67f09SDavid van Moolenbroek 
925*00b67f09SDavid van Moolenbroek 		result = isc_entropy_createfilesource(ns_g_fallbackentropy,
926*00b67f09SDavid van Moolenbroek 						      PATH_RANDOMDEV);
927*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
928*00b67f09SDavid van Moolenbroek 			ns_main_earlywarning("could not open pre-chroot "
929*00b67f09SDavid van Moolenbroek 					     "entropy source %s: %s",
930*00b67f09SDavid van Moolenbroek 					     PATH_RANDOMDEV,
931*00b67f09SDavid van Moolenbroek 					     isc_result_totext(result));
932*00b67f09SDavid van Moolenbroek 			isc_entropy_detach(&ns_g_fallbackentropy);
933*00b67f09SDavid van Moolenbroek 		}
934*00b67f09SDavid van Moolenbroek 	}
935*00b67f09SDavid van Moolenbroek #endif
936*00b67f09SDavid van Moolenbroek 
937*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_USETHREADS
938*00b67f09SDavid van Moolenbroek 	/*
939*00b67f09SDavid van Moolenbroek 	 * Check for the number of cpu's before ns_os_chroot().
940*00b67f09SDavid van Moolenbroek 	 */
941*00b67f09SDavid van Moolenbroek 	ns_g_cpus_detected = isc_os_ncpus();
942*00b67f09SDavid van Moolenbroek #endif
943*00b67f09SDavid van Moolenbroek 
944*00b67f09SDavid van Moolenbroek 	ns_os_chroot(ns_g_chrootdir);
945*00b67f09SDavid van Moolenbroek 
946*00b67f09SDavid van Moolenbroek 	/*
947*00b67f09SDavid van Moolenbroek 	 * For operating systems which have a capability mechanism, now
948*00b67f09SDavid van Moolenbroek 	 * is the time to switch to minimal privs and change our user id.
949*00b67f09SDavid van Moolenbroek 	 * On traditional UNIX systems, this call will be a no-op, and we
950*00b67f09SDavid van Moolenbroek 	 * will change the user ID after reading the config file the first
951*00b67f09SDavid van Moolenbroek 	 * time.  (We need to read the config file to know which possibly
952*00b67f09SDavid van Moolenbroek 	 * privileged ports to bind() to.)
953*00b67f09SDavid van Moolenbroek 	 */
954*00b67f09SDavid van Moolenbroek 	ns_os_minprivs();
955*00b67f09SDavid van Moolenbroek 
956*00b67f09SDavid van Moolenbroek 	result = ns_log_init(ISC_TF(ns_g_username != NULL));
957*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
958*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("ns_log_init() failed: %s",
959*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
960*00b67f09SDavid van Moolenbroek 
961*00b67f09SDavid van Moolenbroek 	/*
962*00b67f09SDavid van Moolenbroek 	 * Now is the time to daemonize (if we're not running in the
963*00b67f09SDavid van Moolenbroek 	 * foreground).  We waited until now because we wanted to get
964*00b67f09SDavid van Moolenbroek 	 * a valid logging context setup.  We cannot daemonize any later,
965*00b67f09SDavid van Moolenbroek 	 * because calling create_managers() will create threads, which
966*00b67f09SDavid van Moolenbroek 	 * would be lost after fork().
967*00b67f09SDavid van Moolenbroek 	 */
968*00b67f09SDavid van Moolenbroek 	if (!ns_g_foreground)
969*00b67f09SDavid van Moolenbroek 		ns_os_daemonize();
970*00b67f09SDavid van Moolenbroek 
971*00b67f09SDavid van Moolenbroek 	/*
972*00b67f09SDavid van Moolenbroek 	 * We call isc_app_start() here as some versions of FreeBSD's fork()
973*00b67f09SDavid van Moolenbroek 	 * destroys all the signal handling it sets up.
974*00b67f09SDavid van Moolenbroek 	 */
975*00b67f09SDavid van Moolenbroek 	result = isc_app_start();
976*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
977*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("isc_app_start() failed: %s",
978*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
979*00b67f09SDavid van Moolenbroek 
980*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
981*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE, "starting %s %s%s", ns_g_product,
982*00b67f09SDavid van Moolenbroek 		      ns_g_version, saved_command_line);
983*00b67f09SDavid van Moolenbroek 
984*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
985*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE, "built with %s", ns_g_configargs);
986*00b67f09SDavid van Moolenbroek 
987*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
988*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
989*00b67f09SDavid van Moolenbroek 		      "----------------------------------------------------");
990*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
991*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
992*00b67f09SDavid van Moolenbroek 		      "BIND 9 is maintained by Internet Systems Consortium,");
993*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
994*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
995*00b67f09SDavid van Moolenbroek 		      "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
996*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
997*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
998*00b67f09SDavid van Moolenbroek 		      "corporation.  Support and training for BIND 9 are ");
999*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
1000*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
1001*00b67f09SDavid van Moolenbroek 		      "available at https://www.isc.org/support");
1002*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
1003*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE,
1004*00b67f09SDavid van Moolenbroek 		      "----------------------------------------------------");
1005*00b67f09SDavid van Moolenbroek 
1006*00b67f09SDavid van Moolenbroek 	dump_symboltable();
1007*00b67f09SDavid van Moolenbroek 
1008*00b67f09SDavid van Moolenbroek 	/*
1009*00b67f09SDavid van Moolenbroek 	 * Get the initial resource limits.
1010*00b67f09SDavid van Moolenbroek 	 */
1011*00b67f09SDavid van Moolenbroek 	(void)isc_resource_getlimit(isc_resource_stacksize,
1012*00b67f09SDavid van Moolenbroek 				    &ns_g_initstacksize);
1013*00b67f09SDavid van Moolenbroek 	(void)isc_resource_getlimit(isc_resource_datasize,
1014*00b67f09SDavid van Moolenbroek 				    &ns_g_initdatasize);
1015*00b67f09SDavid van Moolenbroek 	(void)isc_resource_getlimit(isc_resource_coresize,
1016*00b67f09SDavid van Moolenbroek 				    &ns_g_initcoresize);
1017*00b67f09SDavid van Moolenbroek 	(void)isc_resource_getlimit(isc_resource_openfiles,
1018*00b67f09SDavid van Moolenbroek 				    &ns_g_initopenfiles);
1019*00b67f09SDavid van Moolenbroek 
1020*00b67f09SDavid van Moolenbroek 	/*
1021*00b67f09SDavid van Moolenbroek 	 * System resources cannot effectively be tuned on some systems.
1022*00b67f09SDavid van Moolenbroek 	 * Raise the limit in such cases for safety.
1023*00b67f09SDavid van Moolenbroek 	 */
1024*00b67f09SDavid van Moolenbroek 	old_openfiles = ns_g_initopenfiles;
1025*00b67f09SDavid van Moolenbroek 	ns_os_adjustnofile();
1026*00b67f09SDavid van Moolenbroek 	(void)isc_resource_getlimit(isc_resource_openfiles,
1027*00b67f09SDavid van Moolenbroek 				    &ns_g_initopenfiles);
1028*00b67f09SDavid van Moolenbroek 	if (old_openfiles != ns_g_initopenfiles) {
1029*00b67f09SDavid van Moolenbroek 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
1030*00b67f09SDavid van Moolenbroek 			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
1031*00b67f09SDavid van Moolenbroek 			      "adjusted limit on open files from "
1032*00b67f09SDavid van Moolenbroek 			      "%" ISC_PRINT_QUADFORMAT "u to "
1033*00b67f09SDavid van Moolenbroek 			      "%" ISC_PRINT_QUADFORMAT "u",
1034*00b67f09SDavid van Moolenbroek 			      old_openfiles, ns_g_initopenfiles);
1035*00b67f09SDavid van Moolenbroek 	}
1036*00b67f09SDavid van Moolenbroek 
1037*00b67f09SDavid van Moolenbroek 	/*
1038*00b67f09SDavid van Moolenbroek 	 * If the named configuration filename is relative, prepend the current
1039*00b67f09SDavid van Moolenbroek 	 * directory's name before possibly changing to another directory.
1040*00b67f09SDavid van Moolenbroek 	 */
1041*00b67f09SDavid van Moolenbroek 	if (! isc_file_isabsolute(ns_g_conffile)) {
1042*00b67f09SDavid van Moolenbroek 		result = isc_file_absolutepath(ns_g_conffile,
1043*00b67f09SDavid van Moolenbroek 					       absolute_conffile,
1044*00b67f09SDavid van Moolenbroek 					       sizeof(absolute_conffile));
1045*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS)
1046*00b67f09SDavid van Moolenbroek 			ns_main_earlyfatal("could not construct absolute path "
1047*00b67f09SDavid van Moolenbroek 					   "of configuration file: %s",
1048*00b67f09SDavid van Moolenbroek 					   isc_result_totext(result));
1049*00b67f09SDavid van Moolenbroek 		ns_g_conffile = absolute_conffile;
1050*00b67f09SDavid van Moolenbroek 	}
1051*00b67f09SDavid van Moolenbroek 
1052*00b67f09SDavid van Moolenbroek 	/*
1053*00b67f09SDavid van Moolenbroek 	 * Record the server's startup time.
1054*00b67f09SDavid van Moolenbroek 	 */
1055*00b67f09SDavid van Moolenbroek 	result = isc_time_now(&ns_g_boottime);
1056*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1057*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("isc_time_now() failed: %s",
1058*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
1059*00b67f09SDavid van Moolenbroek 
1060*00b67f09SDavid van Moolenbroek 	result = create_managers();
1061*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1062*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("create_managers() failed: %s",
1063*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
1064*00b67f09SDavid van Moolenbroek 
1065*00b67f09SDavid van Moolenbroek 	ns_builtin_init();
1066*00b67f09SDavid van Moolenbroek 
1067*00b67f09SDavid van Moolenbroek 	/*
1068*00b67f09SDavid van Moolenbroek 	 * Add calls to register sdb drivers here.
1069*00b67f09SDavid van Moolenbroek 	 */
1070*00b67f09SDavid van Moolenbroek 	/* xxdb_init(); */
1071*00b67f09SDavid van Moolenbroek 
1072*00b67f09SDavid van Moolenbroek #ifdef ISC_DLZ_DLOPEN
1073*00b67f09SDavid van Moolenbroek 	/*
1074*00b67f09SDavid van Moolenbroek 	 * Register the DLZ "dlopen" driver.
1075*00b67f09SDavid van Moolenbroek 	 */
1076*00b67f09SDavid van Moolenbroek 	result = dlz_dlopen_init(ns_g_mctx);
1077*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1078*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("dlz_dlopen_init() failed: %s",
1079*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
1080*00b67f09SDavid van Moolenbroek #endif
1081*00b67f09SDavid van Moolenbroek 
1082*00b67f09SDavid van Moolenbroek #if CONTRIB_DLZ
1083*00b67f09SDavid van Moolenbroek 	/*
1084*00b67f09SDavid van Moolenbroek 	 * Register any other contributed DLZ drivers.
1085*00b67f09SDavid van Moolenbroek 	 */
1086*00b67f09SDavid van Moolenbroek 	result = dlz_drivers_init();
1087*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1088*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("dlz_drivers_init() failed: %s",
1089*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
1090*00b67f09SDavid van Moolenbroek #endif
1091*00b67f09SDavid van Moolenbroek 
1092*00b67f09SDavid van Moolenbroek 	ns_server_create(ns_g_mctx, &ns_g_server);
1093*00b67f09SDavid van Moolenbroek 
1094*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSECCOMP
1095*00b67f09SDavid van Moolenbroek 	setup_seccomp();
1096*00b67f09SDavid van Moolenbroek #endif /* HAVE_LIBSECCOMP */
1097*00b67f09SDavid van Moolenbroek }
1098*00b67f09SDavid van Moolenbroek 
1099*00b67f09SDavid van Moolenbroek static void
cleanup(void)1100*00b67f09SDavid van Moolenbroek cleanup(void) {
1101*00b67f09SDavid van Moolenbroek 	destroy_managers();
1102*00b67f09SDavid van Moolenbroek 
1103*00b67f09SDavid van Moolenbroek 	ns_server_destroy(&ns_g_server);
1104*00b67f09SDavid van Moolenbroek 
1105*00b67f09SDavid van Moolenbroek 	ns_builtin_deinit();
1106*00b67f09SDavid van Moolenbroek 
1107*00b67f09SDavid van Moolenbroek 	/*
1108*00b67f09SDavid van Moolenbroek 	 * Add calls to unregister sdb drivers here.
1109*00b67f09SDavid van Moolenbroek 	 */
1110*00b67f09SDavid van Moolenbroek 	/* xxdb_clear(); */
1111*00b67f09SDavid van Moolenbroek 
1112*00b67f09SDavid van Moolenbroek #ifdef CONTRIB_DLZ
1113*00b67f09SDavid van Moolenbroek 	/*
1114*00b67f09SDavid van Moolenbroek 	 * Unregister contributed DLZ drivers.
1115*00b67f09SDavid van Moolenbroek 	 */
1116*00b67f09SDavid van Moolenbroek 	dlz_drivers_clear();
1117*00b67f09SDavid van Moolenbroek #endif
1118*00b67f09SDavid van Moolenbroek #ifdef ISC_DLZ_DLOPEN
1119*00b67f09SDavid van Moolenbroek 	/*
1120*00b67f09SDavid van Moolenbroek 	 * Unregister "dlopen" DLZ driver.
1121*00b67f09SDavid van Moolenbroek 	 */
1122*00b67f09SDavid van Moolenbroek 	dlz_dlopen_clear();
1123*00b67f09SDavid van Moolenbroek #endif
1124*00b67f09SDavid van Moolenbroek 
1125*00b67f09SDavid van Moolenbroek 	dns_name_destroy();
1126*00b67f09SDavid van Moolenbroek 
1127*00b67f09SDavid van Moolenbroek 	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
1128*00b67f09SDavid van Moolenbroek 		      ISC_LOG_NOTICE, "exiting");
1129*00b67f09SDavid van Moolenbroek 	ns_log_shutdown();
1130*00b67f09SDavid van Moolenbroek }
1131*00b67f09SDavid van Moolenbroek 
1132*00b67f09SDavid van Moolenbroek static char *memstats = NULL;
1133*00b67f09SDavid van Moolenbroek 
1134*00b67f09SDavid van Moolenbroek void
ns_main_setmemstats(const char * filename)1135*00b67f09SDavid van Moolenbroek ns_main_setmemstats(const char *filename) {
1136*00b67f09SDavid van Moolenbroek 	/*
1137*00b67f09SDavid van Moolenbroek 	 * Caller has to ensure locking.
1138*00b67f09SDavid van Moolenbroek 	 */
1139*00b67f09SDavid van Moolenbroek 
1140*00b67f09SDavid van Moolenbroek 	if (memstats != NULL) {
1141*00b67f09SDavid van Moolenbroek 		free(memstats);
1142*00b67f09SDavid van Moolenbroek 		memstats = NULL;
1143*00b67f09SDavid van Moolenbroek 	}
1144*00b67f09SDavid van Moolenbroek 	if (filename == NULL)
1145*00b67f09SDavid van Moolenbroek 		return;
1146*00b67f09SDavid van Moolenbroek 	memstats = malloc(strlen(filename) + 1);
1147*00b67f09SDavid van Moolenbroek 	if (memstats)
1148*00b67f09SDavid van Moolenbroek 		strcpy(memstats, filename);
1149*00b67f09SDavid van Moolenbroek }
1150*00b67f09SDavid van Moolenbroek 
1151*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
1152*00b67f09SDavid van Moolenbroek /*
1153*00b67f09SDavid van Moolenbroek  * Get FMRI for the named process.
1154*00b67f09SDavid van Moolenbroek  */
1155*00b67f09SDavid van Moolenbroek isc_result_t
ns_smf_get_instance(char ** ins_name,int debug,isc_mem_t * mctx)1156*00b67f09SDavid van Moolenbroek ns_smf_get_instance(char **ins_name, int debug, isc_mem_t *mctx) {
1157*00b67f09SDavid van Moolenbroek 	scf_handle_t *h = NULL;
1158*00b67f09SDavid van Moolenbroek 	int namelen;
1159*00b67f09SDavid van Moolenbroek 	char *instance;
1160*00b67f09SDavid van Moolenbroek 
1161*00b67f09SDavid van Moolenbroek 	REQUIRE(ins_name != NULL && *ins_name == NULL);
1162*00b67f09SDavid van Moolenbroek 
1163*00b67f09SDavid van Moolenbroek 	if ((h = scf_handle_create(SCF_VERSION)) == NULL) {
1164*00b67f09SDavid van Moolenbroek 		if (debug)
1165*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1166*00b67f09SDavid van Moolenbroek 					 "scf_handle_create() failed: %s",
1167*00b67f09SDavid van Moolenbroek 					 scf_strerror(scf_error()));
1168*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1169*00b67f09SDavid van Moolenbroek 	}
1170*00b67f09SDavid van Moolenbroek 
1171*00b67f09SDavid van Moolenbroek 	if (scf_handle_bind(h) == -1) {
1172*00b67f09SDavid van Moolenbroek 		if (debug)
1173*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1174*00b67f09SDavid van Moolenbroek 					 "scf_handle_bind() failed: %s",
1175*00b67f09SDavid van Moolenbroek 					 scf_strerror(scf_error()));
1176*00b67f09SDavid van Moolenbroek 		scf_handle_destroy(h);
1177*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1178*00b67f09SDavid van Moolenbroek 	}
1179*00b67f09SDavid van Moolenbroek 
1180*00b67f09SDavid van Moolenbroek 	if ((namelen = scf_myname(h, NULL, 0)) == -1) {
1181*00b67f09SDavid van Moolenbroek 		if (debug)
1182*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1183*00b67f09SDavid van Moolenbroek 					 "scf_myname() failed: %s",
1184*00b67f09SDavid van Moolenbroek 					 scf_strerror(scf_error()));
1185*00b67f09SDavid van Moolenbroek 		scf_handle_destroy(h);
1186*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1187*00b67f09SDavid van Moolenbroek 	}
1188*00b67f09SDavid van Moolenbroek 
1189*00b67f09SDavid van Moolenbroek 	if ((instance = isc_mem_allocate(mctx, namelen + 1)) == NULL) {
1190*00b67f09SDavid van Moolenbroek 		UNEXPECTED_ERROR(__FILE__, __LINE__,
1191*00b67f09SDavid van Moolenbroek 				 "ns_smf_get_instance memory "
1192*00b67f09SDavid van Moolenbroek 				 "allocation failed: %s",
1193*00b67f09SDavid van Moolenbroek 				 isc_result_totext(ISC_R_NOMEMORY));
1194*00b67f09SDavid van Moolenbroek 		scf_handle_destroy(h);
1195*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1196*00b67f09SDavid van Moolenbroek 	}
1197*00b67f09SDavid van Moolenbroek 
1198*00b67f09SDavid van Moolenbroek 	if (scf_myname(h, instance, namelen + 1) == -1) {
1199*00b67f09SDavid van Moolenbroek 		if (debug)
1200*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1201*00b67f09SDavid van Moolenbroek 					 "scf_myname() failed: %s",
1202*00b67f09SDavid van Moolenbroek 					 scf_strerror(scf_error()));
1203*00b67f09SDavid van Moolenbroek 		scf_handle_destroy(h);
1204*00b67f09SDavid van Moolenbroek 		isc_mem_free(mctx, instance);
1205*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
1206*00b67f09SDavid van Moolenbroek 	}
1207*00b67f09SDavid van Moolenbroek 
1208*00b67f09SDavid van Moolenbroek 	scf_handle_destroy(h);
1209*00b67f09SDavid van Moolenbroek 	*ins_name = instance;
1210*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
1211*00b67f09SDavid van Moolenbroek }
1212*00b67f09SDavid van Moolenbroek #endif /* HAVE_LIBSCF */
1213*00b67f09SDavid van Moolenbroek 
1214*00b67f09SDavid van Moolenbroek /* main entry point, possibly hooked */
1215*00b67f09SDavid van Moolenbroek 
1216*00b67f09SDavid van Moolenbroek int
main(int argc,char * argv[])1217*00b67f09SDavid van Moolenbroek main(int argc, char *argv[]) {
1218*00b67f09SDavid van Moolenbroek 	isc_result_t result;
1219*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
1220*00b67f09SDavid van Moolenbroek 	char *instance = NULL;
1221*00b67f09SDavid van Moolenbroek #endif
1222*00b67f09SDavid van Moolenbroek 
1223*00b67f09SDavid van Moolenbroek #ifdef HAVE_GPERFTOOLS_PROFILER
1224*00b67f09SDavid van Moolenbroek 	(void) ProfilerStart(NULL);
1225*00b67f09SDavid van Moolenbroek #endif
1226*00b67f09SDavid van Moolenbroek 
1227*00b67f09SDavid van Moolenbroek 	/*
1228*00b67f09SDavid van Moolenbroek 	 * Record version in core image.
1229*00b67f09SDavid van Moolenbroek 	 * strings named.core | grep "named version:"
1230*00b67f09SDavid van Moolenbroek 	 */
1231*00b67f09SDavid van Moolenbroek 	strlcat(version,
1232*00b67f09SDavid van Moolenbroek #if defined(NO_VERSION_DATE) || !defined(__DATE__)
1233*00b67f09SDavid van Moolenbroek 		"named version: BIND " VERSION " <" SRCID ">",
1234*00b67f09SDavid van Moolenbroek #else
1235*00b67f09SDavid van Moolenbroek 		"named version: BIND " VERSION " <" SRCID "> (" __DATE__ ")",
1236*00b67f09SDavid van Moolenbroek #endif
1237*00b67f09SDavid van Moolenbroek 		sizeof(version));
1238*00b67f09SDavid van Moolenbroek 	result = isc_file_progname(*argv, program_name, sizeof(program_name));
1239*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1240*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("program name too long");
1241*00b67f09SDavid van Moolenbroek 
1242*00b67f09SDavid van Moolenbroek 	if (strcmp(program_name, "lwresd") == 0)
1243*00b67f09SDavid van Moolenbroek 		ns_g_lwresdonly = ISC_TRUE;
1244*00b67f09SDavid van Moolenbroek 
1245*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1246*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("failed to build internal symbol table");
1247*00b67f09SDavid van Moolenbroek 
1248*00b67f09SDavid van Moolenbroek 	isc_assertion_setcallback(assertion_failed);
1249*00b67f09SDavid van Moolenbroek 	isc_error_setfatal(library_fatal_error);
1250*00b67f09SDavid van Moolenbroek 	isc_error_setunexpected(library_unexpected_error);
1251*00b67f09SDavid van Moolenbroek 
1252*00b67f09SDavid van Moolenbroek 	ns_os_init(program_name);
1253*00b67f09SDavid van Moolenbroek 
1254*00b67f09SDavid van Moolenbroek 	dns_result_register();
1255*00b67f09SDavid van Moolenbroek 	dst_result_register();
1256*00b67f09SDavid van Moolenbroek 	isccc_result_register();
1257*00b67f09SDavid van Moolenbroek #ifdef PKCS11CRYPTO
1258*00b67f09SDavid van Moolenbroek 	pk11_result_register();
1259*00b67f09SDavid van Moolenbroek #endif
1260*00b67f09SDavid van Moolenbroek 
1261*00b67f09SDavid van Moolenbroek 	parse_command_line(argc, argv);
1262*00b67f09SDavid van Moolenbroek 
1263*00b67f09SDavid van Moolenbroek 	pfilter_open();
1264*00b67f09SDavid van Moolenbroek 
1265*00b67f09SDavid van Moolenbroek 	/*
1266*00b67f09SDavid van Moolenbroek 	 * Warn about common configuration error.
1267*00b67f09SDavid van Moolenbroek 	 */
1268*00b67f09SDavid van Moolenbroek 	if (ns_g_chrootdir != NULL) {
1269*00b67f09SDavid van Moolenbroek 		int len = strlen(ns_g_chrootdir);
1270*00b67f09SDavid van Moolenbroek 		if (strncmp(ns_g_chrootdir, ns_g_conffile, len) == 0 &&
1271*00b67f09SDavid van Moolenbroek 		    (ns_g_conffile[len] == '/' || ns_g_conffile[len] == '\\'))
1272*00b67f09SDavid van Moolenbroek 			ns_main_earlywarning("config filename (-c %s) contains "
1273*00b67f09SDavid van Moolenbroek 					     "chroot path (-t %s)",
1274*00b67f09SDavid van Moolenbroek 					     ns_g_conffile, ns_g_chrootdir);
1275*00b67f09SDavid van Moolenbroek 	}
1276*00b67f09SDavid van Moolenbroek 
1277*00b67f09SDavid van Moolenbroek 	result = isc_mem_create(0, 0, &ns_g_mctx);
1278*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
1279*00b67f09SDavid van Moolenbroek 		ns_main_earlyfatal("isc_mem_create() failed: %s",
1280*00b67f09SDavid van Moolenbroek 				   isc_result_totext(result));
1281*00b67f09SDavid van Moolenbroek 	isc_mem_setname(ns_g_mctx, "main", NULL);
1282*00b67f09SDavid van Moolenbroek 
1283*00b67f09SDavid van Moolenbroek 	setup();
1284*00b67f09SDavid van Moolenbroek 
1285*00b67f09SDavid van Moolenbroek 	/*
1286*00b67f09SDavid van Moolenbroek 	 * Start things running and then wait for a shutdown request
1287*00b67f09SDavid van Moolenbroek 	 * or reload.
1288*00b67f09SDavid van Moolenbroek 	 */
1289*00b67f09SDavid van Moolenbroek 	do {
1290*00b67f09SDavid van Moolenbroek 		result = isc_app_run();
1291*00b67f09SDavid van Moolenbroek 
1292*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_RELOAD) {
1293*00b67f09SDavid van Moolenbroek 			ns_server_reloadwanted(ns_g_server);
1294*00b67f09SDavid van Moolenbroek 		} else if (result != ISC_R_SUCCESS) {
1295*00b67f09SDavid van Moolenbroek 			UNEXPECTED_ERROR(__FILE__, __LINE__,
1296*00b67f09SDavid van Moolenbroek 					 "isc_app_run(): %s",
1297*00b67f09SDavid van Moolenbroek 					 isc_result_totext(result));
1298*00b67f09SDavid van Moolenbroek 			/*
1299*00b67f09SDavid van Moolenbroek 			 * Force exit.
1300*00b67f09SDavid van Moolenbroek 			 */
1301*00b67f09SDavid van Moolenbroek 			result = ISC_R_SUCCESS;
1302*00b67f09SDavid van Moolenbroek 		}
1303*00b67f09SDavid van Moolenbroek 	} while (result != ISC_R_SUCCESS);
1304*00b67f09SDavid van Moolenbroek 
1305*00b67f09SDavid van Moolenbroek #ifdef HAVE_LIBSCF
1306*00b67f09SDavid van Moolenbroek 	if (ns_smf_want_disable == 1) {
1307*00b67f09SDavid van Moolenbroek 		result = ns_smf_get_instance(&instance, 1, ns_g_mctx);
1308*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS && instance != NULL) {
1309*00b67f09SDavid van Moolenbroek 			if (smf_disable_instance(instance, 0) != 0)
1310*00b67f09SDavid van Moolenbroek 				UNEXPECTED_ERROR(__FILE__, __LINE__,
1311*00b67f09SDavid van Moolenbroek 						 "smf_disable_instance() "
1312*00b67f09SDavid van Moolenbroek 						 "failed for %s : %s",
1313*00b67f09SDavid van Moolenbroek 						 instance,
1314*00b67f09SDavid van Moolenbroek 						 scf_strerror(scf_error()));
1315*00b67f09SDavid van Moolenbroek 		}
1316*00b67f09SDavid van Moolenbroek 		if (instance != NULL)
1317*00b67f09SDavid van Moolenbroek 			isc_mem_free(ns_g_mctx, instance);
1318*00b67f09SDavid van Moolenbroek 	}
1319*00b67f09SDavid van Moolenbroek #endif /* HAVE_LIBSCF */
1320*00b67f09SDavid van Moolenbroek 
1321*00b67f09SDavid van Moolenbroek 	cleanup();
1322*00b67f09SDavid van Moolenbroek 
1323*00b67f09SDavid van Moolenbroek 	if (want_stats) {
1324*00b67f09SDavid van Moolenbroek 		isc_mem_stats(ns_g_mctx, stdout);
1325*00b67f09SDavid van Moolenbroek 		isc_mutex_stats(stdout);
1326*00b67f09SDavid van Moolenbroek 	}
1327*00b67f09SDavid van Moolenbroek 
1328*00b67f09SDavid van Moolenbroek 	if (ns_g_memstatistics && memstats != NULL) {
1329*00b67f09SDavid van Moolenbroek 		FILE *fp = NULL;
1330*00b67f09SDavid van Moolenbroek 		result = isc_stdio_open(memstats, "w", &fp);
1331*00b67f09SDavid van Moolenbroek 		if (result == ISC_R_SUCCESS) {
1332*00b67f09SDavid van Moolenbroek 			isc_mem_stats(ns_g_mctx, fp);
1333*00b67f09SDavid van Moolenbroek 			isc_mutex_stats(fp);
1334*00b67f09SDavid van Moolenbroek 			isc_stdio_close(fp);
1335*00b67f09SDavid van Moolenbroek 		}
1336*00b67f09SDavid van Moolenbroek 	}
1337*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&ns_g_mctx);
1338*00b67f09SDavid van Moolenbroek 	isc_mem_checkdestroyed(stderr);
1339*00b67f09SDavid van Moolenbroek 
1340*00b67f09SDavid van Moolenbroek 	ns_main_setmemstats(NULL);
1341*00b67f09SDavid van Moolenbroek 
1342*00b67f09SDavid van Moolenbroek 	isc_app_finish();
1343*00b67f09SDavid van Moolenbroek 
1344*00b67f09SDavid van Moolenbroek 	ns_os_closedevnull();
1345*00b67f09SDavid van Moolenbroek 
1346*00b67f09SDavid van Moolenbroek 	ns_os_shutdown();
1347*00b67f09SDavid van Moolenbroek 
1348*00b67f09SDavid van Moolenbroek #ifdef HAVE_GPERFTOOLS_PROFILER
1349*00b67f09SDavid van Moolenbroek 	ProfilerStop();
1350*00b67f09SDavid van Moolenbroek #endif
1351*00b67f09SDavid van Moolenbroek 
1352*00b67f09SDavid van Moolenbroek 	return (0);
1353*00b67f09SDavid van Moolenbroek }
1354