main.c 37.5 KB
Newer Older
Bob Halley's avatar
add    
Bob Halley committed
1
/*
2
 * Copyright (C) 1999-2016  Internet Systems Consortium, Inc. ("ISC")
3
 *
4
5
6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
Bob Halley's avatar
add    
Bob Halley committed
7
8
 */

9
/*! \file */
David Lawrence's avatar
David Lawrence committed
10

Bob Halley's avatar
add    
Bob Halley committed
11
12
#include <config.h>

13
#include <ctype.h>
Bob Halley's avatar
add    
Bob Halley committed
14
#include <stdlib.h>
15
#include <string.h>
Bob Halley's avatar
add    
Bob Halley committed
16
17

#include <isc/app.h>
18
#include <isc/backtrace.h>
19
#include <isc/commandline.h>
20
#include <isc/dir.h>
21
#include <isc/entropy.h>
22
#include <isc/file.h>
23
#include <isc/hash.h>
24
#include <isc/httpd.h>
25
#include <isc/os.h>
26
#include <isc/platform.h>
27
#include <isc/print.h>
28
#include <isc/resource.h>
29
#include <isc/stdio.h>
30
#include <isc/string.h>
Bob Halley's avatar
add    
Bob Halley committed
31
32
#include <isc/task.h>
#include <isc/timer.h>
Bob Halley's avatar
Bob Halley committed
33
#include <isc/util.h>
Bob Halley's avatar
add    
Bob Halley committed
34

35
36
#include <isccc/result.h>

37
#include <dns/dispatch.h>
Evan Hunt's avatar
Evan Hunt committed
38
#include <dns/dyndb.h>
39
#include <dns/name.h>
40
#include <dns/result.h>
41
#include <dns/resolver.h>
David Lawrence's avatar
David Lawrence committed
42
#include <dns/view.h>
Bob Halley's avatar
add    
Bob Halley committed
43

44
#include <dst/result.h>
45
46
47
#ifdef PKCS11CRYPTO
#include <pk11/result.h>
#endif
48

49
50
#include <dlz/dlz_dlopen_driver.h>

51
52
53
54
#ifdef HAVE_GPERFTOOLS_PROFILER
#include <gperftools/profiler.h>
#endif

55

56
/*
57
 * Defining NS_MAIN provides storage declarations (rather than extern)
58
59
 * for variables in named/globals.h.
 */
60
#define NS_MAIN 1
Bob Halley's avatar
add    
Bob Halley committed
61

62
#include <named/builtin.h>
63
#include <named/control.h>
64
#include <named/fuzz.h>
65
#include <named/globals.h>	/* Explicit, though named/log.h includes it. */
Bob Halley's avatar
add    
Bob Halley committed
66
#include <named/interfacemgr.h>
67
#include <named/log.h>
Bob Halley's avatar
Bob Halley committed
68
#include <named/os.h>
Bob Halley's avatar
add    
Bob Halley committed
69
#include <named/server.h>
70
#include <named/lwresd.h>
Bob Halley's avatar
Bob Halley committed
71
#include <named/main.h>
72
#include <named/seccomp.h>
73
74
75
#ifdef HAVE_LIBSCF
#include <named/ns_smf_globals.h>
#endif
Bob Halley's avatar
add    
Bob Halley committed
76

77
78
#ifdef OPENSSL
#include <openssl/opensslv.h>
79
#include <openssl/crypto.h>
80
81
82
83
#endif
#ifdef HAVE_LIBXML2
#include <libxml/xmlversion.h>
#endif
84
85
86
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
87
88
89
/*
 * Include header files for database drivers here.
 */
90
/* #include "xxdb.h" */
91

92
#ifdef CONTRIB_DLZ
93
/*
94
 * Include contributed DLZ drivers if appropriate.
95
96
97
98
 */
#include <dlz/dlz_drivers.h>
#endif

99
100
101
102
103
104
105
/*
 * The maximum number of stack frames to dump on assertion failure.
 */
#ifndef BACKTRACE_MAXFRAME
#define BACKTRACE_MAXFRAME 128
#endif

106
107
108
109
LIBISC_EXTERNAL_DATA extern int isc_dscp_check_value;
LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_hour;
LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_day;
LIBDNS_EXTERNAL_DATA extern unsigned int dns_zone_mkey_month;
Evan Hunt's avatar
Evan Hunt committed
110

David Lawrence's avatar
David Lawrence committed
111
static isc_boolean_t	want_stats = ISC_FALSE;
112
113
static char		program_name[ISC_DIR_NAMEMAX] = "named";
static char		absolute_conffile[ISC_DIR_PATHMAX];
114
115
static char		saved_command_line[512];
static char		version[512];
116
static unsigned int	maxsocks = 0;
117
static int		maxudp = 0;
Bob Halley's avatar
add    
Bob Halley committed
118

119
void
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
ns_main_earlywarning(const char *format, ...) {
	va_list args;

	va_start(args, format);
	if (ns_g_lctx != NULL) {
		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
			       format, args);
	} else {
		fprintf(stderr, "%s: ", program_name);
		vfprintf(stderr, format, args);
		fprintf(stderr, "\n");
		fflush(stderr);
	}
	va_end(args);
}

Bob Halley's avatar
Bob Halley committed
137
138
void
ns_main_earlyfatal(const char *format, ...) {
Bob Halley's avatar
add    
Bob Halley committed
139
140
141
	va_list args;

	va_start(args, format);
142
143
144
145
	if (ns_g_lctx != NULL) {
		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			       format, args);
Bob Halley's avatar
Bob Halley committed
146
147
148
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			       "exiting (due to early fatal error)");
149
	} else {
150
		fprintf(stderr, "%s: ", program_name);
151
152
		vfprintf(stderr, format, args);
		fprintf(stderr, "\n");
153
		fflush(stderr);
154
	}
Bob Halley's avatar
add    
Bob Halley committed
155
156
157
158
159
	va_end(args);

	exit(1);
}

