nsd.c revision 1.1.1.4 1 1.1 christos /*
2 1.1 christos * nsd.c -- nsd(8)
3 1.1 christos *
4 1.1 christos * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5 1.1 christos *
6 1.1 christos * See LICENSE for the license.
7 1.1 christos *
8 1.1 christos */
9 1.1 christos
10 1.1 christos #include "config.h"
11 1.1 christos
12 1.1 christos #include <sys/types.h>
13 1.1 christos #include <sys/param.h>
14 1.1 christos #include <sys/socket.h>
15 1.1 christos #include <sys/stat.h>
16 1.1 christos #include <sys/uio.h>
17 1.1 christos #include <sys/wait.h>
18 1.1 christos #include <netinet/in.h>
19 1.1 christos #include <arpa/inet.h>
20 1.1 christos #ifdef HAVE_GRP_H
21 1.1 christos #include <grp.h>
22 1.1 christos #endif /* HAVE_GRP_H */
23 1.1 christos #ifdef HAVE_SETUSERCONTEXT
24 1.1 christos #include <login_cap.h>
25 1.1 christos #endif /* HAVE_SETUSERCONTEXT */
26 1.1 christos
27 1.1 christos #include <assert.h>
28 1.1 christos #include <ctype.h>
29 1.1 christos #include <errno.h>
30 1.1 christos #include <fcntl.h>
31 1.1 christos #include <limits.h>
32 1.1 christos #include <netdb.h>
33 1.1 christos #include <pwd.h>
34 1.1 christos #include <signal.h>
35 1.1 christos #include <stdarg.h>
36 1.1 christos #include <stddef.h>
37 1.1 christos #include <stdio.h>
38 1.1 christos #include <stdlib.h>
39 1.1 christos #include <string.h>
40 1.1 christos #include <time.h>
41 1.1 christos #include <unistd.h>
42 1.1 christos
43 1.1 christos #include "nsd.h"
44 1.1 christos #include "options.h"
45 1.1 christos #include "tsig.h"
46 1.1 christos #include "remote.h"
47 1.1 christos #include "xfrd-disk.h"
48 1.1.1.4 prlw1 #ifdef USE_DNSTAP
49 1.1.1.4 prlw1 #include "dnstap/dnstap_collector.h"
50 1.1.1.4 prlw1 #endif
51 1.1 christos
52 1.1 christos /* The server handler... */
53 1.1 christos struct nsd nsd;
54 1.1 christos static char hostname[MAXHOSTNAMELEN];
55 1.1.1.2 christos extern config_parser_state_type* cfg_parser;
56 1.1.1.4 prlw1 static void version(void) ATTR_NORETURN;
57 1.1 christos
58 1.1 christos /*
59 1.1 christos * Print the help text.
60 1.1 christos *
61 1.1 christos */
62 1.1 christos static void
63 1.1 christos usage (void)
64 1.1 christos {
65 1.1 christos fprintf(stderr, "Usage: nsd [OPTION]...\n");
66 1.1 christos fprintf(stderr, "Name Server Daemon.\n\n");
67 1.1 christos fprintf(stderr,
68 1.1 christos "Supported options:\n"
69 1.1 christos " -4 Only listen to IPv4 connections.\n"
70 1.1 christos " -6 Only listen to IPv6 connections.\n"
71 1.1 christos " -a ip-address[@port] Listen to the specified incoming IP address (and port)\n"
72 1.1 christos " May be specified multiple times).\n"
73 1.1 christos " -c configfile Read specified configfile instead of %s.\n"
74 1.1 christos " -d do not fork as a daemon process.\n"
75 1.1 christos #ifndef NDEBUG
76 1.1 christos " -F facilities Specify the debug facilities.\n"
77 1.1 christos #endif /* NDEBUG */
78 1.1 christos " -f database Specify the database to load.\n"
79 1.1 christos " -h Print this help information.\n"
80 1.1 christos , CONFIGFILE);
81 1.1 christos fprintf(stderr,
82 1.1 christos " -i identity Specify the identity when queried for id.server CHAOS TXT.\n"
83 1.1 christos " -I nsid Specify the NSID. This must be a hex string.\n"
84 1.1 christos #ifndef NDEBUG
85 1.1 christos " -L level Specify the debug level.\n"
86 1.1 christos #endif /* NDEBUG */
87 1.1 christos " -l filename Specify the log file.\n"
88 1.1 christos " -N server-count The number of servers to start.\n"
89 1.1 christos " -n tcp-count The maximum number of TCP connections per server.\n"
90 1.1 christos " -P pidfile Specify the PID file to write.\n"
91 1.1 christos " -p port Specify the port to listen to.\n"
92 1.1 christos " -s seconds Dump statistics every SECONDS seconds.\n"
93 1.1 christos " -t chrootdir Change root to specified directory on startup.\n"
94 1.1 christos );
95 1.1 christos fprintf(stderr,
96 1.1 christos " -u user Change effective uid to the specified user.\n"
97 1.1 christos " -V level Specify verbosity level.\n"
98 1.1 christos " -v Print version information.\n"
99 1.1 christos );
100 1.1 christos fprintf(stderr, "Version %s. Report bugs to <%s>.\n",
101 1.1 christos PACKAGE_VERSION, PACKAGE_BUGREPORT);
102 1.1 christos }
103 1.1 christos
104 1.1 christos /*
105 1.1 christos * Print the version exit.
106 1.1 christos *
107 1.1 christos */
108 1.1 christos static void
109 1.1 christos version(void)
110 1.1 christos {
111 1.1 christos fprintf(stderr, "%s version %s\n", PACKAGE_NAME, PACKAGE_VERSION);
112 1.1 christos fprintf(stderr, "Written by NLnet Labs.\n\n");
113 1.1 christos fprintf(stderr,
114 1.1 christos "Copyright (C) 2001-2006 NLnet Labs. This is free software.\n"
115 1.1 christos "There is NO warranty; not even for MERCHANTABILITY or FITNESS\n"
116 1.1 christos "FOR A PARTICULAR PURPOSE.\n");
117 1.1 christos exit(0);
118 1.1 christos }
119 1.1 christos
120 1.1 christos void
121 1.1 christos get_ip_port_frm_str(const char* arg, const char** hostname,
122 1.1 christos const char** port)
123 1.1 christos {
124 1.1.1.4 prlw1 /* parse src[@port] option */
125 1.1.1.4 prlw1 char* delim = NULL;
126 1.1 christos if (arg) {
127 1.1 christos delim = strchr(arg, '@');
128 1.1 christos }
129 1.1 christos
130 1.1.1.4 prlw1 if (delim) {
131 1.1.1.4 prlw1 *delim = '\0';
132 1.1.1.4 prlw1 *port = delim+1;
133 1.1.1.4 prlw1 }
134 1.1.1.4 prlw1 *hostname = arg;
135 1.1 christos }
136 1.1 christos
137 1.1 christos /* append interface to interface array (names, udp, tcp) */
138 1.1 christos void
139 1.1 christos add_interface(char*** nodes, struct nsd* nsd, char* ip)
140 1.1 christos {
141 1.1 christos /* realloc the arrays */
142 1.1 christos if(nsd->ifs == 0) {
143 1.1 christos *nodes = xalloc_zero(sizeof(*nodes));
144 1.1 christos nsd->udp = xalloc_zero(sizeof(*nsd->udp));
145 1.1 christos nsd->tcp = xalloc_zero(sizeof(*nsd->udp));
146 1.1 christos } else {
147 1.1.1.3 christos region_remove_cleanup(nsd->region, free, *nodes);
148 1.1.1.3 christos region_remove_cleanup(nsd->region, free, nsd->udp);
149 1.1.1.3 christos region_remove_cleanup(nsd->region, free, nsd->tcp);
150 1.1 christos *nodes = xrealloc(*nodes, (nsd->ifs+1)*sizeof(*nodes));
151 1.1 christos nsd->udp = xrealloc(nsd->udp, (nsd->ifs+1)*sizeof(*nsd->udp));
152 1.1 christos nsd->tcp = xrealloc(nsd->tcp, (nsd->ifs+1)*sizeof(*nsd->udp));
153 1.1 christos (*nodes)[nsd->ifs] = NULL;
154 1.1 christos memset(&nsd->udp[nsd->ifs], 0, sizeof(*nsd->udp));
155 1.1 christos memset(&nsd->tcp[nsd->ifs], 0, sizeof(*nsd->tcp));
156 1.1 christos }
157 1.1.1.3 christos region_add_cleanup(nsd->region, free, *nodes);
158 1.1.1.3 christos region_add_cleanup(nsd->region, free, nsd->udp);
159 1.1.1.3 christos region_add_cleanup(nsd->region, free, nsd->tcp);
160 1.1 christos
161 1.1 christos /* add it */
162 1.1 christos (*nodes)[nsd->ifs] = ip;
163 1.1 christos ++nsd->ifs;
164 1.1 christos }
165 1.1 christos
166 1.1 christos /*
167 1.1 christos * Fetch the nsd parent process id from the nsd pidfile
168 1.1 christos *
169 1.1 christos */
170 1.1 christos pid_t
171 1.1 christos readpid(const char *file)
172 1.1 christos {
173 1.1 christos int fd;
174 1.1 christos pid_t pid;
175 1.1 christos char pidbuf[16];
176 1.1 christos char *t;
177 1.1 christos int l;
178 1.1 christos
179 1.1 christos if ((fd = open(file, O_RDONLY)) == -1) {
180 1.1 christos return -1;
181 1.1 christos }
182 1.1 christos
183 1.1 christos if (((l = read(fd, pidbuf, sizeof(pidbuf)))) == -1) {
184 1.1 christos close(fd);
185 1.1 christos return -1;
186 1.1 christos }
187 1.1 christos
188 1.1 christos close(fd);
189 1.1 christos
190 1.1 christos /* Empty pidfile means no pidfile... */
191 1.1 christos if (l == 0) {
192 1.1 christos errno = ENOENT;
193 1.1 christos return -1;
194 1.1 christos }
195 1.1 christos
196 1.1 christos pid = (pid_t) strtol(pidbuf, &t, 10);
197 1.1 christos
198 1.1 christos if (*t && *t != '\n') {
199 1.1 christos return -1;
200 1.1 christos }
201 1.1 christos return pid;
202 1.1 christos }
203 1.1 christos
204 1.1 christos /*
205 1.1 christos * Store the nsd parent process id in the nsd pidfile
206 1.1 christos *
207 1.1 christos */
208 1.1 christos int
209 1.1 christos writepid(struct nsd *nsd)
210 1.1 christos {
211 1.1 christos FILE * fd;
212 1.1 christos char pidbuf[32];
213 1.1 christos
214 1.1 christos snprintf(pidbuf, sizeof(pidbuf), "%lu\n", (unsigned long) nsd->pid);
215 1.1 christos
216 1.1 christos if ((fd = fopen(nsd->pidfile, "w")) == NULL ) {
217 1.1 christos log_msg(LOG_ERR, "cannot open pidfile %s: %s",
218 1.1 christos nsd->pidfile, strerror(errno));
219 1.1 christos return -1;
220 1.1 christos }
221 1.1 christos
222 1.1 christos if (!write_data(fd, pidbuf, strlen(pidbuf))) {
223 1.1 christos log_msg(LOG_ERR, "cannot write pidfile %s: %s",
224 1.1 christos nsd->pidfile, strerror(errno));
225 1.1 christos fclose(fd);
226 1.1 christos return -1;
227 1.1 christos }
228 1.1 christos fclose(fd);
229 1.1 christos
230 1.1 christos if (chown(nsd->pidfile, nsd->uid, nsd->gid) == -1) {
231 1.1 christos log_msg(LOG_ERR, "cannot chown %u.%u %s: %s",
232 1.1 christos (unsigned) nsd->uid, (unsigned) nsd->gid,
233 1.1 christos nsd->pidfile, strerror(errno));
234 1.1 christos return -1;
235 1.1 christos }
236 1.1 christos
237 1.1 christos return 0;
238 1.1 christos }
239 1.1 christos
240 1.1 christos void
241 1.1 christos unlinkpid(const char* file)
242 1.1 christos {
243 1.1 christos int fd = -1;
244 1.1 christos
245 1.1 christos if (file) {
246 1.1 christos /* truncate pidfile */
247 1.1 christos fd = open(file, O_WRONLY | O_TRUNC, 0644);
248 1.1 christos if (fd == -1) {
249 1.1 christos /* Truncate the pid file. */
250 1.1 christos log_msg(LOG_ERR, "can not truncate the pid file %s: %s", file, strerror(errno));
251 1.1 christos } else
252 1.1 christos close(fd);
253 1.1 christos
254 1.1 christos /* unlink pidfile */
255 1.1 christos if (unlink(file) == -1)
256 1.1 christos log_msg(LOG_WARNING, "failed to unlink pidfile %s: %s",
257 1.1 christos file, strerror(errno));
258 1.1 christos }
259 1.1 christos }
260 1.1 christos
261 1.1 christos /*
262 1.1 christos * Incoming signals, set appropriate actions.
263 1.1 christos *
264 1.1 christos */
265 1.1 christos void
266 1.1 christos sig_handler(int sig)
267 1.1 christos {
268 1.1 christos /* To avoid race cond. We really don't want to use log_msg() in this handler */
269 1.1 christos
270 1.1 christos /* Are we a child server? */
271 1.1 christos if (nsd.server_kind != NSD_SERVER_MAIN) {
272 1.1 christos switch (sig) {
273 1.1 christos case SIGCHLD:
274 1.1 christos nsd.signal_hint_child = 1;
275 1.1 christos break;
276 1.1 christos case SIGALRM:
277 1.1 christos break;
278 1.1 christos case SIGINT:
279 1.1 christos case SIGTERM:
280 1.1 christos nsd.signal_hint_quit = 1;
281 1.1 christos break;
282 1.1 christos case SIGILL:
283 1.1 christos case SIGUSR1: /* Dump stats on SIGUSR1. */
284 1.1 christos nsd.signal_hint_statsusr = 1;
285 1.1 christos break;
286 1.1 christos default:
287 1.1 christos break;
288 1.1 christos }
289 1.1 christos return;
290 1.1 christos }
291 1.1 christos
292 1.1 christos /* We are the main process */
293 1.1 christos switch (sig) {
294 1.1 christos case SIGCHLD:
295 1.1 christos nsd.signal_hint_child = 1;
296 1.1 christos return;
297 1.1 christos case SIGHUP:
298 1.1 christos nsd.signal_hint_reload_hup = 1;
299 1.1 christos return;
300 1.1 christos case SIGALRM:
301 1.1 christos nsd.signal_hint_stats = 1;
302 1.1 christos break;
303 1.1 christos case SIGILL:
304 1.1 christos /*
305 1.1 christos * For backwards compatibility with BIND 8 and older
306 1.1 christos * versions of NSD.
307 1.1 christos */
308 1.1 christos nsd.signal_hint_statsusr = 1;
309 1.1 christos break;
310 1.1 christos case SIGUSR1:
311 1.1 christos /* Dump statistics. */
312 1.1 christos nsd.signal_hint_statsusr = 1;
313 1.1 christos break;
314 1.1 christos case SIGINT:
315 1.1 christos case SIGTERM:
316 1.1 christos default:
317 1.1 christos nsd.signal_hint_shutdown = 1;
318 1.1 christos break;
319 1.1 christos }
320 1.1 christos }
321 1.1 christos
322 1.1 christos /*
323 1.1 christos * Statistic output...
324 1.1 christos *
325 1.1 christos */
326 1.1 christos #ifdef BIND8_STATS
327 1.1 christos void
328 1.1 christos bind8_stats (struct nsd *nsd)
329 1.1 christos {
330 1.1 christos char buf[MAXSYSLOGMSGLEN];
331 1.1 christos char *msg, *t;
332 1.1 christos int i, len;
333 1.1 christos
334 1.1 christos /* Current time... */
335 1.1 christos time_t now;
336 1.1 christos if(!nsd->st.period)
337 1.1 christos return;
338 1.1 christos time(&now);
339 1.1 christos
340 1.1 christos /* NSTATS */
341 1.1 christos t = msg = buf + snprintf(buf, MAXSYSLOGMSGLEN, "NSTATS %lld %lu",
342 1.1 christos (long long) now, (unsigned long) nsd->st.boot);
343 1.1 christos for (i = 0; i <= 255; i++) {
344 1.1 christos /* How much space left? */
345 1.1 christos if ((len = buf + MAXSYSLOGMSGLEN - t) < 32) {
346 1.1 christos log_msg(LOG_INFO, "%s", buf);
347 1.1 christos t = msg;
348 1.1 christos len = buf + MAXSYSLOGMSGLEN - t;
349 1.1 christos }
350 1.1 christos
351 1.1 christos if (nsd->st.qtype[i] != 0) {
352 1.1 christos t += snprintf(t, len, " %s=%lu", rrtype_to_string(i), nsd->st.qtype[i]);
353 1.1 christos }
354 1.1 christos }
355 1.1 christos if (t > msg)
356 1.1 christos log_msg(LOG_INFO, "%s", buf);
357 1.1 christos
358 1.1 christos /* XSTATS */
359 1.1 christos /* Only print it if we're in the main daemon or have anything to report... */
360 1.1 christos if (nsd->server_kind == NSD_SERVER_MAIN
361 1.1 christos || nsd->st.dropped || nsd->st.raxfr || (nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped)
362 1.1 christos || nsd->st.txerr || nsd->st.opcode[OPCODE_QUERY] || nsd->st.opcode[OPCODE_IQUERY]
363 1.1 christos || nsd->st.wrongzone || nsd->st.ctcp + nsd->st.ctcp6 || nsd->st.rcode[RCODE_SERVFAIL]
364 1.1 christos || nsd->st.rcode[RCODE_FORMAT] || nsd->st.nona || nsd->st.rcode[RCODE_NXDOMAIN]
365 1.1 christos || nsd->st.opcode[OPCODE_UPDATE]) {
366 1.1 christos
367 1.1 christos log_msg(LOG_INFO, "XSTATS %lld %lu"
368 1.1 christos " RR=%lu RNXD=%lu RFwdR=%lu RDupR=%lu RFail=%lu RFErr=%lu RErr=%lu RAXFR=%lu"
369 1.1 christos " RLame=%lu ROpts=%lu SSysQ=%lu SAns=%lu SFwdQ=%lu SDupQ=%lu SErr=%lu RQ=%lu"
370 1.1 christos " RIQ=%lu RFwdQ=%lu RDupQ=%lu RTCP=%lu SFwdR=%lu SFail=%lu SFErr=%lu SNaAns=%lu"
371 1.1 christos " SNXD=%lu RUQ=%lu RURQ=%lu RUXFR=%lu RUUpd=%lu",
372 1.1 christos (long long) now, (unsigned long) nsd->st.boot,
373 1.1 christos nsd->st.dropped, (unsigned long)0, (unsigned long)0, (unsigned long)0, (unsigned long)0,
374 1.1 christos (unsigned long)0, (unsigned long)0, nsd->st.raxfr, (unsigned long)0, (unsigned long)0,
375 1.1 christos (unsigned long)0, nsd->st.qudp + nsd->st.qudp6 - nsd->st.dropped, (unsigned long)0,
376 1.1 christos (unsigned long)0, nsd->st.txerr,
377 1.1 christos nsd->st.opcode[OPCODE_QUERY], nsd->st.opcode[OPCODE_IQUERY], nsd->st.wrongzone,
378 1.1 christos (unsigned long)0, nsd->st.ctcp + nsd->st.ctcp6,
379 1.1 christos (unsigned long)0, nsd->st.rcode[RCODE_SERVFAIL], nsd->st.rcode[RCODE_FORMAT],
380 1.1 christos nsd->st.nona, nsd->st.rcode[RCODE_NXDOMAIN],
381 1.1 christos (unsigned long)0, (unsigned long)0, (unsigned long)0, nsd->st.opcode[OPCODE_UPDATE]);
382 1.1 christos }
383 1.1 christos
384 1.1 christos }
385 1.1 christos #endif /* BIND8_STATS */
386 1.1 christos
387 1.1 christos extern char *optarg;
388 1.1 christos extern int optind;
389 1.1 christos
390 1.1 christos int
391 1.1 christos main(int argc, char *argv[])
392 1.1 christos {
393 1.1 christos /* Scratch variables... */
394 1.1 christos int c;
395 1.1 christos pid_t oldpid;
396 1.1 christos size_t i;
397 1.1 christos struct sigaction action;
398 1.1 christos #ifdef HAVE_GETPWNAM
399 1.1 christos struct passwd *pwd = NULL;
400 1.1 christos #endif /* HAVE_GETPWNAM */
401 1.1 christos
402 1.1 christos struct addrinfo hints[2];
403 1.1 christos int hints_in_use = 1;
404 1.1 christos char** nodes = NULL; /* array of address strings, size nsd.ifs */
405 1.1 christos const char *udp_port = 0;
406 1.1 christos const char *tcp_port = 0;
407 1.1 christos
408 1.1 christos const char *configfile = CONFIGFILE;
409 1.1 christos
410 1.1 christos char* argv0 = (argv0 = strrchr(argv[0], '/')) ? argv0 + 1 : argv[0];
411 1.1 christos
412 1.1 christos log_init(argv0);
413 1.1 christos
414 1.1 christos /* Initialize the server handler... */
415 1.1 christos memset(&nsd, 0, sizeof(struct nsd));
416 1.1 christos nsd.region = region_create(xalloc, free);
417 1.1 christos nsd.dbfile = 0;
418 1.1 christos nsd.pidfile = 0;
419 1.1 christos nsd.server_kind = NSD_SERVER_MAIN;
420 1.1 christos memset(&hints, 0, sizeof(*hints)*2);
421 1.1 christos hints[0].ai_family = DEFAULT_AI_FAMILY;
422 1.1 christos hints[0].ai_flags = AI_PASSIVE;
423 1.1 christos hints[1].ai_family = DEFAULT_AI_FAMILY;
424 1.1 christos hints[1].ai_flags = AI_PASSIVE;
425 1.1 christos nsd.identity = 0;
426 1.1 christos nsd.version = VERSION;
427 1.1 christos nsd.username = 0;
428 1.1 christos nsd.chrootdir = 0;
429 1.1 christos nsd.nsid = NULL;
430 1.1 christos nsd.nsid_len = 0;
431 1.1 christos
432 1.1 christos nsd.child_count = 0;
433 1.1 christos nsd.maximum_tcp_count = 0;
434 1.1 christos nsd.current_tcp_count = 0;
435 1.1 christos nsd.grab_ip6_optional = 0;
436 1.1 christos nsd.file_rotation_ok = 0;
437 1.1 christos
438 1.1 christos /* Set up our default identity to gethostname(2) */
439 1.1 christos if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
440 1.1 christos nsd.identity = hostname;
441 1.1 christos } else {
442 1.1 christos log_msg(LOG_ERR,
443 1.1 christos "failed to get the host name: %s - using default identity",
444 1.1 christos strerror(errno));
445 1.1 christos nsd.identity = IDENTITY;
446 1.1 christos }
447 1.1 christos
448 1.1 christos /* Parse the command line... */
449 1.1 christos while ((c = getopt(argc, argv, "46a:c:df:hi:I:l:N:n:P:p:s:u:t:X:V:v"
450 1.1 christos #ifndef NDEBUG /* <mattthijs> only when configured with --enable-checking */
451 1.1 christos "F:L:"
452 1.1 christos #endif /* NDEBUG */
453 1.1 christos )) != -1) {
454 1.1 christos switch (c) {
455 1.1 christos case '4':
456 1.1 christos hints[0].ai_family = AF_INET;
457 1.1 christos break;
458 1.1 christos case '6':
459 1.1 christos #ifdef INET6
460 1.1 christos hints[0].ai_family = AF_INET6;
461 1.1 christos #else /* !INET6 */
462 1.1 christos error("IPv6 support not enabled.");
463 1.1 christos #endif /* INET6 */
464 1.1 christos break;
465 1.1 christos case 'a':
466 1.1 christos add_interface(&nodes, &nsd, optarg);
467 1.1 christos break;
468 1.1 christos case 'c':
469 1.1 christos configfile = optarg;
470 1.1 christos break;
471 1.1 christos case 'd':
472 1.1 christos nsd.debug = 1;
473 1.1 christos break;
474 1.1 christos case 'f':
475 1.1 christos nsd.dbfile = optarg;
476 1.1 christos break;
477 1.1 christos case 'h':
478 1.1 christos usage();
479 1.1 christos exit(0);
480 1.1 christos case 'i':
481 1.1 christos nsd.identity = optarg;
482 1.1 christos break;
483 1.1 christos case 'I':
484 1.1 christos if (nsd.nsid_len != 0) {
485 1.1 christos /* can only be given once */
486 1.1 christos break;
487 1.1 christos }
488 1.1 christos if (strncasecmp(optarg, "ascii_", 6) == 0) {
489 1.1 christos nsd.nsid = xalloc(strlen(optarg+6));
490 1.1 christos nsd.nsid_len = strlen(optarg+6);
491 1.1 christos memmove(nsd.nsid, optarg+6, nsd.nsid_len);
492 1.1 christos } else {
493 1.1 christos if (strlen(optarg) % 2 != 0) {
494 1.1 christos error("the NSID must be a hex string of an even length.");
495 1.1 christos }
496 1.1 christos nsd.nsid = xalloc(strlen(optarg) / 2);
497 1.1 christos nsd.nsid_len = strlen(optarg) / 2;
498 1.1 christos if (hex_pton(optarg, nsd.nsid, nsd.nsid_len) == -1) {
499 1.1 christos error("hex string cannot be parsed '%s' in NSID.", optarg);
500 1.1 christos }
501 1.1 christos }
502 1.1 christos break;
503 1.1 christos case 'l':
504 1.1 christos nsd.log_filename = optarg;
505 1.1 christos break;
506 1.1 christos case 'N':
507 1.1 christos i = atoi(optarg);
508 1.1 christos if (i <= 0) {
509 1.1 christos error("number of child servers must be greater than zero.");
510 1.1 christos } else {
511 1.1 christos nsd.child_count = i;
512 1.1 christos }
513 1.1 christos break;
514 1.1 christos case 'n':
515 1.1 christos i = atoi(optarg);
516 1.1 christos if (i <= 0) {
517 1.1 christos error("number of concurrent TCP connections must greater than zero.");
518 1.1 christos } else {
519 1.1 christos nsd.maximum_tcp_count = i;
520 1.1 christos }
521 1.1 christos break;
522 1.1 christos case 'P':
523 1.1 christos nsd.pidfile = optarg;
524 1.1 christos break;
525 1.1 christos case 'p':
526 1.1 christos if (atoi(optarg) == 0) {
527 1.1 christos error("port argument must be numeric.");
528 1.1 christos }
529 1.1 christos tcp_port = optarg;
530 1.1 christos udp_port = optarg;
531 1.1 christos break;
532 1.1 christos case 's':
533 1.1 christos #ifdef BIND8_STATS
534 1.1 christos nsd.st.period = atoi(optarg);
535 1.1 christos #else /* !BIND8_STATS */
536 1.1 christos error("BIND 8 statistics not enabled.");
537 1.1 christos #endif /* BIND8_STATS */
538 1.1 christos break;
539 1.1 christos case 't':
540 1.1 christos #ifdef HAVE_CHROOT
541 1.1 christos nsd.chrootdir = optarg;
542 1.1 christos #else /* !HAVE_CHROOT */
543 1.1 christos error("chroot not supported on this platform.");
544 1.1 christos #endif /* HAVE_CHROOT */
545 1.1 christos break;
546 1.1 christos case 'u':
547 1.1 christos nsd.username = optarg;
548 1.1 christos break;
549 1.1 christos case 'V':
550 1.1 christos verbosity = atoi(optarg);
551 1.1 christos break;
552 1.1 christos case 'v':
553 1.1 christos version();
554 1.1 christos /* version exits */
555 1.1.1.2 christos break;
556 1.1 christos #ifndef NDEBUG
557 1.1 christos case 'F':
558 1.1 christos sscanf(optarg, "%x", &nsd_debug_facilities);
559 1.1 christos break;
560 1.1 christos case 'L':
561 1.1 christos sscanf(optarg, "%d", &nsd_debug_level);
562 1.1 christos break;
563 1.1 christos #endif /* NDEBUG */
564 1.1 christos case '?':
565 1.1 christos default:
566 1.1 christos usage();
567 1.1 christos exit(1);
568 1.1 christos }
569 1.1 christos }
570 1.1 christos argc -= optind;
571 1.1.1.3 christos /* argv += optind; */
572 1.1 christos
573 1.1 christos /* Commandline parse error */
574 1.1 christos if (argc != 0) {
575 1.1 christos usage();
576 1.1 christos exit(1);
577 1.1 christos }
578 1.1 christos
579 1.1 christos if (strlen(nsd.identity) > UCHAR_MAX) {
580 1.1 christos error("server identity too long (%u characters)",
581 1.1 christos (unsigned) strlen(nsd.identity));
582 1.1 christos }
583 1.1 christos if(!tsig_init(nsd.region))
584 1.1 christos error("init tsig failed");
585 1.1 christos
586 1.1 christos /* Read options */
587 1.1 christos nsd.options = nsd_options_create(region_create_custom(xalloc, free,
588 1.1 christos DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE,
589 1.1 christos DEFAULT_INITIAL_CLEANUP_SIZE, 1));
590 1.1 christos if(!parse_options_file(nsd.options, configfile, NULL, NULL)) {
591 1.1 christos error("could not read config: %s\n", configfile);
592 1.1 christos }
593 1.1 christos if(!parse_zone_list_file(nsd.options)) {
594 1.1 christos error("could not read zonelist file %s\n",
595 1.1 christos nsd.options->zonelistfile);
596 1.1 christos }
597 1.1 christos if(nsd.options->do_ip4 && !nsd.options->do_ip6) {
598 1.1 christos hints[0].ai_family = AF_INET;
599 1.1 christos }
600 1.1 christos #ifdef INET6
601 1.1 christos if(nsd.options->do_ip6 && !nsd.options->do_ip4) {
602 1.1 christos hints[0].ai_family = AF_INET6;
603 1.1 christos }
604 1.1 christos #endif /* INET6 */
605 1.1 christos if(nsd.options->ip_addresses)
606 1.1 christos {
607 1.1.1.2 christos ip_address_option_type* ip = nsd.options->ip_addresses;
608 1.1 christos while(ip) {
609 1.1 christos add_interface(&nodes, &nsd, ip->address);
610 1.1 christos ip = ip->next;
611 1.1 christos }
612 1.1 christos }
613 1.1 christos if (verbosity == 0)
614 1.1 christos verbosity = nsd.options->verbosity;
615 1.1 christos #ifndef NDEBUG
616 1.1 christos if (nsd_debug_level > 0 && verbosity == 0)
617 1.1 christos verbosity = nsd_debug_level;
618 1.1 christos #endif /* NDEBUG */
619 1.1 christos if(nsd.options->debug_mode) nsd.debug=1;
620 1.1 christos if(!nsd.dbfile)
621 1.1 christos {
622 1.1 christos if(nsd.options->database)
623 1.1 christos nsd.dbfile = nsd.options->database;
624 1.1 christos else
625 1.1 christos nsd.dbfile = DBFILE;
626 1.1 christos }
627 1.1 christos if(!nsd.pidfile)
628 1.1 christos {
629 1.1 christos if(nsd.options->pidfile)
630 1.1 christos nsd.pidfile = nsd.options->pidfile;
631 1.1 christos else
632 1.1 christos nsd.pidfile = PIDFILE;
633 1.1 christos }
634 1.1 christos if(strcmp(nsd.identity, hostname)==0 || strcmp(nsd.identity,IDENTITY)==0)
635 1.1 christos {
636 1.1 christos if(nsd.options->identity)
637 1.1 christos nsd.identity = nsd.options->identity;
638 1.1 christos }
639 1.1 christos if(nsd.options->version) {
640 1.1 christos nsd.version = nsd.options->version;
641 1.1 christos }
642 1.1 christos if (nsd.options->logfile && !nsd.log_filename) {
643 1.1 christos nsd.log_filename = nsd.options->logfile;
644 1.1 christos }
645 1.1 christos if(nsd.child_count == 0) {
646 1.1 christos nsd.child_count = nsd.options->server_count;
647 1.1 christos }
648 1.1 christos #ifdef SO_REUSEPORT
649 1.1 christos if(nsd.options->reuseport && nsd.child_count > 1) {
650 1.1 christos nsd.reuseport = nsd.child_count;
651 1.1 christos }
652 1.1 christos #endif /* SO_REUSEPORT */
653 1.1 christos if(nsd.maximum_tcp_count == 0) {
654 1.1 christos nsd.maximum_tcp_count = nsd.options->tcp_count;
655 1.1 christos }
656 1.1 christos nsd.tcp_timeout = nsd.options->tcp_timeout;
657 1.1 christos nsd.tcp_query_count = nsd.options->tcp_query_count;
658 1.1 christos nsd.tcp_mss = nsd.options->tcp_mss;
659 1.1 christos nsd.outgoing_tcp_mss = nsd.options->outgoing_tcp_mss;
660 1.1 christos nsd.ipv4_edns_size = nsd.options->ipv4_edns_size;
661 1.1 christos nsd.ipv6_edns_size = nsd.options->ipv6_edns_size;
662 1.1 christos
663 1.1 christos if(udp_port == 0)
664 1.1 christos {
665 1.1 christos if(nsd.options->port != 0) {
666 1.1 christos udp_port = nsd.options->port;
667 1.1 christos tcp_port = nsd.options->port;
668 1.1 christos } else {
669 1.1 christos udp_port = UDP_PORT;
670 1.1 christos tcp_port = TCP_PORT;
671 1.1 christos }
672 1.1 christos }
673 1.1 christos #ifdef BIND8_STATS
674 1.1 christos if(nsd.st.period == 0) {
675 1.1 christos nsd.st.period = nsd.options->statistics;
676 1.1 christos }
677 1.1 christos #endif /* BIND8_STATS */
678 1.1 christos #ifdef HAVE_CHROOT
679 1.1 christos if(nsd.chrootdir == 0) nsd.chrootdir = nsd.options->chroot;
680 1.1 christos #ifdef CHROOTDIR
681 1.1 christos /* if still no chrootdir, fallback to default */
682 1.1 christos if(nsd.chrootdir == 0) nsd.chrootdir = CHROOTDIR;
683 1.1 christos #endif /* CHROOTDIR */
684 1.1 christos #endif /* HAVE_CHROOT */
685 1.1 christos if(nsd.username == 0) {
686 1.1 christos if(nsd.options->username) nsd.username = nsd.options->username;
687 1.1 christos else nsd.username = USER;
688 1.1 christos }
689 1.1 christos if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
690 1.1 christos if(chdir(nsd.options->zonesdir)) {
691 1.1 christos error("cannot chdir to '%s': %s",
692 1.1 christos nsd.options->zonesdir, strerror(errno));
693 1.1 christos }
694 1.1 christos DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
695 1.1 christos nsd.options->zonesdir));
696 1.1 christos }
697 1.1 christos
698 1.1 christos /* EDNS0 */
699 1.1 christos edns_init_data(&nsd.edns_ipv4, nsd.options->ipv4_edns_size);
700 1.1 christos #if defined(INET6)
701 1.1 christos #if defined(IPV6_USE_MIN_MTU) || defined(IPV6_MTU)
702 1.1 christos edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
703 1.1 christos #else /* no way to set IPV6 MTU, send no bigger than that. */
704 1.1 christos if (nsd.options->ipv6_edns_size < IPV6_MIN_MTU)
705 1.1 christos edns_init_data(&nsd.edns_ipv6, nsd.options->ipv6_edns_size);
706 1.1 christos else
707 1.1 christos edns_init_data(&nsd.edns_ipv6, IPV6_MIN_MTU);
708 1.1 christos #endif /* IPV6 MTU) */
709 1.1 christos #endif /* defined(INET6) */
710 1.1 christos
711 1.1 christos if (nsd.nsid_len == 0 && nsd.options->nsid) {
712 1.1 christos if (strlen(nsd.options->nsid) % 2 != 0) {
713 1.1 christos error("the NSID must be a hex string of an even length.");
714 1.1 christos }
715 1.1 christos nsd.nsid = xalloc(strlen(nsd.options->nsid) / 2);
716 1.1 christos nsd.nsid_len = strlen(nsd.options->nsid) / 2;
717 1.1 christos if (hex_pton(nsd.options->nsid, nsd.nsid, nsd.nsid_len) == -1) {
718 1.1 christos error("hex string cannot be parsed '%s' in NSID.", nsd.options->nsid);
719 1.1 christos }
720 1.1 christos }
721 1.1 christos edns_init_nsid(&nsd.edns_ipv4, nsd.nsid_len);
722 1.1 christos #if defined(INET6)
723 1.1 christos edns_init_nsid(&nsd.edns_ipv6, nsd.nsid_len);
724 1.1 christos #endif /* defined(INET6) */
725 1.1 christos
726 1.1 christos /* Number of child servers to fork. */
727 1.1 christos nsd.children = (struct nsd_child *) region_alloc_array(
728 1.1 christos nsd.region, nsd.child_count, sizeof(struct nsd_child));
729 1.1 christos for (i = 0; i < nsd.child_count; ++i) {
730 1.1 christos nsd.children[i].kind = NSD_SERVER_BOTH;
731 1.1 christos nsd.children[i].pid = -1;
732 1.1 christos nsd.children[i].child_fd = -1;
733 1.1 christos nsd.children[i].parent_fd = -1;
734 1.1 christos nsd.children[i].handler = NULL;
735 1.1 christos nsd.children[i].need_to_send_STATS = 0;
736 1.1 christos nsd.children[i].need_to_send_QUIT = 0;
737 1.1 christos nsd.children[i].need_to_exit = 0;
738 1.1 christos nsd.children[i].has_exited = 0;
739 1.1.1.3 christos #ifdef BIND8_STATS
740 1.1.1.3 christos nsd.children[i].query_count = 0;
741 1.1.1.3 christos #endif
742 1.1 christos }
743 1.1 christos
744 1.1 christos nsd.this_child = NULL;
745 1.1 christos
746 1.1 christos /* We need at least one active interface */
747 1.1 christos if (nsd.ifs == 0) {
748 1.1 christos add_interface(&nodes, &nsd, NULL);
749 1.1 christos
750 1.1 christos /*
751 1.1 christos * With IPv6 we'd like to open two separate sockets,
752 1.1 christos * one for IPv4 and one for IPv6, both listening to
753 1.1 christos * the wildcard address (unless the -4 or -6 flags are
754 1.1 christos * specified).
755 1.1 christos *
756 1.1 christos * However, this is only supported on platforms where
757 1.1 christos * we can turn the socket option IPV6_V6ONLY _on_.
758 1.1 christos * Otherwise we just listen to a single IPv6 socket
759 1.1 christos * and any incoming IPv4 connections will be
760 1.1 christos * automatically mapped to our IPv6 socket.
761 1.1 christos */
762 1.1 christos #ifdef INET6
763 1.1 christos if (hints[0].ai_family == AF_UNSPEC) {
764 1.1 christos #ifdef IPV6_V6ONLY
765 1.1 christos add_interface(&nodes, &nsd, NULL);
766 1.1 christos hints[0].ai_family = AF_INET6;
767 1.1 christos hints[1].ai_family = AF_INET;
768 1.1 christos hints_in_use = 2;
769 1.1 christos nsd.grab_ip6_optional = 1;
770 1.1 christos #else /* !IPV6_V6ONLY */
771 1.1 christos hints[0].ai_family = AF_INET6;
772 1.1 christos #endif /* IPV6_V6ONLY */
773 1.1 christos }
774 1.1 christos #endif /* INET6 */
775 1.1 christos }
776 1.1 christos
777 1.1 christos /* Set up the address info structures with real interface/port data */
778 1.1.1.3 christos assert(nodes);
779 1.1 christos for (i = 0; i < nsd.ifs; ++i) {
780 1.1 christos int r;
781 1.1 christos const char* node = NULL;
782 1.1 christos const char* service = NULL;
783 1.1 christos int h = ((hints_in_use == 1)?0:i%hints_in_use);
784 1.1 christos
785 1.1 christos /* We don't perform name-lookups */
786 1.1 christos if (nodes[i] != NULL)
787 1.1 christos hints[h].ai_flags |= AI_NUMERICHOST;
788 1.1 christos get_ip_port_frm_str(nodes[i], &node, &service);
789 1.1 christos
790 1.1 christos hints[h].ai_socktype = SOCK_DGRAM;
791 1.1 christos if ((r=getaddrinfo(node, (service?service:udp_port), &hints[h], &nsd.udp[i].addr)) != 0) {
792 1.1 christos #ifdef INET6
793 1.1 christos if(nsd.grab_ip6_optional && hints[0].ai_family == AF_INET6) {
794 1.1 christos log_msg(LOG_WARNING, "No IPv6, fallback to IPv4. getaddrinfo: %s",
795 1.1 christos r==EAI_SYSTEM?strerror(errno):gai_strerror(r));
796 1.1 christos continue;
797 1.1 christos }
798 1.1 christos #endif
799 1.1 christos error("cannot parse address '%s': getaddrinfo: %s %s",
800 1.1 christos nodes[i]?nodes[i]:"(null)",
801 1.1 christos gai_strerror(r),
802 1.1 christos r==EAI_SYSTEM?strerror(errno):"");
803 1.1 christos }
804 1.1 christos
805 1.1 christos hints[h].ai_socktype = SOCK_STREAM;
806 1.1 christos if ((r=getaddrinfo(node, (service?service:tcp_port), &hints[h], &nsd.tcp[i].addr)) != 0) {
807 1.1 christos error("cannot parse address '%s': getaddrinfo: %s %s",
808 1.1 christos nodes[i]?nodes[i]:"(null)",
809 1.1 christos gai_strerror(r),
810 1.1 christos r==EAI_SYSTEM?strerror(errno):"");
811 1.1 christos }
812 1.1 christos }
813 1.1 christos
814 1.1 christos /* Parse the username into uid and gid */
815 1.1 christos nsd.gid = getgid();
816 1.1 christos nsd.uid = getuid();
817 1.1 christos #ifdef HAVE_GETPWNAM
818 1.1 christos /* Parse the username into uid and gid */
819 1.1 christos if (*nsd.username) {
820 1.1 christos if (isdigit((unsigned char)*nsd.username)) {
821 1.1 christos char *t;
822 1.1 christos nsd.uid = strtol(nsd.username, &t, 10);
823 1.1 christos if (*t != 0) {
824 1.1 christos if (*t != '.' || !isdigit((unsigned char)*++t)) {
825 1.1 christos error("-u user or -u uid or -u uid.gid");
826 1.1 christos }
827 1.1 christos nsd.gid = strtol(t, &t, 10);
828 1.1 christos } else {
829 1.1 christos /* Lookup the group id in /etc/passwd */
830 1.1 christos if ((pwd = getpwuid(nsd.uid)) == NULL) {
831 1.1 christos error("user id %u does not exist.", (unsigned) nsd.uid);
832 1.1 christos } else {
833 1.1 christos nsd.gid = pwd->pw_gid;
834 1.1 christos }
835 1.1 christos }
836 1.1 christos } else {
837 1.1 christos /* Lookup the user id in /etc/passwd */
838 1.1 christos if ((pwd = getpwnam(nsd.username)) == NULL) {
839 1.1 christos error("user '%s' does not exist.", nsd.username);
840 1.1 christos } else {
841 1.1 christos nsd.uid = pwd->pw_uid;
842 1.1 christos nsd.gid = pwd->pw_gid;
843 1.1 christos }
844 1.1 christos }
845 1.1 christos }
846 1.1 christos /* endpwent(); */
847 1.1 christos #endif /* HAVE_GETPWNAM */
848 1.1 christos
849 1.1 christos #if defined(HAVE_SSL)
850 1.1 christos key_options_tsig_add(nsd.options);
851 1.1 christos #endif
852 1.1 christos
853 1.1 christos append_trailing_slash(&nsd.options->xfrdir, nsd.options->region);
854 1.1 christos /* Check relativity of pathnames to chroot */
855 1.1 christos if (nsd.chrootdir && nsd.chrootdir[0]) {
856 1.1 christos /* existing chrootdir: append trailing slash for strncmp checking */
857 1.1 christos append_trailing_slash(&nsd.chrootdir, nsd.region);
858 1.1 christos append_trailing_slash(&nsd.options->zonesdir, nsd.options->region);
859 1.1 christos
860 1.1 christos /* zonesdir must be absolute and within chroot,
861 1.1 christos * all other pathnames may be relative to zonesdir */
862 1.1 christos if (strncmp(nsd.options->zonesdir, nsd.chrootdir, strlen(nsd.chrootdir)) != 0) {
863 1.1 christos error("zonesdir %s has to be an absolute path that starts with the chroot path %s",
864 1.1 christos nsd.options->zonesdir, nsd.chrootdir);
865 1.1 christos } else if (!file_inside_chroot(nsd.pidfile, nsd.chrootdir)) {
866 1.1 christos error("pidfile %s is not relative to %s: chroot not possible",
867 1.1 christos nsd.pidfile, nsd.chrootdir);
868 1.1 christos } else if (!file_inside_chroot(nsd.dbfile, nsd.chrootdir)) {
869 1.1 christos error("database %s is not relative to %s: chroot not possible",
870 1.1 christos nsd.dbfile, nsd.chrootdir);
871 1.1 christos } else if (!file_inside_chroot(nsd.options->xfrdfile, nsd.chrootdir)) {
872 1.1 christos error("xfrdfile %s is not relative to %s: chroot not possible",
873 1.1 christos nsd.options->xfrdfile, nsd.chrootdir);
874 1.1 christos } else if (!file_inside_chroot(nsd.options->zonelistfile, nsd.chrootdir)) {
875 1.1 christos error("zonelistfile %s is not relative to %s: chroot not possible",
876 1.1 christos nsd.options->zonelistfile, nsd.chrootdir);
877 1.1 christos } else if (!file_inside_chroot(nsd.options->xfrdir, nsd.chrootdir)) {
878 1.1 christos error("xfrdir %s is not relative to %s: chroot not possible",
879 1.1 christos nsd.options->xfrdir, nsd.chrootdir);
880 1.1 christos }
881 1.1 christos }
882 1.1 christos
883 1.1 christos /* Set up the logging */
884 1.1 christos log_open(LOG_PID, FACILITY, nsd.log_filename);
885 1.1 christos if (!nsd.log_filename)
886 1.1 christos log_set_log_function(log_syslog);
887 1.1 christos else if (nsd.uid && nsd.gid) {
888 1.1 christos if(chown(nsd.log_filename, nsd.uid, nsd.gid) != 0)
889 1.1 christos VERBOSITY(2, (LOG_WARNING, "chown %s failed: %s",
890 1.1 christos nsd.log_filename, strerror(errno)));
891 1.1 christos }
892 1.1 christos log_msg(LOG_NOTICE, "%s starting (%s)", argv0, PACKAGE_STRING);
893 1.1 christos
894 1.1 christos /* Do we have a running nsd? */
895 1.1 christos if ((oldpid = readpid(nsd.pidfile)) == -1) {
896 1.1 christos if (errno != ENOENT) {
897 1.1 christos log_msg(LOG_ERR, "can't read pidfile %s: %s",
898 1.1 christos nsd.pidfile, strerror(errno));
899 1.1 christos }
900 1.1 christos } else {
901 1.1 christos if (kill(oldpid, 0) == 0 || errno == EPERM) {
902 1.1 christos log_msg(LOG_WARNING,
903 1.1 christos "%s is already running as %u, continuing",
904 1.1 christos argv0, (unsigned) oldpid);
905 1.1 christos } else {
906 1.1 christos log_msg(LOG_ERR,
907 1.1 christos "...stale pid file from process %u",
908 1.1 christos (unsigned) oldpid);
909 1.1 christos }
910 1.1 christos }
911 1.1 christos
912 1.1 christos /* Setup the signal handling... */
913 1.1 christos action.sa_handler = sig_handler;
914 1.1 christos sigfillset(&action.sa_mask);
915 1.1 christos action.sa_flags = 0;
916 1.1 christos sigaction(SIGTERM, &action, NULL);
917 1.1 christos sigaction(SIGHUP, &action, NULL);
918 1.1 christos sigaction(SIGINT, &action, NULL);
919 1.1 christos sigaction(SIGILL, &action, NULL);
920 1.1 christos sigaction(SIGUSR1, &action, NULL);
921 1.1 christos sigaction(SIGALRM, &action, NULL);
922 1.1 christos sigaction(SIGCHLD, &action, NULL);
923 1.1 christos action.sa_handler = SIG_IGN;
924 1.1 christos sigaction(SIGPIPE, &action, NULL);
925 1.1 christos
926 1.1 christos /* Initialize... */
927 1.1 christos nsd.mode = NSD_RUN;
928 1.1 christos nsd.signal_hint_child = 0;
929 1.1 christos nsd.signal_hint_reload = 0;
930 1.1 christos nsd.signal_hint_reload_hup = 0;
931 1.1 christos nsd.signal_hint_quit = 0;
932 1.1 christos nsd.signal_hint_shutdown = 0;
933 1.1 christos nsd.signal_hint_stats = 0;
934 1.1 christos nsd.signal_hint_statsusr = 0;
935 1.1 christos nsd.quit_sync_done = 0;
936 1.1 christos
937 1.1 christos /* Initialize the server... */
938 1.1 christos if (server_init(&nsd) != 0) {
939 1.1 christos error("server initialization failed, %s could "
940 1.1 christos "not be started", argv0);
941 1.1 christos }
942 1.1 christos #if defined(HAVE_SSL)
943 1.1 christos if(nsd.options->control_enable) {
944 1.1 christos /* read ssl keys while superuser and outside chroot */
945 1.1 christos if(!(nsd.rc = daemon_remote_create(nsd.options)))
946 1.1 christos error("could not perform remote control setup");
947 1.1 christos }
948 1.1 christos #endif /* HAVE_SSL */
949 1.1 christos
950 1.1 christos /* Unless we're debugging, fork... */
951 1.1 christos if (!nsd.debug) {
952 1.1 christos int fd;
953 1.1 christos
954 1.1 christos /* Take off... */
955 1.1 christos switch ((nsd.pid = fork())) {
956 1.1 christos case 0:
957 1.1 christos /* Child */
958 1.1 christos break;
959 1.1 christos case -1:
960 1.1 christos error("fork() failed: %s", strerror(errno));
961 1.1.1.2 christos break;
962 1.1 christos default:
963 1.1 christos /* Parent is done */
964 1.1 christos server_close_all_sockets(nsd.udp, nsd.ifs);
965 1.1 christos server_close_all_sockets(nsd.tcp, nsd.ifs);
966 1.1 christos exit(0);
967 1.1 christos }
968 1.1 christos
969 1.1 christos /* Detach ourselves... */
970 1.1 christos if (setsid() == -1) {
971 1.1 christos error("setsid() failed: %s", strerror(errno));
972 1.1 christos }
973 1.1 christos
974 1.1 christos if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
975 1.1 christos (void)dup2(fd, STDIN_FILENO);
976 1.1 christos (void)dup2(fd, STDOUT_FILENO);
977 1.1 christos (void)dup2(fd, STDERR_FILENO);
978 1.1 christos if (fd > 2)
979 1.1 christos (void)close(fd);
980 1.1 christos }
981 1.1 christos }
982 1.1 christos
983 1.1 christos /* Get our process id */
984 1.1 christos nsd.pid = getpid();
985 1.1 christos
986 1.1 christos /* Set user context */
987 1.1 christos #ifdef HAVE_GETPWNAM
988 1.1 christos if (*nsd.username) {
989 1.1 christos #ifdef HAVE_SETUSERCONTEXT
990 1.1 christos /* setusercontext does initgroups, setuid, setgid, and
991 1.1 christos * also resource limits from login config, but we
992 1.1 christos * still call setresuid, setresgid to be sure to set all uid */
993 1.1 christos if (setusercontext(NULL, pwd, nsd.uid,
994 1.1 christos LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0)
995 1.1 christos log_msg(LOG_WARNING, "unable to setusercontext %s: %s",
996 1.1 christos nsd.username, strerror(errno));
997 1.1 christos #endif /* HAVE_SETUSERCONTEXT */
998 1.1 christos }
999 1.1 christos #endif /* HAVE_GETPWNAM */
1000 1.1 christos
1001 1.1 christos /* Chroot */
1002 1.1 christos #ifdef HAVE_CHROOT
1003 1.1 christos if (nsd.chrootdir && nsd.chrootdir[0]) {
1004 1.1 christos int l = strlen(nsd.chrootdir)-1; /* ends in trailing slash */
1005 1.1 christos
1006 1.1 christos if (file_inside_chroot(nsd.log_filename, nsd.chrootdir))
1007 1.1 christos nsd.file_rotation_ok = 1;
1008 1.1 christos
1009 1.1 christos /* strip chroot from pathnames if they're absolute */
1010 1.1 christos nsd.options->zonesdir += l;
1011 1.1 christos if (nsd.log_filename){
1012 1.1 christos if (nsd.log_filename[0] == '/')
1013 1.1 christos nsd.log_filename += l;
1014 1.1 christos }
1015 1.1 christos if (nsd.pidfile[0] == '/')
1016 1.1 christos nsd.pidfile += l;
1017 1.1 christos if (nsd.dbfile[0] == '/')
1018 1.1 christos nsd.dbfile += l;
1019 1.1 christos if (nsd.options->xfrdfile[0] == '/')
1020 1.1 christos nsd.options->xfrdfile += l;
1021 1.1 christos if (nsd.options->zonelistfile[0] == '/')
1022 1.1 christos nsd.options->zonelistfile += l;
1023 1.1 christos if (nsd.options->xfrdir[0] == '/')
1024 1.1 christos nsd.options->xfrdir += l;
1025 1.1 christos
1026 1.1 christos /* strip chroot from pathnames of "include:" statements
1027 1.1 christos * on subsequent repattern commands */
1028 1.1 christos cfg_parser->chroot = nsd.chrootdir;
1029 1.1 christos
1030 1.1 christos #ifdef HAVE_TZSET
1031 1.1 christos /* set timezone whilst not yet in chroot */
1032 1.1 christos tzset();
1033 1.1 christos #endif
1034 1.1 christos if (chroot(nsd.chrootdir)) {
1035 1.1 christos error("unable to chroot: %s", strerror(errno));
1036 1.1 christos }
1037 1.1 christos if (chdir("/")) {
1038 1.1 christos error("unable to chdir to chroot: %s", strerror(errno));
1039 1.1 christos }
1040 1.1 christos DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed root directory to %s",
1041 1.1 christos nsd.chrootdir));
1042 1.1 christos /* chdir to zonesdir again after chroot */
1043 1.1 christos if(nsd.options->zonesdir && nsd.options->zonesdir[0]) {
1044 1.1 christos if(chdir(nsd.options->zonesdir)) {
1045 1.1 christos error("unable to chdir to '%s': %s",
1046 1.1 christos nsd.options->zonesdir, strerror(errno));
1047 1.1 christos }
1048 1.1 christos DEBUG(DEBUG_IPC,1, (LOG_INFO, "changed directory to %s",
1049 1.1 christos nsd.options->zonesdir));
1050 1.1 christos }
1051 1.1 christos }
1052 1.1 christos else
1053 1.1 christos #endif /* HAVE_CHROOT */
1054 1.1 christos nsd.file_rotation_ok = 1;
1055 1.1 christos
1056 1.1 christos DEBUG(DEBUG_IPC,1, (LOG_INFO, "file rotation on %s %sabled",
1057 1.1 christos nsd.log_filename, nsd.file_rotation_ok?"en":"dis"));
1058 1.1 christos
1059 1.1 christos /* Write pidfile */
1060 1.1 christos if (writepid(&nsd) == -1) {
1061 1.1 christos log_msg(LOG_ERR, "cannot overwrite the pidfile %s: %s",
1062 1.1 christos nsd.pidfile, strerror(errno));
1063 1.1 christos }
1064 1.1 christos
1065 1.1 christos /* Drop the permissions */
1066 1.1 christos #ifdef HAVE_GETPWNAM
1067 1.1 christos if (*nsd.username) {
1068 1.1 christos #ifdef HAVE_INITGROUPS
1069 1.1 christos if(initgroups(nsd.username, nsd.gid) != 0)
1070 1.1 christos log_msg(LOG_WARNING, "unable to initgroups %s: %s",
1071 1.1 christos nsd.username, strerror(errno));
1072 1.1 christos #endif /* HAVE_INITGROUPS */
1073 1.1 christos endpwent();
1074 1.1 christos
1075 1.1 christos #ifdef HAVE_SETRESGID
1076 1.1 christos if(setresgid(nsd.gid,nsd.gid,nsd.gid) != 0)
1077 1.1 christos #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID)
1078 1.1 christos if(setregid(nsd.gid,nsd.gid) != 0)
1079 1.1 christos #else /* use setgid */
1080 1.1 christos if(setgid(nsd.gid) != 0)
1081 1.1 christos #endif /* HAVE_SETRESGID */
1082 1.1 christos error("unable to set group id of %s: %s",
1083 1.1 christos nsd.username, strerror(errno));
1084 1.1 christos
1085 1.1 christos #ifdef HAVE_SETRESUID
1086 1.1 christos if(setresuid(nsd.uid,nsd.uid,nsd.uid) != 0)
1087 1.1 christos #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID)
1088 1.1 christos if(setreuid(nsd.uid,nsd.uid) != 0)
1089 1.1 christos #else /* use setuid */
1090 1.1 christos if(setuid(nsd.uid) != 0)
1091 1.1 christos #endif /* HAVE_SETRESUID */
1092 1.1 christos error("unable to set user id of %s: %s",
1093 1.1 christos nsd.username, strerror(errno));
1094 1.1 christos
1095 1.1 christos DEBUG(DEBUG_IPC,1, (LOG_INFO, "dropped user privileges, run as %s",
1096 1.1 christos nsd.username));
1097 1.1 christos }
1098 1.1 christos #endif /* HAVE_GETPWNAM */
1099 1.1 christos xfrd_make_tempdir(&nsd);
1100 1.1 christos #ifdef USE_ZONE_STATS
1101 1.1 christos options_zonestatnames_create(nsd.options);
1102 1.1 christos server_zonestat_alloc(&nsd);
1103 1.1 christos #endif /* USE_ZONE_STATS */
1104 1.1.1.4 prlw1 #ifdef USE_DNSTAP
1105 1.1.1.4 prlw1 if(nsd.options->dnstap_enable) {
1106 1.1.1.4 prlw1 nsd.dt_collector = dt_collector_create(&nsd);
1107 1.1.1.4 prlw1 dt_collector_start(nsd.dt_collector, &nsd);
1108 1.1.1.4 prlw1 }
1109 1.1.1.4 prlw1 #endif /* USE_DNSTAP */
1110 1.1 christos
1111 1.1 christos if(nsd.server_kind == NSD_SERVER_MAIN) {
1112 1.1 christos server_prepare_xfrd(&nsd);
1113 1.1 christos /* xfrd forks this before reading database, so it does not get
1114 1.1 christos * the memory size of the database */
1115 1.1 christos server_start_xfrd(&nsd, 0, 0);
1116 1.1.1.3 christos /* close zonelistfile in non-xfrd processes */
1117 1.1.1.3 christos zone_list_close(nsd.options);
1118 1.1 christos }
1119 1.1 christos if (server_prepare(&nsd) != 0) {
1120 1.1 christos unlinkpid(nsd.pidfile);
1121 1.1 christos error("server preparation failed, %s could "
1122 1.1 christos "not be started", argv0);
1123 1.1 christos }
1124 1.1 christos if(nsd.server_kind == NSD_SERVER_MAIN) {
1125 1.1 christos server_send_soa_xfrd(&nsd, 0);
1126 1.1 christos }
1127 1.1 christos
1128 1.1 christos /* Really take off */
1129 1.1 christos log_msg(LOG_NOTICE, "%s started (%s), pid %d",
1130 1.1 christos argv0, PACKAGE_STRING, (int) nsd.pid);
1131 1.1 christos
1132 1.1 christos if (nsd.server_kind == NSD_SERVER_MAIN) {
1133 1.1 christos server_main(&nsd);
1134 1.1 christos } else {
1135 1.1 christos server_child(&nsd);
1136 1.1 christos }
1137 1.1 christos
1138 1.1 christos /* NOTREACH */
1139 1.1 christos exit(0);
1140 1.1 christos }
1141