]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnsmasq.c
import of dnsmasq-2.35.tar.gz
[people/ms/dnsmasq.git] / src / dnsmasq.c
CommitLineData
cdeda28f 1/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
9e4abcb5
SK
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991.
6
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11*/
12
9e4abcb5
SK
13#include "dnsmasq.h"
14
3d8df260
SK
15static char *compile_opts =
16#ifndef HAVE_IPV6
17"no-"
18#endif
19"IPv6 "
20#ifndef HAVE_GETOPT_LONG
21"no-"
22#endif
23"GNU-getopt "
24#ifdef HAVE_BROKEN_RTC
25"no-RTC "
26#endif
1697269c
SK
27#ifdef NO_FORK
28"no-MMU "
29#endif
3d8df260
SK
30#ifndef HAVE_ISC_READER
31"no-"
32#endif
33"ISC-leasefile "
34#ifndef HAVE_DBUS
35"no-"
36#endif
b8187c80
SK
37"DBus "
38#ifdef NO_GETTEXT
39"no-"
40#endif
e17fb629 41"I18N ";
3d8df260 42
5e9e0efb
SK
43static pid_t pid;
44static int pipewrite;
9e4abcb5 45
1697269c 46static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int *maxfdp);
3be34541
SK
47static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now);
48static void sig_handler(int sig);
9e4abcb5
SK
49
50int main (int argc, char **argv)
51{
3be34541 52 struct daemon *daemon;
de37951c 53 int bind_fallback = 0;
309331f5 54 int bad_capabilities = 0;
9e4abcb5 55 time_t now, last = 0;
9e4abcb5 56 struct sigaction sigact;
26128d27 57 struct iname *if_tmp;
7cebd20f 58 int piperead, pipefd[2];
5e9e0efb 59 unsigned char sig;
7cebd20f 60
b8187c80
SK
61#ifndef NO_GETTEXT
62 setlocale(LC_ALL, "");
63 bindtextdomain("dnsmasq", LOCALEDIR);
64 textdomain("dnsmasq");
65#endif
66
5e9e0efb 67 pid = 0;
9e4abcb5
SK
68
69 sigact.sa_handler = sig_handler;
70 sigact.sa_flags = 0;
71 sigemptyset(&sigact.sa_mask);
72 sigaction(SIGUSR1, &sigact, NULL);
9e4abcb5
SK
73 sigaction(SIGHUP, &sigact, NULL);
74 sigaction(SIGTERM, &sigact, NULL);
44a2a316 75 sigaction(SIGALRM, &sigact, NULL);
feba5c1d
SK
76 sigaction(SIGCHLD, &sigact, NULL);
77
78 /* ignore SIGPIPE */
79 sigact.sa_handler = SIG_IGN;
80 sigaction(SIGPIPE, &sigact, NULL);
9e4abcb5 81
3d8df260 82 daemon = read_opts(argc, argv, compile_opts);
3be34541
SK
83
84 if (daemon->edns_pktsz < PACKETSZ)
85 daemon->edns_pktsz = PACKETSZ;
0a852541
SK
86 daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
87 daemon->edns_pktsz : DNSMASQ_PACKETSZ;
88 daemon->packet = safe_malloc(daemon->packet_buff_sz);
9e4abcb5 89
3be34541 90 if (!daemon->lease_file)
9e4abcb5 91 {
3be34541
SK
92 if (daemon->dhcp)
93 daemon->lease_file = LEASEFILE;
9e4abcb5 94 }
33820b7e 95#ifndef HAVE_ISC_READER
3be34541 96 else if (!daemon->dhcp)
b8187c80 97 die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL);
33820b7e 98#endif
9e4abcb5 99
5e9e0efb
SK
100#ifdef HAVE_LINUX_NETWORK
101 netlink_init(daemon);
309331f5
SK
102#elif !(defined(IP_RECVDSTADDR) && \
103 defined(IP_RECVIF) && \
104 defined(IP_SENDSRCADDR))
105 if (!(daemon->options & OPT_NOWILD))
de37951c
SK
106 {
107 bind_fallback = 1;
3be34541 108 daemon->options |= OPT_NOWILD;
de37951c 109 }
309331f5
SK
110#endif
111
112 daemon->interfaces = NULL;
113 if (!enumerate_interfaces(daemon))
114 die(_("failed to find list of interfaces: %s"), NULL);
9e4abcb5 115
3be34541 116 if (daemon->options & OPT_NOWILD)
de37951c 117 {
5e9e0efb 118 daemon->listeners = create_bound_listeners(daemon);
de37951c 119
3be34541 120 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
de37951c 121 if (if_tmp->name && !if_tmp->used)
b8187c80 122 die(_("unknown interface %s"), if_tmp->name);
de37951c 123
3be34541 124 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
de37951c
SK
125 if (!if_tmp->used)
126 {
3d8df260 127 prettyprint_addr(&if_tmp->addr, daemon->namebuff);
b8187c80 128 die(_("no interface with address %s"), daemon->namebuff);
de37951c
SK
129 }
130 }
309331f5
SK
131 else if (!(daemon->listeners = create_wildcard_listeners(daemon->port)))
132 die(_("failed to create listening socket: %s"), NULL);
de37951c 133
3be34541 134 cache_init(daemon->cachesize, daemon->options & OPT_LOG);
44a2a316 135
5e9e0efb 136 now = dnsmasq_time();
9e4abcb5 137
3be34541 138 if (daemon->dhcp)
9e4abcb5 139 {
5e9e0efb 140#if !defined(HAVE_LINUX_NETWORK) && !defined(IP_RECVIF)
de37951c
SK
141 int c;
142 struct iname *tmp;
3be34541 143 for (c = 0, tmp = daemon->if_names; tmp; tmp = tmp->next)
de37951c
SK
144 if (!tmp->isloop)
145 c++;
146 if (c != 1)
b8187c80 147 die(_("must set exactly one interface on broken systems without IP_RECVIF"), NULL);
de37951c 148#endif
3be34541
SK
149 dhcp_init(daemon);
150 lease_init(daemon, now);
9e4abcb5 151 }
feba5c1d 152
3d8df260
SK
153 if (daemon->options & OPT_DBUS)
154#ifdef HAVE_DBUS
155 {
156 char *err;
157 daemon->dbus = NULL;
158 daemon->watches = NULL;
159 if ((err = dbus_init(daemon)))
b8187c80 160 die(_("DBus error: %s"), err);
3d8df260
SK
161 }
162#else
cdeda28f 163 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL);
3d8df260
SK
164#endif
165
feba5c1d
SK
166 /* If query_port is set then create a socket now, before dumping root
167 for use to access nameservers without more specific source addresses.
168 This allows query_port to be a low port */
3be34541 169 if (daemon->query_port)
feba5c1d
SK
170 {
171 union mysockaddr addr;
849a8357 172 memset(&addr, 0, sizeof(addr));
feba5c1d
SK
173 addr.in.sin_family = AF_INET;
174 addr.in.sin_addr.s_addr = INADDR_ANY;
3be34541 175 addr.in.sin_port = htons(daemon->query_port);
feba5c1d
SK
176#ifdef HAVE_SOCKADDR_SA_LEN
177 addr.in.sin_len = sizeof(struct sockaddr_in);
178#endif
3be34541 179 allocate_sfd(&addr, &daemon->sfds);
feba5c1d 180#ifdef HAVE_IPV6
849a8357 181 memset(&addr, 0, sizeof(addr));
feba5c1d
SK
182 addr.in6.sin6_family = AF_INET6;
183 addr.in6.sin6_addr = in6addr_any;
3be34541 184 addr.in6.sin6_port = htons(daemon->query_port);
feba5c1d
SK
185#ifdef HAVE_SOCKADDR_SA_LEN
186 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
187#endif
3be34541 188 allocate_sfd(&addr, &daemon->sfds);
feba5c1d
SK
189#endif
190 }
9e4abcb5 191
5e9e0efb 192 /* Use a pipe to carry signals back to the event loop in a race-free manner */
7cebd20f 193 if (pipe(pipefd) == -1 || !fix_fd(pipefd[0]) || !fix_fd(pipefd[1]))
5e9e0efb
SK
194 die(_("cannot create pipe: %s"), NULL);
195
196 piperead = pipefd[0];
197 pipewrite = pipefd[1];
198 /* prime the pipe to load stuff first time. */
199 sig = SIGHUP;
200 write(pipewrite, &sig, 1);
1697269c
SK
201
202 if (!(daemon->options & OPT_DEBUG))
9e4abcb5
SK
203 {
204 FILE *pidfile;
3d8df260 205 fd_set test_set;
1697269c 206 int maxfd = -1, i;
7cebd20f 207 int nullfd = open("/dev/null", O_RDWR);
5e9e0efb 208
9e4abcb5
SK
209 /* The following code "daemonizes" the process.
210 See Stevens section 12.4 */
1697269c
SK
211
212#ifndef NO_FORK
3be34541
SK
213 if (!(daemon->options & OPT_NO_FORK))
214 {
215 if (fork() != 0 )
7cebd20f 216 _exit(0);
3be34541
SK
217
218 setsid();
219
220 if (fork() != 0)
7cebd20f 221 _exit(0);
3be34541 222 }
9e4abcb5
SK
223#endif
224
225 chdir("/");
226 umask(022); /* make pidfile 0644 */
227
228 /* write pidfile _after_ forking ! */
3be34541 229 if (daemon->runfile && (pidfile = fopen(daemon->runfile, "w")))
9e4abcb5
SK
230 {
231 fprintf(pidfile, "%d\n", (int) getpid());
232 fclose(pidfile);
233 }
234
235 umask(0);
1697269c
SK
236
237 FD_ZERO(&test_set);
238 set_dns_listeners(daemon, now, &test_set, &maxfd);
239#ifdef HAVE_DBUS
240 set_dbus_listeners(daemon, &maxfd, &test_set, &test_set, &test_set);
241#endif
9e4abcb5
SK
242 for (i=0; i<64; i++)
243 {
5e9e0efb
SK
244 if (i == piperead || i == pipewrite)
245 continue;
246
247#ifdef HAVE_LINUX_NETWORK
248 if (i == daemon->netlinkfd)
9e4abcb5 249 continue;
3be34541 250#endif
3d8df260 251
3be34541 252 if (daemon->dhcp &&
208b65c5 253 ((daemon->lease_stream && i == fileno(daemon->lease_stream)) ||
5e9e0efb 254#ifndef HAVE_LINUX_NETWORK
3be34541 255 i == daemon->dhcp_raw_fd ||
5e9e0efb
SK
256 i == daemon->dhcp_icmp_fd ||
257#endif
258 i == daemon->dhcpfd))
3be34541 259 continue;
3d8df260
SK
260
261 if (i <= maxfd && FD_ISSET(i, &test_set))
feba5c1d
SK
262 continue;
263
7cebd20f
SK
264 /* open stdout etc to /dev/null */
265 if (i == STDOUT_FILENO || i == STDERR_FILENO || i == STDIN_FILENO)
266 dup2(nullfd, i);
267 else
268 close(i);
9e4abcb5 269 }
1697269c
SK
270 }
271
272 /* if we are to run scripts, we need to fork a helper before dropping root. */
273 daemon->helperfd = create_helper(daemon);
274
275 if (!(daemon->options & OPT_DEBUG))
276 {
277 /* UID changing, etc */
278 struct passwd *ent_pw = daemon->username ? getpwnam(daemon->username) : NULL;
279
7cebd20f 280 if (daemon->groupname || ent_pw)
9e4abcb5
SK
281 {
282 gid_t dummy;
283 struct group *gp;
7cebd20f
SK
284
285 /* change group for /etc/ppp/resolv.conf otherwise get the group for "nobody" */
3be34541 286 if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) ||
7cebd20f
SK
287 (ent_pw && (gp = getgrgid(ent_pw->pw_gid))))
288 {
289 /* remove all supplimentary groups */
290 setgroups(0, &dummy);
291 setgid(gp->gr_gid);
292 }
293 }
1697269c 294
7cebd20f 295 if (ent_pw && ent_pw->pw_uid != 0)
1697269c 296 {
5e9e0efb 297#ifdef HAVE_LINUX_NETWORK
1697269c
SK
298 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
299 CAP_NET_RAW (for icmp) if we're doing dhcp */
300 cap_user_header_t hdr = safe_malloc(sizeof(*hdr));
301 cap_user_data_t data = safe_malloc(sizeof(*data));
302 hdr->version = _LINUX_CAPABILITY_VERSION;
303 hdr->pid = 0; /* this process */
304 data->effective = data->permitted = data->inheritable =
305 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
306 (1 << CAP_SETGID) | (1 << CAP_SETUID);
5e9e0efb 307
1697269c
SK
308 /* Tell kernel to not clear capabilities when dropping root */
309 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1) == -1)
310 bad_capabilities = errno;
311 else
5e9e0efb 312#endif
1697269c
SK
313 {
314 /* finally drop root */
315 setuid(ent_pw->pw_uid);
316
317#ifdef HAVE_LINUX_NETWORK
318 data->effective = data->permitted =
319 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
320 data->inheritable = 0;
321
322 /* lose the setuid and setgid capbilities */
323 capset(hdr, data);
324#endif
325 }
9e4abcb5
SK
326 }
327 }
1697269c
SK
328
329 log_start(daemon);
330
331#ifdef HAVE_LINUX_NETWORK
332 if (daemon->options & OPT_DEBUG)
333 prctl(PR_SET_DUMPABLE, 1);
334#endif
9e4abcb5 335
3be34541 336 if (daemon->cachesize != 0)
b8187c80 337 syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
9e4abcb5 338 else
b8187c80 339 syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
1697269c 340
b8187c80 341 syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
1697269c 342
3d8df260
SK
343#ifdef HAVE_DBUS
344 if (daemon->options & OPT_DBUS)
345 {
346 if (daemon->dbus)
b8187c80 347 syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
3d8df260 348 else
b8187c80 349 syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
3d8df260
SK
350 }
351#endif
352
de37951c 353 if (bind_fallback)
b8187c80 354 syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
de37951c 355
26128d27
SK
356 if (!(daemon->options & OPT_NOWILD))
357 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
358 if (if_tmp->name && !if_tmp->used)
b8187c80 359 syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
5e9e0efb 360
208b65c5
SK
361 if (daemon->options & OPT_NO_RESOLV)
362 {
363 if (daemon->resolv_files && !daemon->resolv_files->is_default)
364 syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
365 daemon->resolv_files = NULL;
366 }
367
3be34541 368 if (daemon->dhcp)
9e4abcb5 369 {
3be34541 370 struct dhcp_context *dhcp_tmp;
0a852541 371
3be34541 372 for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
feba5c1d 373 {
0a852541 374 prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
3be34541 375 strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
3be34541 376 syslog(LOG_INFO,
0a852541 377 (dhcp_tmp->flags & CONTEXT_STATIC) ?
b8187c80
SK
378 _("DHCP, static leases only on %.0s%s, lease time %s") :
379 _("DHCP, IP range %s -- %s, lease time %s"),
0a852541 380 daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
feba5c1d 381 }
26128d27
SK
382 }
383
3be34541 384 if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
309331f5
SK
385 {
386 if (bad_capabilities)
387 {
388 errno = bad_capabilities;
389 syslog(LOG_WARNING, _("warning: setting capabilities failed: %m"));
390 }
391 syslog(LOG_WARNING, _("running as root"));
392 }
9e4abcb5 393
3d8df260 394 check_servers(daemon);
5e9e0efb 395
7cebd20f
SK
396 pid = getpid();
397
5e9e0efb 398 while (1)
9e4abcb5 399 {
1697269c 400 int maxfd = -1;
5e9e0efb 401 struct timeval t, *tp = NULL;
3d8df260 402 fd_set rset, wset, eset;
9e4abcb5
SK
403
404 FD_ZERO(&rset);
3d8df260
SK
405 FD_ZERO(&wset);
406 FD_ZERO(&eset);
9e4abcb5 407
1697269c
SK
408 /* if we are out of resources, find how long we have to wait
409 for some to come free, we'll loop around then and restart
410 listening for queries */
411 if ((t.tv_sec = set_dns_listeners(daemon, now, &rset, &maxfd)) != 0)
412 {
413 t.tv_usec = 0;
414 tp = &t;
415 }
416
3d8df260 417#ifdef HAVE_DBUS
5e9e0efb
SK
418 /* Whilst polling for the dbus, wake every quarter second */
419 if ((daemon->options & OPT_DBUS) && !daemon->dbus)
420 {
1697269c
SK
421 t.tv_sec = 0;
422 t.tv_usec = 250000;
5e9e0efb 423 tp = &t;
5e9e0efb 424 }
44a2a316 425
1697269c 426 set_dbus_listeners(daemon, &maxfd, &rset, &wset, &eset);
5e9e0efb
SK
427#endif
428
429 if (daemon->dhcp)
430 {
431 FD_SET(daemon->dhcpfd, &rset);
1697269c 432 bump_maxfd(daemon->dhcpfd, &maxfd);
5e9e0efb 433 }
cdeda28f 434
5e9e0efb
SK
435#ifdef HAVE_LINUX_NETWORK
436 FD_SET(daemon->netlinkfd, &rset);
1697269c 437 bump_maxfd(daemon->netlinkfd, &maxfd);
3d8df260 438#endif
3d8df260 439
5e9e0efb 440 FD_SET(piperead, &rset);
1697269c
SK
441 bump_maxfd(piperead, &maxfd);
442
443 while (helper_buf_empty() && do_script_run(daemon));
444
445 if (!helper_buf_empty())
446 {
447 FD_SET(daemon->helperfd, &wset);
448 bump_maxfd(daemon->helperfd, &maxfd);
449 }
450
5e9e0efb
SK
451 if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
452 {
453 /* otherwise undefined after error */
454 FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
455 }
456
457 now = dnsmasq_time();
9e4abcb5
SK
458
459 /* Check for changes to resolv files once per second max. */
3d8df260 460 /* Don't go silent for long periods if the clock goes backwards. */
849a8357 461 if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < -1.0)
9e4abcb5
SK
462 {
463 last = now;
33820b7e
SK
464
465#ifdef HAVE_ISC_READER
3be34541 466 if (daemon->lease_file && !daemon->dhcp)
fd9fa481 467 load_dhcp(daemon, now);
33820b7e
SK
468#endif
469
3be34541 470 if (!(daemon->options & OPT_NO_POLL))
9e4abcb5 471 {
208b65c5 472 struct resolvc *res, *latest;
9e4abcb5 473 struct stat statbuf;
33820b7e 474 time_t last_change = 0;
9e4abcb5
SK
475 /* There may be more than one possible file.
476 Go through and find the one which changed _last_.
477 Warn of any which can't be read. */
208b65c5
SK
478 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
479 if (stat(res->name, &statbuf) == -1)
480 {
481 if (!res->logged)
482 syslog(LOG_WARNING, _("failed to access %s: %m"), res->name);
483 res->logged = 1;
484 }
485 else
486 {
487 res->logged = 0;
488 if (statbuf.st_mtime != res->mtime)
489 {
490 res->mtime = statbuf.st_mtime;
491 if (difftime(statbuf.st_mtime, last_change) > 0.0)
492 {
493 last_change = statbuf.st_mtime;
494 latest = res;
495 }
496 }
497 }
498
3d8df260 499 if (latest)
9e4abcb5 500 {
849a8357
SK
501 static int warned = 0;
502 if (reload_servers(latest->name, daemon))
503 {
504 syslog(LOG_INFO, _("reading %s"), latest->name);
849a8357
SK
505 warned = 0;
506 check_servers(daemon);
1697269c
SK
507 if (daemon->options & OPT_RELOAD)
508 cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
849a8357 509 }
208b65c5 510 else
849a8357 511 {
208b65c5
SK
512 latest->mtime = 0;
513 if (!warned)
514 {
515 syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
516 warned = 1;
517 }
849a8357 518 }
9e4abcb5
SK
519 }
520 }
521 }
cdeda28f 522
5e9e0efb
SK
523 if (FD_ISSET(piperead, &rset))
524 {
7cebd20f
SK
525 pid_t p;
526
5e9e0efb
SK
527 if (read(piperead, &sig, 1) == 1)
528 switch (sig)
529 {
530 case SIGHUP:
7cebd20f 531 clear_cache_and_reload(daemon, now);
5e9e0efb
SK
532 if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
533 {
534 reload_servers(daemon->resolv_files->name, daemon);
535 check_servers(daemon);
536 }
537 break;
538
539 case SIGUSR1:
540 dump_cache(daemon, now);
541 break;
542
543 case SIGALRM:
544 if (daemon->dhcp)
7cebd20f
SK
545 {
546 lease_prune(NULL, now);
547 lease_update_file(daemon, now);
7cebd20f 548 }
5e9e0efb
SK
549 break;
550
551 case SIGTERM:
7cebd20f
SK
552 {
553 int i;
7cebd20f
SK
554 /* Knock all our children on the head. */
555 for (i = 0; i < MAX_PROCS; i++)
556 if (daemon->tcp_pids[i] != 0)
849a8357 557 kill(daemon->tcp_pids[i], SIGALRM);
7cebd20f 558
1697269c
SK
559 /* handle pending lease transitions */
560 if (daemon->helperfd != -1)
561 {
562 /* block in writes until all done */
563 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
564 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
565 do {
566 helper_write(daemon);
567 } while (!helper_buf_empty() || do_script_run(daemon));
568 close(daemon->helperfd);
569 }
570
208b65c5 571 if (daemon->lease_stream)
849a8357 572 fclose(daemon->lease_stream);
1697269c
SK
573
574 syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
7cebd20f
SK
575 exit(0);
576 }
5e9e0efb
SK
577
578 case SIGCHLD:
579 /* See Stevens 5.10 */
7cebd20f
SK
580 /* Note that if a script process forks and then exits
581 without waiting for its child, we will reap that child.
582 It is not therefore safe to assume that any dieing children
583 whose pid != script_pid are TCP server threads. */
584 while ((p = waitpid(-1, NULL, WNOHANG)) > 0)
585 {
1697269c
SK
586 int i;
587 for (i = 0 ; i < MAX_PROCS; i++)
588 if (daemon->tcp_pids[i] == p)
589 {
590 daemon->tcp_pids[i] = 0;
591 break;
592 }
7cebd20f 593 }
5e9e0efb 594 break;
5e9e0efb
SK
595 }
596 }
7cebd20f 597
5e9e0efb
SK
598#ifdef HAVE_LINUX_NETWORK
599 if (FD_ISSET(daemon->netlinkfd, &rset))
cdeda28f
SK
600 netlink_multicast(daemon);
601#endif
3d8df260
SK
602
603#ifdef HAVE_DBUS
604 /* if we didn't create a DBus connection, retry now. */
7cebd20f 605 if ((daemon->options & OPT_DBUS) && !daemon->dbus)
3d8df260
SK
606 {
607 char *err;
608 if ((err = dbus_init(daemon)))
b8187c80 609 syslog(LOG_WARNING, _("DBus error: %s"), err);
3d8df260 610 if (daemon->dbus)
b8187c80 611 syslog(LOG_INFO, _("connected to system DBus"));
3d8df260
SK
612 }
613 check_dbus_listeners(daemon, &rset, &wset, &eset);
614#endif
615
3be34541 616 check_dns_listeners(daemon, &rset, now);
9e4abcb5 617
3be34541
SK
618 if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
619 dhcp_packet(daemon, now);
1697269c
SK
620
621 if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
622 helper_write(daemon);
9e4abcb5 623 }
9e4abcb5
SK
624}
625
3be34541
SK
626static void sig_handler(int sig)
627{
5e9e0efb 628 if (pid == 0)
3be34541 629 {
1697269c
SK
630 /* ignore anything other than TERM during startup
631 and in helper proc. (helper ignore TERM too) */
5e9e0efb 632 if (sig == SIGTERM)
3be34541 633 exit(0);
3be34541 634 }
5e9e0efb 635 else if (pid == getpid())
3be34541 636 {
5e9e0efb
SK
637 /* master process */
638 unsigned char sigchr = sig;
639 int errsave = errno;
640 write(pipewrite, &sigchr, 1);
641 errno = errsave;
642 }
643 else
644 {
1697269c 645 /* alarm is used to kill TCP children after a fixed time. */
5e9e0efb 646 if (sig == SIGALRM)
7cebd20f 647 _exit(0);
3be34541
SK
648 }
649}
650
3d8df260 651
7cebd20f 652void clear_cache_and_reload(struct daemon *daemon, time_t now)
3d8df260
SK
653{
654 cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
655 if (daemon->dhcp)
656 {
657 if (daemon->options & OPT_ETHERS)
658 dhcp_read_ethers(daemon);
659 dhcp_update_configs(daemon->dhcp_conf);
b8187c80 660 lease_update_from_configs(daemon);
7cebd20f 661 lease_update_file(daemon, now);
3d8df260
SK
662 lease_update_dns(daemon);
663 }
664}
665
1697269c 666static int set_dns_listeners(struct daemon *daemon, time_t now, fd_set *set, int *maxfdp)
3be34541
SK
667{
668 struct serverfd *serverfdp;
669 struct listener *listener;
1697269c 670 int wait, i;
9e4abcb5 671
1697269c
SK
672 /* will we be able to get memory? */
673 get_new_frec(daemon, now, &wait);
674
3be34541
SK
675 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
676 {
677 FD_SET(serverfdp->fd, set);
1697269c 678 bump_maxfd(serverfdp->fd, maxfdp);
3be34541
SK
679 }
680
681 for (listener = daemon->listeners; listener; listener = listener->next)
682 {
1697269c
SK
683 /* only listen for queries if we have resources */
684 if (wait == 0)
685 {
686 FD_SET(listener->fd, set);
687 bump_maxfd(listener->fd, maxfdp);
688 }
689
690 /* death of a child goes through the select loop, so
691 we don't need to explicitly arrange to wake up here */
692 for (i = 0; i < MAX_PROCS; i++)
693 if (daemon->tcp_pids[i] == 0)
694 {
695 FD_SET(listener->tcpfd, set);
696 bump_maxfd(listener->tcpfd, maxfdp);
697 break;
698 }
3be34541 699 }
9e4abcb5 700
1697269c 701 return wait;
3be34541 702}
9e4abcb5 703
3be34541
SK
704static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
705{
706 struct serverfd *serverfdp;
707 struct listener *listener;
708
709 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
710 if (FD_ISSET(serverfdp->fd, set))
711 reply_query(serverfdp, daemon, now);
712
713 for (listener = daemon->listeners; listener; listener = listener->next)
714 {
715 if (FD_ISSET(listener->fd, set))
716 receive_query(listener, daemon, now);
717
718 if (FD_ISSET(listener->tcpfd, set))
719 {
720 int confd;
7cebd20f
SK
721 struct irec *iface = NULL;
722 pid_t p;
723
3be34541
SK
724 while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
725
7cebd20f
SK
726 if (confd == -1)
727 continue;
728
729 if (daemon->options & OPT_NOWILD)
730 iface = listener->iface;
731 else
3be34541 732 {
7cebd20f
SK
733 union mysockaddr tcp_addr;
734 socklen_t tcp_len = sizeof(union mysockaddr);
735 /* Check for allowed interfaces when binding the wildcard address:
736 we do this by looking for an interface with the same address as
737 the local address of the TCP connection, then looking to see if that's
738 an allowed interface. As a side effect, we get the netmask of the
739 interface too, for localisation. */
5e9e0efb 740
7cebd20f
SK
741 /* interface may be new since startup */
742 if (enumerate_interfaces(daemon) &&
743 getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
744 for (iface = daemon->interfaces; iface; iface = iface->next)
745 if (sockaddr_isequal(&iface->addr, &tcp_addr))
746 break;
747 }
748
1697269c 749 if (!iface)
7cebd20f
SK
750 {
751 shutdown(confd, SHUT_RDWR);
752 close(confd);
753 }
59353a6b 754#ifndef NO_FORK
7cebd20f
SK
755 else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
756 {
757 if (p != -1)
3be34541 758 {
7cebd20f
SK
759 int i;
760 for (i = 0; i < MAX_PROCS; i++)
761 if (daemon->tcp_pids[i] == 0)
762 {
763 daemon->tcp_pids[i] = p;
764 break;
765 }
3be34541 766 }
7cebd20f
SK
767 close(confd);
768 }
769#endif
770 else
771 {
772 unsigned char *buff;
773 struct server *s;
774 int flags;
775 struct in_addr dst_addr_4;
776
777 dst_addr_4.s_addr = 0;
778
779 /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
780 terminate the process. */
781 if (!(daemon->options & OPT_DEBUG))
782 alarm(CHILD_LIFETIME);
783
784 /* start with no upstream connections. */
785 for (s = daemon->servers; s; s = s->next)
786 s->tcpfd = -1;
787
788 /* The connected socket inherits non-blocking
789 attribute from the listening socket.
790 Reset that here. */
791 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
792 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
793
794 if (listener->family == AF_INET)
795 dst_addr_4 = iface->addr.in.sin_addr;
796
797 buff = tcp_request(daemon, confd, now, dst_addr_4, iface->netmask);
798
799 shutdown(confd, SHUT_RDWR);
800 close(confd);
801
802 if (buff)
803 free(buff);
804
805 for (s = daemon->servers; s; s = s->next)
806 if (s->tcpfd != -1)
807 {
808 shutdown(s->tcpfd, SHUT_RDWR);
809 close(s->tcpfd);
810 }
811#ifndef NO_FORK
812 if (!(daemon->options & OPT_DEBUG))
813 _exit(0);
59353a6b 814#endif
3be34541
SK
815 }
816 }
817 }
818}
819
7cebd20f 820
5e9e0efb
SK
821int make_icmp_sock(void)
822{
7cebd20f 823 int fd;
5e9e0efb
SK
824 int zeroopt = 0;
825
826 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
827 {
7cebd20f 828 if (!fix_fd(fd) ||
5e9e0efb
SK
829 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
830 {
831 close(fd);
832 fd = -1;
833 }
834 }
835
836 return fd;
837}
838
3be34541
SK
839int icmp_ping(struct daemon *daemon, struct in_addr addr)
840{
5e9e0efb 841 /* Try and get an ICMP echo from a machine. */
3be34541
SK
842
843 /* Note that whilst in the three second wait, we check for
844 (and service) events on the DNS sockets, (so doing that
845 better not use any resources our caller has in use...)
846 but we remain deaf to signals or further DHCP packets. */
847
5e9e0efb 848 int fd;
3be34541
SK
849 struct sockaddr_in saddr;
850 struct {
851 struct ip ip;
852 struct icmp icmp;
853 } packet;
854 unsigned short id = rand16();
855 unsigned int i, j;
5e9e0efb 856 int gotreply = 0;
3be34541 857 time_t start, now;
5e9e0efb
SK
858
859#ifdef HAVE_LINUX_NETWORK
860 if ((fd = make_icmp_sock()) == -1)
861 return 0;
862#else
863 int opt = 2000;
864 fd = daemon->dhcp_icmp_fd;
865 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
866#endif
867
3be34541
SK
868 saddr.sin_family = AF_INET;
869 saddr.sin_port = 0;
870 saddr.sin_addr = addr;
871#ifdef HAVE_SOCKADDR_SA_LEN
872 saddr.sin_len = sizeof(struct sockaddr_in);
873#endif
874
875 memset(&packet.icmp, 0, sizeof(packet.icmp));
876 packet.icmp.icmp_type = ICMP_ECHO;
877 packet.icmp.icmp_id = id;
878 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
879 j += ((u16 *)&packet.icmp)[i];
880 while (j>>16)
881 j = (j & 0xffff) + (j >> 16);
882 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
883
5e9e0efb 884 while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
fd9fa481
SK
885 (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
886 retry_send());
887
5e9e0efb
SK
888 for (now = start = dnsmasq_time();
889 difftime(now, start) < (float)PING_WAIT;)
fd9fa481
SK
890 {
891 struct timeval tv;
892 fd_set rset;
893 struct sockaddr_in faddr;
1697269c 894 int maxfd = fd;
3d8df260 895 socklen_t len = sizeof(faddr);
fd9fa481
SK
896
897 tv.tv_usec = 250000;
898 tv.tv_sec = 0;
899
900 FD_ZERO(&rset);
5e9e0efb 901 FD_SET(fd, &rset);
1697269c 902 set_dns_listeners(daemon, now, &rset, &maxfd);
3be34541 903
fd9fa481
SK
904 if (select(maxfd+1, &rset, NULL, NULL, &tv) < 0)
905 FD_ZERO(&rset);
906
5e9e0efb 907 now = dnsmasq_time();
fd9fa481
SK
908 check_dns_listeners(daemon, &rset, now);
909
5e9e0efb
SK
910 if (FD_ISSET(fd, &rset) &&
911 recvfrom(fd, &packet, sizeof(packet), 0,
fd9fa481
SK
912 (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
913 saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
914 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
915 packet.icmp.icmp_seq == 0 &&
916 packet.icmp.icmp_id == id)
917 {
918 gotreply = 1;
919 break;
920 }
921 }
922
5e9e0efb
SK
923#ifdef HAVE_LINUX_NETWORK
924 close(fd);
925#else
3be34541 926 opt = 1;
5e9e0efb
SK
927 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
928#endif
929
3be34541
SK
930 return gotreply;
931}
0a852541
SK
932
933