main.c 11.3 KB
Newer Older
Bob Halley's avatar
add    
Bob Halley committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1999, 2000  Internet Software Consortium.
Bob Halley's avatar
add    
Bob Halley committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

#include <config.h>

#include <stdlib.h>
21
#include <string.h>
Bob Halley's avatar
add    
Bob Halley committed
22
23

#include <isc/app.h>
24
#include <isc/commandline.h>
Bob Halley's avatar
add    
Bob Halley committed
25
26
#include <isc/task.h>
#include <isc/timer.h>
Bob Halley's avatar
Bob Halley committed
27
#include <isc/util.h>
Bob Halley's avatar
add    
Bob Halley committed
28

29
#include <dns/dispatch.h>
Bob Halley's avatar
add    
Bob Halley committed
30
#include <dst/result.h>
David Lawrence's avatar
David Lawrence committed
31
#include <dns/view.h>
Bob Halley's avatar
add    
Bob Halley committed
32

33
34
35
36
37
/*
 * Defining NS_MAIN provides storage declaratons (rather than extern)
 * for variables in named/globals.h.
 */
#define NS_MAIN 1		
Bob Halley's avatar
add    
Bob Halley committed
38

39
#include <named/globals.h>	/* Explicit, though named/log.h includes it. */
Bob Halley's avatar
add    
Bob Halley committed
40
#include <named/interfacemgr.h>
41
#include <named/log.h>
42
#include <named/omapi.h>
Bob Halley's avatar
Bob Halley committed
43
#include <named/os.h>
Bob Halley's avatar
add    
Bob Halley committed
44
#include <named/server.h>
45
#include <named/lwresd.h>
Bob Halley's avatar
Bob Halley committed
46
#include <named/main.h>
Bob Halley's avatar
add    
Bob Halley committed
47

David Lawrence's avatar
David Lawrence committed
48
static isc_boolean_t	want_stats = ISC_FALSE;
49
static isc_boolean_t	lwresd_only = ISC_FALSE;
David Lawrence's avatar
David Lawrence committed
50
static const char *	program_name = "named";
Bob Halley's avatar
add    
Bob Halley committed
51

Bob Halley's avatar
Bob Halley committed
52
53
void
ns_main_earlyfatal(const char *format, ...) {
Bob Halley's avatar
add    
Bob Halley committed
54
55
56
	va_list args;

	va_start(args, format);
57
58
59
60
	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
61
62
63
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			       "exiting (due to early fatal error)");
64
	} else {
65
		fprintf(stderr, "%s: ", program_name);
66
67
		vfprintf(stderr, format, args);
		fprintf(stderr, "\n");
68
		fflush(stderr);
69
	}
Bob Halley's avatar
add    
Bob Halley committed
70
71
72
73
74
	va_end(args);

	exit(1);
}

75
static void
David Lawrence's avatar
David Lawrence committed
76
77
78
assertion_failed(const char *file, int line, isc_assertiontype_t type,
		 const char *cond)
{
79
80
81
82
83
	/*
	 * Handle assertion failures.
	 */

	if (ns_g_lctx != NULL) {
84
85
86
87
88
89
		/*
		 * Reset the assetion callback in case it is the log
		 * routines causing the assertion.
		 */
		isc_assertion_setcallback(NULL);

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			      "%s:%d: %s(%s) failed", file, line,
			      isc_assertion_typetotext(type), cond);
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			       NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
			       "exiting (due assertion failure)");
	} 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);
}

static void
David Lawrence's avatar
David Lawrence committed
109
110
111
library_fatal_error(const char *file, int line, const char *format,
		    va_list args)
{
112
113
114
115
116
	/*
	 * Handle isc_error_fatal() calls from our libraries.
	 */

	if (ns_g_lctx != NULL) {
117
118
119
120
121
122
		/*
		 * Reset the error callback in case it is the log
		 * routines causing the assertion.
		 */
		isc_error_setfatal(NULL);

123
124
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_MAIN, ISC_LOG_CRITICAL,
125
			      "%s:%d: fatal error:", file, line);
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
		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);
}