Francis Dupont's avatar
Francis Dupont committed
160
161
162
163
ISC_PLATFORM_NORETURN_PRE static void
assertion_failed(const char *file, int line, isc_assertiontype_t type,
		 const char *cond) ISC_PLATFORM_NORETURN_POST;

164
static void
David Lawrence's avatar
David Lawrence committed
165
166
167
assertion_failed(const char *file, int line, isc_assertiontype_t type,
		 const char *cond)
{
168
169
170
171
172
173
	void *tracebuf[BACKTRACE_MAXFRAME];
	int i, nframes;
	isc_result_t result;
	const char *logsuffix = "";
	const char *fname;

174
175
176
177
178
	/*
	 * Handle assertion failures.
	 */

	if (ns_g_lctx != NULL) {
179
		/*
Francis Dupont's avatar
Francis Dupont committed
180
		 * Reset the assertion callback in case it is the log
181
182
183
184
		 * routines causing the assertion.
		 */
		isc_assertion_setcallback(NULL);

185
186
187
188
		result = isc_backtrace_gettrace(tracebuf, BACKTRACE_MAXFRAME,
						&nframes);
		if (result == ISC_R_SUCCESS && nframes > 0)
			logsuffix = ", back trace";
189
190
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
			      "%s:%d: %s(%s) failed%s", file, line,
			      isc_assertion_typetotext(type), cond, logsuffix);
		if (result == ISC_R_SUCCESS) {
			for (i = 0; i < nframes; i++) {
				unsigned long offset;

				fname = NULL;
				result = isc_backtrace_getsymbol(tracebuf[i],
								 &fname,
								 &offset);
				if (result == ISC_R_SUCCESS) {
					isc_log_write(ns_g_lctx,
						      NS_LOGCATEGORY_GENERAL,
						      NS_LOGMODULE_MAIN,
						      ISC_LOG_CRITICAL,
						      "#%d %p in %s()+0x%lx", i,
						      tracebuf[i], fname,
						      offset);
				} else {
					isc_log_write(ns_g_lctx,
						      NS_LOGCATEGORY_GENERAL,
						      NS_LOGMODULE_MAIN,
						      ISC_LOG_CRITICAL,
						      "#%d %p in ??", i,
						      tracebuf[i]);
				}
			}
		}
219
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
220
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
221
			      "exiting (due to assertion failure)");
222
223
224
225
226
227
228
229
230
231
232
	} else {
		fprintf(stderr, "%s:%d: %s(%s) failed\n",
			file, line, isc_assertion_typetotext(type), cond);
		fflush(stderr);
	}

	if (ns_g_coreok)
		abort();
	exit(1);
}

Francis Dupont's avatar
Francis Dupont committed
233
ISC_PLATFORM_NORETURN_PRE static void
234
library_fatal_error(const char *file, int line, const char *format,
Francis Dupont's avatar
Francis Dupont committed
235
236
		    va_list args)
ISC_FORMAT_PRINTF(3, 0) ISC_PLATFORM_NORETURN_POST;
237

238
static void
David Lawrence's avatar
David Lawrence committed
239
240
241
library_fatal_error(const char *file, int line, const char *format,
		    va_list args)
{
242
243
244
245
246
	/*
	 * Handle isc_error_fatal() calls from our libraries.
	 */

	if (ns_g_lctx != NULL) {
247
248
249
250
251
252
		/*
		 * Reset the error callback in case it is the log
		 * routines causing the assertion.
		 */
		isc_error_setfatal(NULL);

253
254
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
255
			      "%s:%d: fatal error:", file, line);
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			       format, args);
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			      "exiting (due to fatal error in library)");
	} else {
		fprintf(stderr, "%s:%d: fatal error: ", file, line);
		vfprintf(stderr, format, args);
		fprintf(stderr, "\n");
		fflush(stderr);
	}

	if (ns_g_coreok)
		abort();
	exit(1);
}

274
275
276
277
static void
library_unexpected_error(const char *file, int line, const char *format,
			 va_list args) ISC_FORMAT_PRINTF(3, 0);

278
static void
David Lawrence's avatar
David Lawrence committed
279
280
281
library_unexpected_error(const char *file, int line, const char *format,
			 va_list args)
{
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
	/*
	 * Handle isc_error_unexpected() calls from our libraries.
	 */

	if (ns_g_lctx != NULL) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
			      "%s:%d: unexpected error:", file, line);
		isc_log_vwrite(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_ERROR,
			       format, args);
	} else {
		fprintf(stderr, "%s:%d: fatal error: ", file, line);
		vfprintf(stderr, format, args);
		fprintf(stderr, "\n");
		fflush(stderr);
	}
}

301
302
303
static void
lwresd_usage(void) {
	fprintf(stderr,
Mark Andrews's avatar
Mark Andrews committed
304
		"usage: lwresd [-4|-6] [-c conffile | -C resolvconffile] "
Mark Andrews's avatar
Mark Andrews committed
305
306
		"[-d debuglevel] [-f|-g]\n"
		"              [-i pidfile] [-n number_of_cpus] "
307
		"[-p port] [-P listen-port]\n"
Mark Andrews's avatar
Mark Andrews committed
308
309
310
311
		"              [-s] [-S sockets] [-t chrootdir] [-u username] "
		"[-U listeners]\n"
		"              [-m {usage|trace|record|size|mctx}]\n"
		"usage: lwresd [-v|-V]\n");
312
313
}