144
static void
David Lawrence's avatar
David Lawrence committed
145
146
147
library_unexpected_error(const char *file, int line, const char *format,
			 va_list args)
{
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
	/*
	 * 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);
	}
}

Bob Halley's avatar
add    
Bob Halley committed
167
168
169
static void
usage(void) {
	fprintf(stderr,
170
171
		"usage: named [-c conffile] [-d debuglevel] "
		"[-f|-g] [-n number_of_cpus]\n"
Andreas Gustafsson's avatar
Andreas Gustafsson committed
172
		"             [-p port] [-s] [-t chrootdir] [-u username]\n");
Bob Halley's avatar
add    
Bob Halley committed
173
174
175
176
177
}

static void 
parse_command_line(int argc, char *argv[]) {
	int ch;
178
	unsigned int port;
179
180
181
182
183
184
185
186
187
	char *s;

	s = strrchr(argv[0], '/');
	if (s == NULL)
		s = argv[0];
	else
		s++;
	if (strcmp(s, "lwresd") == 0)
		lwresd_only = ISC_TRUE;
Bob Halley's avatar
add    
Bob Halley committed
188

189
	isc_commandline_errprint = ISC_FALSE;
190
	while ((ch = isc_commandline_parse(argc, argv,
191
					   "c:d:fgn:N:p:st:u:x:")) !=
Bob Halley's avatar
Bob Halley committed
192
	       -1) {
Bob Halley's avatar
add    
Bob Halley committed
193
194
		switch (ch) {
		case 'c':
195
			ns_g_conffile = isc_commandline_argument;
Bob Halley's avatar
add    
Bob Halley committed
196
			break;
Bob Halley's avatar
Bob Halley committed
197
198
199
		case 'd':
			ns_g_debuglevel = atoi(isc_commandline_argument);
			break;
200
201
202
		case 'f':
			ns_g_foreground = ISC_TRUE;
			break;
203
204
205
206
		case 'g':
			ns_g_foreground = ISC_TRUE;
			ns_g_logstderr = ISC_TRUE;
			break;
207
208
		case 'N': /* Deprecated. */
		case 'n':
209
			ns_g_cpus = atoi(isc_commandline_argument);
Bob Halley's avatar
add    
Bob Halley committed
210
211
212
			if (ns_g_cpus == 0)
				ns_g_cpus = 1;
			break;
Bob Halley's avatar
Bob Halley committed
213
		case 'p':
214
215
			port = atoi(isc_commandline_argument);
			if (port < 1 || port > 65535)
216
				ns_main_earlyfatal("port '%s' out of range",
217
218
						   isc_commandline_argument);
			ns_g_port = port;
Bob Halley's avatar
Bob Halley committed
219
			break;
Bob Halley's avatar
add    
Bob Halley committed
220
221
222
223
		case 's':
			/* XXXRTH temporary syntax */
			want_stats = ISC_TRUE;
			break;
224
		case 't':
225
			/* XXXJAB should we make a copy? */
226
227
			ns_g_chrootdir = isc_commandline_argument;
			break;
228
229
230
		case 'u':
			ns_g_username = isc_commandline_argument;
			break;
231
232
233
		case 'x':
			/* XXXRTH temporary syntax */
			ns_g_cachefile = isc_commandline_argument;
Bob Halley's avatar
add    
Bob Halley committed
234
			break;
235
		case '?':
236
			usage();
237
			ns_main_earlyfatal("unknown option '-%c'",
238
					   isc_commandline_option);
Bob Halley's avatar
add    
Bob Halley committed
239
		default:
Bob Halley's avatar
Bob Halley committed
240
			ns_main_earlyfatal("parsing options returned %d", ch);
Bob Halley's avatar
add    
Bob Halley committed
241
242
243
		}
	}

244
245
	argc -= isc_commandline_index;
	argv += isc_commandline_index;
Bob Halley's avatar
add    
Bob Halley committed
246

247
	if (argc > 0) {
Bob Halley's avatar
add    
Bob Halley committed
248
		usage();
Bob Halley's avatar
Bob Halley committed
249
		ns_main_earlyfatal("extra command line arguments");
Bob Halley's avatar
add    
Bob Halley committed
250
251
252
253
	}
}

static isc_result_t
254
create_managers(void) {
Bob Halley's avatar
add    
Bob Halley committed
255
256
257
258
259
	isc_result_t result;

	result = isc_taskmgr_create(ns_g_mctx, ns_g_cpus, 0, &ns_g_taskmgr);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
260
				 "ns_taskmgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
261
262
263
264
265
266
267
				 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__,
268
				 "ns_timermgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
269
270
271
272
273
274
275
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

	result = isc_socketmgr_create(ns_g_mctx, &ns_g_socketmgr);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
276
				 "isc_socketmgr_create() failed: %s",
Bob Halley's avatar
add    
Bob Halley committed
277
278
279
280
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

281
282
283
284
285
286
287
288
	result = dns_dispatchmgr_create(ns_g_mctx, &ns_g_dispatchmgr);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "dns_dispatchmgr_create() failed: %s",
				 isc_result_totext(result));
		return (ISC_R_UNEXPECTED);
	}

Bob Halley's avatar
add    
Bob Halley committed
289
290
291
292
293
	return (ISC_R_SUCCESS);
}

static void
destroy_managers(void) {
294
295
296
297
298
299
	if (!lwresd_only) {
		if (ns_g_omapimgr != NULL)
			omapi_listener_shutdown(ns_g_omapimgr);
		else
			omapi_lib_destroy();
	}
300

301
	dns_dispatchmgr_destroy(&ns_g_dispatchmgr);
Bob Halley's avatar
add    
Bob Halley committed
302
303
304
305
306
307
308
309
310
	/*
	 * isc_taskmgr_destroy() will  block until all tasks have exited,
	 */
	isc_taskmgr_destroy(&ns_g_taskmgr);
	isc_timermgr_destroy(&ns_g_timermgr);
	isc_socketmgr_destroy(&ns_g_socketmgr);
}