Bob Halley's avatar
add    
Bob Halley committed
314
315
static void
usage(void) {
316
317
318
319
	if (ns_g_lwresdonly) {
		lwresd_usage();
		return;
	}
Bob Halley's avatar
add    
Bob Halley committed
320
	fprintf(stderr,
Mark Andrews's avatar
Mark Andrews committed
321
		"usage: named [-4|-6] [-c conffile] [-d debuglevel] "
Francis Dupont's avatar
Francis Dupont committed
322
323
		"[-E engine] [-f|-g]\n"
		"             [-n number_of_cpus] [-p port] [-s] "
Mark Andrews's avatar
Mark Andrews committed
324
325
326
327
		"[-S sockets] [-t chrootdir]\n"
		"             [-u username] [-U listeners] "
		"[-m {usage|trace|record|size|mctx}]\n"
		"usage: named [-v|-V]\n");
Bob Halley's avatar
add    
Bob Halley committed
328
329
}

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
static void
save_command_line(int argc, char *argv[]) {
	int i;
	char *src;
	char *dst;
	char *eob;
	const char truncated[] = "...";
	isc_boolean_t quoted = ISC_FALSE;

	dst = saved_command_line;
	eob = saved_command_line + sizeof(saved_command_line);

	for (i = 1; i < argc && dst < eob; i++) {
		*dst++ = ' ';

		src = argv[i];
		while (*src != '\0' && dst < eob) {
			/*
			 * This won't perfectly produce a shell-independent
			 * pastable command line in all circumstances, but
			 * comes close, and for practical purposes will
			 * nearly always be fine.
			 */
			if (quoted || isalnum(*src & 0xff) ||
			    *src == '-' || *src == '_' ||
			    *src == '.' || *src == '/') {
				*dst++ = *src++;
				quoted = ISC_FALSE;
			} else {
				*dst++ = '\\';
				quoted = ISC_TRUE;
			}
		}
	}

	INSIST(sizeof(saved_command_line) >= sizeof(truncated));

	if (dst == eob)
		strcpy(eob - sizeof(truncated), truncated);
	else
		*dst = '\0';
}

373
374
375
376
377
378
static int
parse_int(char *arg, const char *desc) {
	char *endp;
	int tmp;
	long int ltmp;

379
	ltmp = strtol(arg, &endp, 10);
380
381
382
383
384
385
386
387
	tmp = (int) ltmp;
	if (*endp != '\0')
		ns_main_earlyfatal("%s '%s' must be numeric", desc, arg);
	if (tmp < 0 || tmp != ltmp)
		ns_main_earlyfatal("%s '%s' out of range", desc, arg);
	return (tmp);
}

388
389
390
391
static struct flag_def {
	const char *name;
	unsigned int value;
} mem_debug_flags[] = {
392
	{ "none", 0},
393
394
	{ "trace",  ISC_MEM_DEBUGTRACE },
	{ "record", ISC_MEM_DEBUGRECORD },
Mark Andrews's avatar
Mark Andrews committed
395
	{ "usage", ISC_MEM_DEBUGUSAGE },
396
397
	{ "size", ISC_MEM_DEBUGSIZE },
	{ "mctx", ISC_MEM_DEBUGCTX },
398
399
400
401
402
	{ NULL, 0 }
};

static void
set_flags(const char *arg, struct flag_def *defs, unsigned int *ret) {
403
404
	isc_boolean_t clear = ISC_FALSE;

405
406
407
	for (;;) {
		const struct flag_def *def;
		const char *end = strchr(arg, ',');
Mark Andrews's avatar
Mark Andrews committed
408
		int arglen;
409
410
		if (end == NULL)
			end = arg + strlen(arg);
411
		arglen = (int)(end - arg);
412
		for (def = defs; def->name != NULL; def++) {
Mark Andrews's avatar
Mark Andrews committed
413
414
			if (arglen == (int)strlen(def->name) &&
			    memcmp(arg, def->name, arglen) == 0) {
415
416
				if (def->value == 0)
					clear = ISC_TRUE;
417
418
419
420
				*ret |= def->value;
				goto found;
			}
		}
Mark Andrews's avatar
Mark Andrews committed
421
		ns_main_earlyfatal("unrecognized flag '%.*s'", arglen, arg);
422
	 found:
423
		if (clear || (*end == '\0'))
424
425
426
			break;
		arg = end + 1;
	}
427
428
429

	if (clear)
		*ret = 0;
430
431
}

432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
static void
parse_fuzz_arg(void) {
	if (!strncmp(isc_commandline_argument, "client:", 7)) {
		ns_g_fuzz_named_addr = isc_commandline_argument + 7;
		ns_g_fuzz_type = ns_fuzz_client;
	} else if (!strncmp(isc_commandline_argument, "tcp:", 4)) {
		ns_g_fuzz_named_addr = isc_commandline_argument + 4;
		ns_g_fuzz_type = ns_fuzz_tcpclient;
	} else if (!strncmp(isc_commandline_argument, "resolver:", 9)) {
		ns_g_fuzz_named_addr = isc_commandline_argument + 9;
		ns_g_fuzz_type = ns_fuzz_resolver;
	} else if (!strncmp(isc_commandline_argument, "http:", 5)) {
		ns_g_fuzz_named_addr = isc_commandline_argument + 5;
		ns_g_fuzz_type = ns_fuzz_http;
	} else if (!strncmp(isc_commandline_argument, "rndc:", 5)) {
		ns_g_fuzz_named_addr = isc_commandline_argument + 5;
		ns_g_fuzz_type = ns_fuzz_rndc;
	} else {
		ns_main_earlyfatal("unknown fuzzing type '%s'",
				   isc_commandline_argument);
	}
}

455
static void
Bob Halley's avatar
add    
Bob Halley committed
456
457
parse_command_line(int argc, char *argv[]) {
	int ch;
458
	int port;
459
	const char *p;
460

461
462
	save_command_line(argc, argv);

463
464
465
466
	/*
	 * NS_MAIN_ARGS is defined in main.h, so that it can be used
	 * both by named and by ntservice hooks.
	 */
467
	isc_commandline_errprint = ISC_FALSE;
468
	while ((ch = isc_commandline_parse(argc, argv, NS_MAIN_ARGS)) != -1) {
Bob Halley's avatar
add    
Bob Halley committed
469
		switch (ch) {
470
		case '4':
471
			if (ns_g_disable4)
472
473
474
475
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv4 not supported by OS");
			isc_net_disableipv6();
476
			ns_g_disable6 = ISC_TRUE;
477
478
			break;
		case '6':
479
			if (ns_g_disable6)
480
481
482
483
				ns_main_earlyfatal("cannot specify -4 and -6");
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				ns_main_earlyfatal("IPv6 not supported by OS");
			isc_net_disableipv4();
484
			ns_g_disable4 = ISC_TRUE;
485
			break;
486
487
488
		case 'A':
			parse_fuzz_arg();
			break;
Bob Halley's avatar
add    
Bob Halley committed
489
		case 'c':
490
			ns_g_conffile = isc_commandline_argument;
491
			lwresd_g_conffile = isc_commandline_argument;
492
493
494
			if (lwresd_g_useresolvconf)
				ns_main_earlyfatal("cannot specify -c and -C");
			ns_g_conffileset = ISC_TRUE;
495
496
497
			break;
		case 'C':
			lwresd_g_resolvconffile = isc_commandline_argument;
498
499
			if (ns_g_conffileset)
				ns_main_earlyfatal("cannot specify -c and -C");
500
			lwresd_g_useresolvconf = ISC_TRUE;
Bob Halley's avatar
add    
Bob Halley committed
501
			break;
Bob Halley's avatar
Bob Halley committed
502
		case 'd':
503
504
			ns_g_debuglevel = parse_int(isc_commandline_argument,
						    "debug level");
Bob Halley's avatar
Bob Halley committed
505
			break;
506
507
508
		case 'D':
			/* Descriptive comment for 'ps'. */
			break;
Francis Dupont's avatar
Francis Dupont committed
509
510
511
		case 'E':
			ns_g_engine = isc_commandline_argument;
			break;
512
513
514
		case 'f':
			ns_g_foreground = ISC_TRUE;
			break;
515
516
517
518
		case 'g':
			ns_g_foreground = ISC_TRUE;
			ns_g_logstderr = ISC_TRUE;
			break;
519
520
521
522
523
524
525
		/* XXXBEW -i should be removed */
		case 'i':
			lwresd_g_defaultpidfile = isc_commandline_argument;
			break;
		case 'l':
			ns_g_lwresdonly = ISC_TRUE;
			break;
526
527
528
		case 'L':
			ns_g_logfile = isc_commandline_argument;
			break;
529
530
531
532
		case 'M':
			if (strcmp(isc_commandline_argument, "external") == 0)
				isc_mem_defaultflags = 0;
			break;
533
534
535
536
		case 'm':
			set_flags(isc_commandline_argument, mem_debug_flags,
				  &isc_mem_debugging);
			break;
537
538
		case 'N': /* Deprecated. */
		case 'n':
539
540
			ns_g_cpus = parse_int(isc_commandline_argument,
					      "number of cpus");
Bob Halley's avatar
add    
Bob Halley committed
541
542
543
			if (ns_g_cpus == 0)
				ns_g_cpus = 1;
			break;
Bob Halley's avatar
Bob Halley committed
544
		case 'p':
545
			port = parse_int(isc_commandline_argument, "port");
546
			if (port < 1 || port > 65535)
547
				ns_main_earlyfatal("port '%s' out of range",
548
549
						   isc_commandline_argument);
			ns_g_port = port;
Bob Halley's avatar
Bob Halley committed
550
			break;
551
552
553
554
555
556
557
558
		/* XXXBEW Should -P be removed? */
		case 'P':
			port = parse_int(isc_commandline_argument, "port");
			if (port < 1 || port > 65535)
				ns_main_earlyfatal("port '%s' out of range",
						   isc_commandline_argument);
			lwresd_g_listenport = port;
			break;
Bob Halley's avatar
add    
Bob Halley committed
559
560
561
562
		case 's':
			/* XXXRTH temporary syntax */
			want_stats = ISC_TRUE;
			break;
563
564
565
566
		case 'S':
			maxsocks = parse_int(isc_commandline_argument,
					     "max number of sockets");
			break;
567
		case 't':
568
			/* XXXJAB should we make a copy? */
569
570
			ns_g_chrootdir = isc_commandline_argument;
			break;
Mark Andrews's avatar
Mark Andrews committed
571
		case 'T':	/* NOT DOCUMENTED */
572
			/*
Evan Hunt's avatar
Evan Hunt committed
573
574
575
			 * force the server to behave (or misbehave) in
			 * specified ways for testing purposes.
			 *
576
577
			 * clienttest: make clients single shot with their
			 * 	       own memory context.
578
579
			 * delay=xxxx: delay client responses by xxxx ms to
			 *	       simulate remote servers.
Evan Hunt's avatar
Evan Hunt committed
580
581
			 * dscp=x:     check that dscp values are as
			 * 	       expected and assert otherwise.
582
			 */
583
			if (!strcmp(isc_commandline_argument, "clienttest"))
584
				ns_g_clienttest = ISC_TRUE;
585
586
			else if (!strcmp(isc_commandline_argument, "nosoa"))
				ns_g_nosoa = ISC_TRUE;
587
588
			else if (!strcmp(isc_commandline_argument, "noaa"))
				ns_g_noaa = ISC_TRUE;
589
590
591
592
			else if (!strcmp(isc_commandline_argument, "maxudp512"))
				maxudp = 512;
			else if (!strcmp(isc_commandline_argument, "maxudp1460"))
				maxudp = 1460;
593
594
595
596
597
598
599
			else if (!strcmp(isc_commandline_argument, "dropedns"))
				ns_g_dropedns = ISC_TRUE;
			else if (!strcmp(isc_commandline_argument, "noedns"))
				ns_g_noedns = ISC_TRUE;
			else if (!strncmp(isc_commandline_argument,
					  "maxudp=", 7))
				maxudp = atoi(isc_commandline_argument + 7);
600
601
602
			else if (!strncmp(isc_commandline_argument,
					  "delay=", 6))
				ns_g_delay = atoi(isc_commandline_argument + 6);
603
604
			else if (!strcmp(isc_commandline_argument, "nosyslog"))
				ns_g_nosyslog = ISC_TRUE;
605
606
			else if (!strcmp(isc_commandline_argument, "nonearest"))
				ns_g_nonearest = ISC_TRUE;
Evan Hunt's avatar
Evan Hunt committed
607
608
609
			else if (!strncmp(isc_commandline_argument, "dscp=", 5))
				isc_dscp_check_value =
					   atoi(isc_commandline_argument + 5);
Evan Hunt's avatar
Evan Hunt committed
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
			else if (!strncmp(isc_commandline_argument,
					  "mkeytimers=", 11))
			{
				p = strtok(isc_commandline_argument + 11, "/");
				if (p == NULL)
					ns_main_earlyfatal("bad mkeytimer");
				dns_zone_mkey_hour = atoi(p);
				if (dns_zone_mkey_hour == 0)
					ns_main_earlyfatal("bad mkeytimer");

				p = strtok(NULL, "/");
				if (p == NULL) {
					dns_zone_mkey_day =
						(24 * dns_zone_mkey_hour);
					dns_zone_mkey_month =
						(30 * dns_zone_mkey_day);
					break;
				}
				dns_zone_mkey_day = atoi(p);
				if (dns_zone_mkey_day < dns_zone_mkey_hour)
					ns_main_earlyfatal("bad mkeytimer");

				p = strtok(NULL, "/");
				if (p == NULL) {
					dns_zone_mkey_month =
						(30 * dns_zone_mkey_day);
					break;
				}
				dns_zone_mkey_month = atoi(p);
				if (dns_zone_mkey_month < dns_zone_mkey_day)
					ns_main_earlyfatal("bad mkeytimer");
			} else if (!strcmp(isc_commandline_argument, "notcp"))
642
				ns_g_notcp = ISC_TRUE;
643
644
645
			else if (!strncmp(isc_commandline_argument, "tat=", 4))
				ns_g_tat_interval =
					   atoi(isc_commandline_argument + 4);
646
647
648
649
			else
				fprintf(stderr, "unknown -T flag '%s\n",
					isc_commandline_argument);
			break;
650
651
652
653
654
		case 'U':
			ns_g_udpdisp = parse_int(isc_commandline_argument,
						 "number of UDP listeners "
						 "per interface");
			break;
655
656
657
		case 'u':
			ns_g_username = isc_commandline_argument;
			break;
658
		case 'v':
Evan Hunt's avatar
Evan Hunt committed
659
660
661
662
			printf("%s %s%s%s <id:%s>\n",
			       ns_g_product, ns_g_version,
			       (*ns_g_description != '\0') ? " " : "",
			       ns_g_description, ns_g_srcid);
663
			exit(0);
664
		case 'V':
Evan Hunt's avatar
Evan Hunt committed
665
666
667
			printf("%s %s%s%s <id:%s>\n", ns_g_product, ns_g_version,
			       (*ns_g_description != '\0') ? " " : "",
			       ns_g_description, ns_g_srcid);
668
			printf("running on %s\n", ns_os_uname());
Evan Hunt's avatar
Evan Hunt committed
669
			printf("built by %s with %s\n",
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
			       ns_g_builder, ns_g_configargs);
#ifdef __clang__
			printf("compiled by CLANG %s\n", __VERSION__);
#else
#if defined(__ICC) || defined(__INTEL_COMPILER)
			printf("compiled by ICC %s\n", __VERSION__);
#else
#ifdef __GNUC__
			printf("compiled by GCC %s\n", __VERSION__);
#endif
#endif
#endif
#ifdef _MSC_VER
			printf("compiled by MSVC %d\n", _MSC_VER);
#endif
#ifdef __SUNPRO_C
			printf("compiled by Solaris Studio %x\n", __SUNPRO_C);
#endif
688
#ifdef OPENSSL
689
			printf("compiled with OpenSSL version: %s\n",
690
			       OPENSSL_VERSION_TEXT);
691
692
#if !defined(LIBRESSL_VERSION_NUMBER) && \
    OPENSSL_VERSION_NUMBER >= 0x10100000L /* 1.1.0 or higher */
693
694
695
696
			printf("linked to OpenSSL version: %s\n",
			       OpenSSL_version(OPENSSL_VERSION));

#else
697
698
			printf("linked to OpenSSL version: %s\n",
			       SSLeay_version(SSLEAY_VERSION));
699
#endif /* OPENSSL_VERSION_NUMBER >= 0x10100000L */
700
701
#endif
#ifdef HAVE_LIBXML2
702
			printf("compiled with libxml2 version: %s\n",
703
			       LIBXML_DOTTED_VERSION);
704
705
			printf("linked to libxml2 version: %s\n",
			       xmlParserVersion);
Evan Hunt's avatar
Evan Hunt committed
706
#endif
707
#if defined(HAVE_JSON) && defined(JSON_C_VERSION)
Evan Hunt's avatar
Evan Hunt committed
708
709
710
711
			printf("compiled with libjson-c version: %s\n",
			       JSON_C_VERSION);
			printf("linked to libjson-c version: %s\n",
			       json_c_version());
712
#endif
713
714
715
716
717
718
#if defined(HAVE_ZLIB) && defined(ZLIB_VERSION)
			printf("compiled with zlib version: %s\n",
			       ZLIB_VERSION);
			printf("linked to zlib version: %s\n",
			       zlibVersion());
#endif
719
720
721
722
#ifdef ISC_PLATFORM_USETHREADS
			printf("threads support is enabled\n");
#else
			printf("threads support is disabled\n");
723
#endif
724
			exit(0);
725
726
727
728
		case 'x':
			/* Obsolete. No longer in use. Ignore. */
			break;
		case 'X':
729
730
731
732
733
			ns_g_forcelock = ISC_TRUE;
			if (strcasecmp(isc_commandline_argument, "none") != 0)
				ns_g_defaultlockfile = isc_commandline_argument;
			else
				ns_g_defaultlockfile = NULL;
734
			break;
Francis Dupont's avatar
Francis Dupont committed
735
736
737
		case 'F':
			/* Reserved for FIPS mode */
			/* FALLTHROUGH */
738
		case '?':
739
			usage();
740
741
			if (isc_commandline_option == '?')
				exit(0);
742
			p = strchr(NS_MAIN_ARGS, isc_commandline_option);
743
744
745
746
747
748
749
			if (p == NULL || *++p != ':')
				ns_main_earlyfatal("unknown option '-%c'",
						   isc_commandline_option);
			else
				ns_main_earlyfatal("option '-%c' requires "
						   "an argument",
						   isc_commandline_option);
Francis Dupont's avatar
Francis Dupont committed
750
			/* FALLTHROUGH */
Bob Halley's avatar
add    
Bob Halley committed
751
		default:
Bob Halley's avatar
Bob Halley committed
752
			ns_main_earlyfatal("parsing options returned %d", ch);
Bob Halley's avatar
add    
Bob Halley committed
753
754
755
		}
	}

756
757
	argc -= isc_commandline_index;
	argv += isc_commandline_index;
758
	POST(argv);
Bob Halley's avatar
add    
Bob Halley committed
759

760
	if (argc > 0) {
Bob Halley's avatar
add    
Bob Halley committed
761
		usage();
Bob Halley's avatar
Bob Halley committed
762
		ns_main_earlyfatal("extra command line arguments");
Bob Halley's avatar
add    
Bob Halley committed
763
764
765
766
	}
}