static void
311
setup(void) {
Bob Halley's avatar
add    
Bob Halley committed
312
313
	isc_result_t result;

314
315
	ns_os_chroot(ns_g_chrootdir);

Bob Halley's avatar
Bob Halley committed
316
317
318
319
320
321
322
323
324
325
	/*
	 * 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.)
	 */
	ns_os_minprivs(ns_g_username);

326
	result = ns_log_init(ISC_TF(ns_g_username != NULL));
327
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
328
329
		ns_main_earlyfatal("ns_log_init() failed: %s",
				   isc_result_totext(result));
330

Bob Halley's avatar
Bob Halley committed
331
332
333
334
335
336
337
	/*
	 * 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().
	 */
338
339
	if (!ns_g_foreground)
		ns_os_daemonize();
Bob Halley's avatar
Bob Halley committed
340

341
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
Bob Halley's avatar
Bob Halley committed
342
		      ISC_LOG_NOTICE, "starting BIND %s", ns_g_version);
Bob Halley's avatar
add    
Bob Halley committed
343
344
345

	result = create_managers();
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
346
347
		ns_main_earlyfatal("create_managers() failed: %s",
				   isc_result_totext(result));
Bob Halley's avatar
add    
Bob Halley committed
348

349
350
351
352
353
354
355
356
357
358
	if (lwresd_only) {
		dns_view_t *view = NULL;
		result = ns_lwresd_createview(ns_g_mctx, &view);
		if (result != ISC_R_SUCCESS)
			ns_main_earlyfatal("ns_lwresd_createview() failed: %s",
					   isc_result_totext(result));
		ns_lwresd_create(ns_g_mctx, view, &ns_g_lwresd);
		dns_view_detach(&view);
	} else
		ns_server_create(ns_g_mctx, &ns_g_server);
359

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
	if (!lwresd_only) {
		result = ns_omapi_init();
		if (result != ISC_R_SUCCESS)
			ns_main_earlyfatal("omapi_lib_init() failed: %s",
					   isc_result_totext(result));
	
		result = ns_omapi_listen(&ns_g_omapimgr);
		if (result == ISC_R_SUCCESS)
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_DEBUG(3),
				      "OMAPI started");
		else
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_MAIN, ISC_LOG_WARNING,
				      "OMAPI failed to start: %s",
				      isc_result_totext(result));
	}
Bob Halley's avatar
add    
Bob Halley committed
377
378
379
}

static void
380
cleanup(void) {
Bob Halley's avatar
add    
Bob Halley committed
381
	destroy_managers();
382
383
384
385
	if (lwresd_only)
		ns_lwresd_destroy(&ns_g_lwresd);
	else
		ns_server_destroy(&ns_g_server);
386
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN,
Bob Halley's avatar
Bob Halley committed
387
		      ISC_LOG_NOTICE, "exiting");
388
	ns_log_shutdown();
Bob Halley's avatar
add    
Bob Halley committed
389
390
391
392
393
394
}

int
main(int argc, char *argv[]) {
	isc_result_t result;

395
	program_name = argv[0];
396
397
	isc_assertion_setcallback(assertion_failed);
	isc_error_setfatal(library_fatal_error);
398
	isc_error_setunexpected(library_unexpected_error);
399

400
	ns_os_init();
Bob Halley's avatar
Bob Halley committed
401

Bob Halley's avatar
add    
Bob Halley committed
402
403
	result = isc_app_start();
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
404
405
		ns_main_earlyfatal("isc_app_start() failed: %s",
				   isc_result_totext(result));
Bob Halley's avatar
add    
Bob Halley committed
406
407
408

	result = isc_mem_create(0, 0, &ns_g_mctx);
	if (result != ISC_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
409
410
		ns_main_earlyfatal("isc_mem_create() failed: %s",
				   isc_result_totext(result));
Bob Halley's avatar
add    
Bob Halley committed
411
412
413
414
415
416
417
418
419

	dns_result_register();
	dst_result_register();

	parse_command_line(argc, argv);

	setup();

	/*
Bob Halley's avatar
Bob Halley committed
420
421
	 * Start things running and then wait for a shutdown request
	 * or reload.
Bob Halley's avatar
add    
Bob Halley committed
422
	 */
Bob Halley's avatar
Bob Halley committed
423
424
425
426
	do {
		result = isc_app_run();
		
		if (result == ISC_R_RELOAD) {
427
			ns_server_reloadwanted(ns_g_server);
Bob Halley's avatar
Bob Halley committed
428
429
430
431
432
433
434
435
436
437
		} else if (result != ISC_R_SUCCESS) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "isc_app_run(): %s",
					 isc_result_totext(result));
			/*
			 * Force exit.
			 */
			result = ISC_R_SUCCESS;
		}
	} while (result != ISC_R_SUCCESS);
Bob Halley's avatar
add    
Bob Halley committed
438
439
440
441
442
443
444
445
446

	cleanup();

	if (want_stats)
		isc_mem_stats(ns_g_mctx, stdout);
	isc_mem_destroy(&ns_g_mctx);

	isc_app_finish();

Bob Halley's avatar
Bob Halley committed
447
448
	ns_os_shutdown();

Bob Halley's avatar
add    
Bob Halley committed
449
450
	return (0);
}
451
452