static isc_result_t
767
create_managers(void) {
Bob Halley's avatar
add    
Bob Halley committed
768
	isc_result_t result;
769
	unsigned int socks;
Bob Halley's avatar
add    
Bob Halley committed
770

771
772
	INSIST(ns_g_cpus_detected > 0);

773
#ifdef ISC_PLATFORM_USETHREADS
774
	if (ns_g_cpus == 0)
775
		ns_g_cpus = ns_g_cpus_detected;
776
777
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
		      ISC_LOG_INFO, "found %u CPU%s, using %u worker thread%s",
778
		      ns_g_cpus_detected, ns_g_cpus_detected == 1 ? "" : "s",
779
		      ns_g_cpus, ns_g_cpus == 1 ? "" : "s");
780
781
782
#else
	ns_g_cpus = 1;
#endif
783
784
785
#ifdef WIN32
	ns_g_udpdisp = 1;
#else
Evan Hunt's avatar
Evan Hunt committed
786
787
788
789
	if (ns_g_udpdisp == 0) {
		if (ns_g_cpus_detected == 1)
			ns_g_udpdisp = 1;
		else
790
			ns_g_udpdisp = ns_g_cpus_detected - 1;
Evan Hunt's avatar
Evan Hunt committed
791
	}
792
	if (ns_g_udpdisp > ns_g_cpus)
793
		ns_g_udpdisp = ns_g_cpus;
794
#endif
795
#ifdef ISC_PLATFORM_USETHREADS
796
797
798
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER,
		      ISC_LOG_INFO, "using %u UDP listener%s per interface",
		      ns_g_udpdisp, ns_g_udpdisp == 1 ? "" : "s");
799
#endif
800

Bob Halley's avatar
add    
Bob Halley committed
801
802
803
	result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
Mark Andrews's avatar
Mark Andrews committed
804
				 "isc_taskmgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
805
806
807
808
809
810
811
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

	result = isc_timermgr_create(ns_g_mctx, &ns_g_timermgr);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
Mark Andrews's avatar
Mark Andrews committed
812
				 "isc_timermgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
813
814
815
816
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

817
	result = isc_socketmgr_create2(ns_g_mctx, &ns_g_socketmgr, maxsocks);
Bob Halley's avatar
add    
Bob Halley committed
818
819
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
820
				 "isc_socketmgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
821
822
823
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}
824
	isc__socketmgr_maxudp(ns_g_socketmgr, maxudp);
825
826
827
828
829
830
	result = isc_socketmgr_getmaxsockets(ns_g_socketmgr, &socks);
	if (result == ISC_R_SUCCESS) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER,
			      ISC_LOG_INFO, "using up to %u sockets", socks);
	}
Bob Halley's avatar
add    
Bob Halley committed
831

832
	result = isc_entropy_create(ns_g_mctx, &ns_g_entropy);
833
834
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
835
				 "isc_entropy_create() failed: %s",
836
837
838
839
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

840
841
842
843
844
845
846
847
	result = isc_hash_create(ns_g_mctx, ns_g_entropy, DNS_NAME_MAXWIRE);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "isc_hash_create() failed: %s",
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

Bob Halley's avatar
add    
Bob Halley committed
848
849
850
851
852
	return (ISC_R_SUCCESS);
}

static void
destroy_managers(void) {
853
854
	ns_lwresd_shutdown();

Bob Halley's avatar
add    
Bob Halley committed
855
	/*
Andreas Gustafsson's avatar
Andreas Gustafsson committed
856
	 * isc_taskmgr_destroy() will block until all tasks have exited,
Bob Halley's avatar
add    
Bob Halley committed
857
858
859
860
	 */
	isc_taskmgr_destroy(&ns_g_taskmgr);
	isc_timermgr_destroy(&ns_g_timermgr);
	isc_socketmgr_destroy(&ns_g_socketmgr);
861
862
863
864
865
866
867

	/*
	 * isc_hash_destroy() cannot be called as long as a resolver may be
	 * running.  Calling this after isc_taskmgr_destroy() ensures the
	 * call is safe.
	 */
	isc_hash_destroy();
Bob Halley's avatar
add    
Bob Halley committed
868
869
}

870
static void
871
dump_symboltable(void) {
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
	int i;
	isc_result_t result;
	const char *fname;
	const void *addr;

	if (isc__backtrace_nsymbols == 0)
		return;

	if (!isc_log_wouldlog(ns_g_lctx, ISC_LOG_DEBUG(99)))
		return;

	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_DEBUG(99), "Symbol table:");

	for (i = 0, result = ISC_R_SUCCESS; result == ISC_R_SUCCESS; i++) {
		addr = NULL;
		fname = NULL;
		result = isc_backtrace_getsymbolfromindex(i, &addr, &fname);
		if (result == ISC_R_SUCCESS) {
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(99),
				      "[%d] %p %s", i, addr, fname);
		}
	}
}

898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
#ifdef HAVE_LIBSECCOMP
static void
setup_seccomp() {
	scmp_filter_ctx ctx;
	unsigned int i;
	int ret;

	/* Make sure the lists are in sync */
	INSIST((sizeof(scmp_syscalls) / sizeof(int)) ==
	       (sizeof(scmp_syscall_names) / sizeof(const char *)));

	ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
			      "libseccomp activation failed");
		return;
	}

	for (i = 0 ; i < sizeof(scmp_syscalls)/sizeof(*(scmp_syscalls)); i++) {
		ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
				       scmp_syscalls[i], 0);
		if (ret < 0)
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
				      "libseccomp rule failed: %s",
				      scmp_syscall_names[i]);

		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(9),
				      "added libseccomp rule: %s",
				      scmp_syscall_names[i]);
	}

	ret = seccomp_load(ctx);
	if (ret < 0) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
			      "libseccomp unable to load filter");
938
939
940
941
	} else {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
			      "libseccomp sandboxing active");
942
943
	}

944
945
946
947
948
	/*
	 * Release filter in ctx. Filters already loaded are not
	 * affected.
	 */
	seccomp_release(ctx);
949
950
951
}
#endif /* HAVE_LIBSECCOMP */

Bob Halley's avatar
add    
Bob Halley committed
952
static void
953
setup(void) {
Bob Halley's avatar
add    
Bob Halley committed
954
	isc_result_t result;
955
	isc_resourcevalue_t old_openfiles;
956
957
958
#ifdef HAVE_LIBSCF
	char *instance = NULL;
#endif
Bob Halley's avatar
add    
Bob Halley committed
959

960
961
962
963
964
965
966
	/*
	 * Get the user and group information before changing the root
	 * directory, so the administrator does not need to keep a copy
	 * of the user and group databases in the chroot'ed environment.
	 */
	ns_os_inituserinfo(ns_g_username);

967
968
969
970
971
	/*
	 * Initialize time conversion information
	 */
	ns_os_tzset();

972
973
	ns_os_opendevnull();

974
975
976
977
978
979
980
981
982
#ifdef HAVE_LIBSCF
	/* Check if named is under smf control, before chroot. */
	result = ns_smf_get_instance(&instance, 0, ns_g_mctx);
	/* We don't care about instance, just check if we got one. */
	if (result == ISC_R_SUCCESS)
		ns_smf_got_instance = 1;
	else
		ns_smf_got_instance = 0;
	if (instance != NULL)
983
		isc_mem_free(ns_g_mctx, instance);
984
985
#endif /* HAVE_LIBSCF */

986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
#ifdef PATH_RANDOMDEV
	/*
	 * Initialize system's random device as fallback entropy source
	 * if running chroot'ed.
	 */
	if (ns_g_chrootdir != NULL) {
		result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy);
		if (result != ISC_R_SUCCESS)
			ns_main_earlyfatal("isc_entropy_create() failed: %s",
					   isc_result_totext(result));

		result = isc_entropy_createfilesource(ns_g_fallbackentropy,
						      PATH_RANDOMDEV);
		if (result != ISC_R_SUCCESS) {
			ns_main_earlywarning("could not open pre-chroot "
					     "entropy source %s: %s",
					     PATH_RANDOMDEV,
					     isc_result_totext(result));
			isc_entropy_detach(&ns_g_fallbackentropy);
		}
	}
#endif
1008
1009
1010
1011
1012
1013
1014

#ifdef ISC_PLATFORM_USETHREADS
	/*
	 * Check for the number of cpu's before ns_os_chroot().
	 */
	ns_g_cpus_detected = isc_os_ncpus();
#endif
1015

1016
1017
	ns_os_chroot(ns_g_chrootdir);

Bob Halley's avatar
Bob Halley committed
1018
1019
1020
1021
1022
1023
1024
1025
	/*
	 * For operating systems which have a capability mechanism, now
	 * is the time to switch to minimal privs and change our user id.
	 * On traditional UNIX systems, this call will be a no-op, and we
	 * will change the user ID after reading the config file the first
	 * time.  (We need to read the config file to know which possibly
	 * privileged ports to bind() to.)
	 */
1026
	ns_os_minprivs();
Bob Halley's avatar
Bob Halley committed
1027

1028
	result = ns_log_init(ISC_TF(ns_g_username != NULL));
1029
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
1030
1031
		ns_main_earlyfatal("ns_log_init() failed: %s",
				   isc_result_totext(result));
1032

Bob Halley's avatar
Bob Halley committed
1033
1034
1035
1036
1037
1038
1039
	/*
	 * Now is the time to daemonize (if we're not running in the
	 * foreground).  We waited until now because we wanted to get
	 * a valid logging context setup.  We cannot daemonize any later,
	 * because calling create_managers() will create threads, which
	 * would be lost after fork().
	 */
1040
1041
	if (!ns_g_foreground)
		ns_os_daemonize();
Bob Halley's avatar
Bob Halley committed
1042

1043
1044
1045
1046
1047
1048
1049
1050
1051
	/*
	 * We call isc_app_start() here as some versions of FreeBSD's fork()
	 * destroys all the signal handling it sets up.
	 */
	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("isc_app_start() failed: %s",
				   isc_result_totext(result));

1052
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
Evan Hunt's avatar
Evan Hunt committed
1053
1054
1055
1056
		      ISC_LOG_NOTICE, "starting %s %s%s%s <id:%s>",
		      ns_g_product, ns_g_version,
		      *ns_g_description ? " " : "", ns_g_description,
		      ns_g_srcid);
Bob Halley's avatar
add    
Bob Halley committed
1057

1058
1059
1060
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "running on %s", ns_os_uname());

1061
1062
1063
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "built with %s", ns_g_configargs);

Evan Hunt's avatar
Evan Hunt committed
1064
1065
1066
1067
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE, "running as: %s%s",
		      program_name, saved_command_line);

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "----------------------------------------------------");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "BIND 9 is maintained by Internet Systems Consortium,");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "Inc. (ISC), a non-profit 501(c)(3) public-benefit ");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "corporation.  Support and training for BIND 9 are ");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "available at https://www.isc.org/support");
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
		      ISC_LOG_NOTICE,
		      "----------------------------------------------------");

1087
1088
	dump_symboltable();

1089
1090
1091
	/*
	 * Get the initial resource limits.
	 */
1092
1093
1094
1095
1096
1097
1098
1099
	(void)isc_resource_getlimit(isc_resource_stacksize,
				    &ns_g_initstacksize);
	(void)isc_resource_getlimit(isc_resource_datasize,
				    &ns_g_initdatasize);
	(void)isc_resource_getlimit(isc_resource_coresize,
				    &ns_g_initcoresize);
	(void)isc_resource_getlimit(isc_resource_openfiles,
				    &ns_g_initopenfiles);
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
	/*
	 * System resources cannot effectively be tuned on some systems.
	 * Raise the limit in such cases for safety.
	 */
	old_openfiles = ns_g_initopenfiles;
	ns_os_adjustnofile();
	(void)isc_resource_getlimit(isc_resource_openfiles,
				    &ns_g_initopenfiles);
	if (old_openfiles != ns_g_initopenfiles) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_NOTICE,
			      "adjusted limit on open files from "
			      "%" ISC_PRINT_QUADFORMAT "u to "
			      "%" ISC_PRINT_QUADFORMAT "u",
			      old_openfiles, ns_g_initopenfiles);
	}

1118
1119
1120
1121
1122
	/*
	 * If the named configuration filename is relative, prepend the current
	 * directory's name before possibly changing to another directory.
	 */
	if (! isc_file_isabsolute(ns_g_conffile)) {
1123
1124
1125
		result = isc_file_absolutepath(ns_g_conffile,
					       absolute_conffile,
					       sizeof(absolute_conffile));
1126
		if (result != ISC_R_SUCCESS)
1127
1128
			ns_main_earlyfatal("could not construct absolute path "
					   "of configuration file: %s",
1129
					   isc_result_totext(result));
1130
1131
1132
		ns_g_conffile = absolute_conffile;
	}

1133
1134
1135
1136
1137
1138
1139
1140
	/*
	 * Record the server's startup time.
	 */
	result = isc_time_now(&ns_g_boottime);
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("isc_time_now() failed: %s",
				   isc_result_totext(result));

Bob Halley's avatar
add    
Bob Halley committed
1141
1142
	result = create_managers();
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
1143
1144
		ns_main_earlyfatal("create_managers() failed: %s",
				   isc_result_totext(result));
Bob Halley's avatar
add    
Bob Halley committed
1145

1146
1147
	ns_builtin_init();

1148
1149
1150
	/*
	 * Add calls to register sdb drivers here.
	 */
1151
	/* xxdb_init(); */
1152

1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
#ifdef ISC_DLZ_DLOPEN
	/*
	 * Register the DLZ "dlopen" driver.
	 */
	result = dlz_dlopen_init(ns_g_mctx);
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("dlz_dlopen_init() failed: %s",
				   isc_result_totext(result));
#endif

#if CONTRIB_DLZ
1164
	/*
1165
	 * Register any other contributed DLZ drivers.
1166
1167
1168
1169
1170
1171
1172
	 */
	result = dlz_drivers_init();
	if (result != ISC_R_SUCCESS)
		ns_main_earlyfatal("dlz_drivers_init() failed: %s",
				   isc_result_totext(result));
#endif

1173
	ns_server_create(ns_g_mctx, &ns_g_server);
1174
1175
1176
1177

#ifdef HAVE_LIBSECCOMP
	setup_seccomp();
#endif /* HAVE_LIBSECCOMP */
Bob Halley's avatar
add    
Bob Halley committed
1178
1179
1180
}

static void
1181
cleanup(void) {
Bob Halley's avatar
add    
Bob Halley committed
1182
	destroy_managers();
1183

1184
1185
1186
	if (ns_g_mapped != NULL)
		dns_acl_detach(&ns_g_mapped);

1187
	ns_server_destroy(&ns_g_server);
1188

1189
1190
1191
1192
	isc_entropy_detach(&ns_g_entropy);
	if (ns_g_fallbackentropy != NULL)
		isc_entropy_detach(&ns_g_fallbackentropy);

1193
1194
	ns_builtin_deinit();

1195
1196
1197
	/*
	 * Add calls to unregister sdb drivers here.
	 */
1198
	/* xxdb_clear(); */
1199

1200
#ifdef CONTRIB_DLZ
1201
	/*
1202
	 * Unregister contributed DLZ drivers.
1203
1204
1205
	 */
	dlz_drivers_clear();
#endif
1206
1207
1208
1209
1210
1211
#ifdef ISC_DLZ_DLOPEN
	/*
	 * Unregister "dlopen" DLZ driver.
	 */
	dlz_dlopen_clear();
#endif
1212

1213
1214
	dns_name_destroy();

1215
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
Bob Halley's avatar
Bob Halley committed
1216
		      ISC_LOG_NOTICE, "exiting");
1217
	ns_log_shutdown();
Bob Halley's avatar
add    
Bob Halley committed
1218
1219
}

1220
1221
1222
1223