]> git.ipfire.org Git - people/ms/dnsmasq.git/blame - src/dnsmasq.c
import of dnsmasq-2.26.tar.gz
[people/ms/dnsmasq.git] / src / dnsmasq.c
CommitLineData
f6b7dc47 1/* dnsmasq is Copyright (c) 2000-2005 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/* Author's email: simon@thekelleys.org.uk */
14
15#include "dnsmasq.h"
16
3d8df260
SK
17static char *compile_opts =
18#ifndef HAVE_IPV6
19"no-"
20#endif
21"IPv6 "
22#ifndef HAVE_GETOPT_LONG
23"no-"
24#endif
25"GNU-getopt "
26#ifdef HAVE_BROKEN_RTC
27"no-RTC "
28#endif
e17fb629
SK
29#ifdef HAVE_RTNETLINK
30"RTNetlink "
31#endif
3d8df260
SK
32#ifndef HAVE_ISC_READER
33"no-"
34#endif
35"ISC-leasefile "
36#ifndef HAVE_DBUS
37"no-"
38#endif
b8187c80
SK
39"DBus "
40#ifdef NO_GETTEXT
41"no-"
42#endif
e17fb629 43"I18N ";
3d8df260 44
0a852541 45static volatile int sigterm, sighup, sigusr1, sigalarm, num_kids, in_child;
9e4abcb5 46
3be34541
SK
47static int set_dns_listeners(struct daemon *daemon, fd_set *set, int maxfd);
48static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now);
49static void sig_handler(int sig);
9e4abcb5
SK
50
51int main (int argc, char **argv)
52{
3be34541 53 struct daemon *daemon;
9e4abcb5 54 int first_loop = 1;
de37951c 55 int bind_fallback = 0;
9e4abcb5 56 time_t now, last = 0;
9e4abcb5
SK
57 struct sigaction sigact;
58 sigset_t sigmask;
26128d27 59 struct iname *if_tmp;
33820b7e 60
b8187c80
SK
61#ifndef NO_GETTEXT
62 setlocale(LC_ALL, "");
63 bindtextdomain("dnsmasq", LOCALEDIR);
64 textdomain("dnsmasq");
65#endif
66
9e4abcb5
SK
67 sighup = 1; /* init cache the first time through */
68 sigusr1 = 0; /* but don't dump */
9e4abcb5 69 sigterm = 0; /* or die */
44a2a316
SK
70#ifdef HAVE_BROKEN_RTC
71 sigalarm = 1; /* need regular lease dumps */
72#else
73 sigalarm = 0; /* or not */
74#endif
feba5c1d
SK
75 num_kids = 0;
76 in_child = 0;
9e4abcb5
SK
77
78 sigact.sa_handler = sig_handler;
79 sigact.sa_flags = 0;
80 sigemptyset(&sigact.sa_mask);
81 sigaction(SIGUSR1, &sigact, NULL);
9e4abcb5
SK
82 sigaction(SIGHUP, &sigact, NULL);
83 sigaction(SIGTERM, &sigact, NULL);
44a2a316 84 sigaction(SIGALRM, &sigact, NULL);
feba5c1d
SK
85 sigaction(SIGCHLD, &sigact, NULL);
86
87 /* ignore SIGPIPE */
88 sigact.sa_handler = SIG_IGN;
89 sigaction(SIGPIPE, &sigact, NULL);
9e4abcb5
SK
90
91 /* now block all the signals, they stay that way except
92 during the call to pselect */
93 sigaddset(&sigact.sa_mask, SIGUSR1);
9e4abcb5
SK
94 sigaddset(&sigact.sa_mask, SIGTERM);
95 sigaddset(&sigact.sa_mask, SIGHUP);
44a2a316 96 sigaddset(&sigact.sa_mask, SIGALRM);
feba5c1d 97 sigaddset(&sigact.sa_mask, SIGCHLD);
9e4abcb5
SK
98 sigprocmask(SIG_BLOCK, &sigact.sa_mask, &sigmask);
99
3d8df260 100 daemon = read_opts(argc, argv, compile_opts);
3be34541
SK
101
102 if (daemon->edns_pktsz < PACKETSZ)
103 daemon->edns_pktsz = PACKETSZ;
0a852541
SK
104 daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
105 daemon->edns_pktsz : DNSMASQ_PACKETSZ;
106 daemon->packet = safe_malloc(daemon->packet_buff_sz);
9e4abcb5 107
3be34541 108 if (!daemon->lease_file)
9e4abcb5 109 {
3be34541
SK
110 if (daemon->dhcp)
111 daemon->lease_file = LEASEFILE;
9e4abcb5 112 }
33820b7e 113#ifndef HAVE_ISC_READER
3be34541 114 else if (!daemon->dhcp)
b8187c80 115 die(_("ISC dhcpd integration not available: set HAVE_ISC_READER in src/config.h"), NULL);
33820b7e 116#endif
9e4abcb5 117
3d8df260 118 if (!enumerate_interfaces(daemon, &daemon->interfaces, NULL, NULL))
b8187c80 119 die(_("failed to find list of interfaces: %s"), NULL);
f6b7dc47 120
3be34541
SK
121 if (!(daemon->options & OPT_NOWILD) &&
122 !(daemon->listeners = create_wildcard_listeners(daemon->port)))
de37951c
SK
123 {
124 bind_fallback = 1;
3be34541 125 daemon->options |= OPT_NOWILD;
de37951c 126 }
9e4abcb5 127
3be34541 128 if (daemon->options & OPT_NOWILD)
de37951c 129 {
3d8df260 130 daemon->listeners = create_bound_listeners(daemon->interfaces, daemon->port);
de37951c 131
3be34541 132 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
de37951c 133 if (if_tmp->name && !if_tmp->used)
b8187c80 134 die(_("unknown interface %s"), if_tmp->name);
de37951c 135
3be34541 136 for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
de37951c
SK
137 if (!if_tmp->used)
138 {
3d8df260 139 prettyprint_addr(&if_tmp->addr, daemon->namebuff);
b8187c80 140 die(_("no interface with address %s"), daemon->namebuff);
de37951c
SK
141 }
142 }
143
9e4abcb5 144 forward_init(1);
3be34541 145 cache_init(daemon->cachesize, daemon->options & OPT_LOG);
44a2a316
SK
146
147#ifdef HAVE_BROKEN_RTC
3be34541 148 if ((daemon->uptime_fd = open(UPTIME, O_RDONLY)) == -1)
b8187c80 149 die(_("cannot open %s:%s"), UPTIME);
44a2a316
SK
150#endif
151
3be34541 152 now = dnsmasq_time(daemon->uptime_fd);
9e4abcb5 153
3be34541 154 if (daemon->dhcp)
9e4abcb5 155 {
de37951c
SK
156#if !defined(IP_PKTINFO) && !defined(IP_RECVIF)
157 int c;
158 struct iname *tmp;
3be34541 159 for (c = 0, tmp = daemon->if_names; tmp; tmp = tmp->next)
de37951c
SK
160 if (!tmp->isloop)
161 c++;
162 if (c != 1)
b8187c80 163 die(_("must set exactly one interface on broken systems without IP_RECVIF"), NULL);
de37951c 164#endif
3be34541
SK
165 dhcp_init(daemon);
166 lease_init(daemon, now);
9e4abcb5 167 }
feba5c1d 168
3d8df260
SK
169 if (daemon->options & OPT_DBUS)
170#ifdef HAVE_DBUS
171 {
172 char *err;
173 daemon->dbus = NULL;
174 daemon->watches = NULL;
175 if ((err = dbus_init(daemon)))
b8187c80 176 die(_("DBus error: %s"), err);
3d8df260
SK
177 }
178#else
179 if (daemon->options & OPT_DBUS)
b8187c80 180 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL);
3d8df260
SK
181#endif
182
feba5c1d
SK
183 /* If query_port is set then create a socket now, before dumping root
184 for use to access nameservers without more specific source addresses.
185 This allows query_port to be a low port */
3be34541 186 if (daemon->query_port)
feba5c1d
SK
187 {
188 union mysockaddr addr;
189 addr.in.sin_family = AF_INET;
190 addr.in.sin_addr.s_addr = INADDR_ANY;
3be34541 191 addr.in.sin_port = htons(daemon->query_port);
feba5c1d
SK
192#ifdef HAVE_SOCKADDR_SA_LEN
193 addr.in.sin_len = sizeof(struct sockaddr_in);
194#endif
3be34541 195 allocate_sfd(&addr, &daemon->sfds);
feba5c1d
SK
196#ifdef HAVE_IPV6
197 addr.in6.sin6_family = AF_INET6;
198 addr.in6.sin6_addr = in6addr_any;
3be34541 199 addr.in6.sin6_port = htons(daemon->query_port);
feba5c1d
SK
200 addr.in6.sin6_flowinfo = htonl(0);
201#ifdef HAVE_SOCKADDR_SA_LEN
202 addr.in6.sin6_len = sizeof(struct sockaddr_in6);
203#endif
3be34541 204 allocate_sfd(&addr, &daemon->sfds);
feba5c1d
SK
205#endif
206 }
9e4abcb5
SK
207
208 setbuf(stdout, NULL);
209
3be34541 210 if (!(daemon->options & OPT_DEBUG))
9e4abcb5
SK
211 {
212 FILE *pidfile;
213 struct passwd *ent_pw;
3d8df260
SK
214 fd_set test_set;
215 int maxfd, i;
216
217 FD_ZERO(&test_set);
218 maxfd = set_dns_listeners(daemon, &test_set, -1);
219#ifdef HAVE_DBUS
220 maxfd = set_dbus_listeners(daemon, maxfd, &test_set, &test_set, &test_set);
221#endif
222
9e4abcb5
SK
223 /* The following code "daemonizes" the process.
224 See Stevens section 12.4 */
3d8df260 225
9e4abcb5 226#ifndef NO_FORK
3be34541
SK
227 if (!(daemon->options & OPT_NO_FORK))
228 {
229 if (fork() != 0 )
230 exit(0);
231
232 setsid();
233
234 if (fork() != 0)
235 exit(0);
236 }
9e4abcb5
SK
237#endif
238
239 chdir("/");
240 umask(022); /* make pidfile 0644 */
241
242 /* write pidfile _after_ forking ! */
3be34541 243 if (daemon->runfile && (pidfile = fopen(daemon->runfile, "w")))
9e4abcb5
SK
244 {
245 fprintf(pidfile, "%d\n", (int) getpid());
246 fclose(pidfile);
247 }
248
249 umask(0);
250
251 for (i=0; i<64; i++)
252 {
3be34541
SK
253#ifdef HAVE_BROKEN_RTC
254 if (i == daemon->uptime_fd)
9e4abcb5 255 continue;
3be34541 256#endif
3d8df260 257
3be34541
SK
258 if (daemon->dhcp &&
259 (i == daemon->lease_fd ||
260 i == daemon->dhcpfd ||
261 i == daemon->dhcp_raw_fd ||
262 i == daemon->dhcp_icmp_fd))
263 continue;
3d8df260
SK
264
265 if (i <= maxfd && FD_ISSET(i, &test_set))
feba5c1d
SK
266 continue;
267
9e4abcb5
SK
268 close(i);
269 }
270
271 /* Change uid and gid for security */
3be34541 272 if (daemon->username && (ent_pw = getpwnam(daemon->username)))
9e4abcb5
SK
273 {
274 gid_t dummy;
275 struct group *gp;
276 /* remove all supplimentary groups */
277 setgroups(0, &dummy);
278 /* change group for /etc/ppp/resolv.conf
279 otherwise get the group for "nobody" */
3be34541 280 if ((daemon->groupname && (gp = getgrnam(daemon->groupname))) ||
9e4abcb5
SK
281 (gp = getgrgid(ent_pw->pw_gid)))
282 setgid(gp->gr_gid);
283 /* finally drop root */
284 setuid(ent_pw->pw_uid);
285 }
286 }
287
288 openlog("dnsmasq",
3be34541
SK
289 DNSMASQ_LOG_OPT(daemon->options & OPT_DEBUG),
290 DNSMASQ_LOG_FAC(daemon->options & OPT_DEBUG));
9e4abcb5 291
3be34541 292 if (daemon->cachesize != 0)
b8187c80 293 syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
9e4abcb5 294 else
b8187c80 295 syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
3d8df260 296
b8187c80 297 syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
3d8df260
SK
298
299#ifdef HAVE_DBUS
300 if (daemon->options & OPT_DBUS)
301 {
302 if (daemon->dbus)
b8187c80 303 syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
3d8df260 304 else
b8187c80 305 syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
3d8df260
SK
306 }
307#endif
308
de37951c 309 if (bind_fallback)
b8187c80 310 syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
de37951c 311
26128d27
SK
312 if (!(daemon->options & OPT_NOWILD))
313 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
314 if (if_tmp->name && !if_tmp->used)
b8187c80 315 syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
26128d27 316
3be34541 317 if (daemon->dhcp)
9e4abcb5 318 {
3be34541 319 struct dhcp_context *dhcp_tmp;
0a852541
SK
320
321#ifdef HAVE_RTNETLINK
322 /* Must do this after daemonizing so that the pid is right */
323 daemon->netlinkfd = netlink_init();
324#endif
325
3be34541 326 for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
feba5c1d 327 {
0a852541 328 prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
3be34541 329 strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
3be34541 330 syslog(LOG_INFO,
0a852541 331 (dhcp_tmp->flags & CONTEXT_STATIC) ?
b8187c80
SK
332 _("DHCP, static leases only on %.0s%s, lease time %s") :
333 _("DHCP, IP range %s -- %s, lease time %s"),
0a852541 334 daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
feba5c1d 335 }
26128d27 336
44a2a316 337#ifdef HAVE_BROKEN_RTC
0a852541
SK
338 daemon->min_leasetime = daemon->min_leasetime/3;
339 if (daemon->min_leasetime > (60 * 60 * 24))
340 daemon->min_leasetime = 60 * 60 * 24;
341 if (daemon->min_leasetime < 60)
342 daemon->min_leasetime = 60;
343 prettyprint_time(daemon->dhcp_buff2, daemon->min_leasetime);
b8187c80 344 syslog(LOG_INFO, _("DHCP, %s will be written every %s"), daemon->lease_file, daemon->dhcp_buff2);
44a2a316 345#endif
26128d27
SK
346 }
347
3be34541 348 if (!(daemon->options & OPT_DEBUG) && (getuid() == 0 || geteuid() == 0))
b8187c80 349 syslog(LOG_WARNING, _("running as root"));
9e4abcb5 350
3d8df260 351 check_servers(daemon);
3be34541 352
9e4abcb5
SK
353 while (sigterm == 0)
354 {
3d8df260 355 fd_set rset, wset, eset;
9e4abcb5
SK
356
357 if (sighup)
358 {
3d8df260 359 clear_cache_and_reload(daemon, now);
3be34541 360 if (daemon->resolv_files && (daemon->options & OPT_NO_POLL))
de37951c 361 {
3be34541 362 reload_servers(daemon->resolv_files->name, daemon);
3d8df260 363 check_servers(daemon);
de37951c 364 }
9e4abcb5
SK
365 sighup = 0;
366 }
367
368 if (sigusr1)
369 {
fd9fa481 370 dump_cache(daemon);
9e4abcb5
SK
371 sigusr1 = 0;
372 }
373
44a2a316 374 if (sigalarm)
9e4abcb5 375 {
3be34541 376 if (daemon->dhcp)
44a2a316
SK
377 {
378 lease_update_file(1, now);
379#ifdef HAVE_BROKEN_RTC
0a852541 380 alarm(daemon->min_leasetime);
44a2a316
SK
381#endif
382 }
383 sigalarm = 0;
9e4abcb5
SK
384 }
385
386 FD_ZERO(&rset);
3d8df260
SK
387 FD_ZERO(&wset);
388 FD_ZERO(&eset);
9e4abcb5
SK
389
390 if (!first_loop)
391 {
3d8df260
SK
392 int maxfd = set_dns_listeners(daemon, &rset, -1);
393#ifdef HAVE_DBUS
394 maxfd = set_dbus_listeners(daemon, maxfd, &rset, &wset, &eset);
395#endif
3be34541 396 if (daemon->dhcp)
9e4abcb5 397 {
3be34541
SK
398 FD_SET(daemon->dhcpfd, &rset);
399 if (daemon->dhcpfd > maxfd)
400 maxfd = daemon->dhcpfd;
9e4abcb5 401 }
44a2a316 402
3d8df260 403 /* Whilst polling for the dbus, wake every quarter second */
9e4abcb5 404#ifdef HAVE_PSELECT
3d8df260
SK
405 {
406 struct timespec *tp = NULL;
407#ifdef HAVE_DBUS
408 struct timespec t;
409 if ((daemon->options & OPT_DBUS) && !daemon->dbus)
410 {
411 tp = &t;
412 tp->tv_sec = 0;
413 tp->tv_nsec = 250000000;
414 }
415#endif
416 if (pselect(maxfd+1, &rset, &wset, &eset, tp, &sigmask) < 0)
417 {
418 /* otherwise undefined after error */
419 FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
420 }
421 }
9e4abcb5
SK
422#else
423 {
424 sigset_t save_mask;
3d8df260
SK
425 struct timeval *tp = NULL;
426#ifdef HAVE_DBUS
427 struct timeval t;
428 if ((daemon->options & OPT_DBUS) && !daemon->dbus)
429 {
430 tp = &t;
431 tp->tv_sec = 0;
432 tp->tv_usec = 250000;
433 }
434#endif
9e4abcb5 435 sigprocmask(SIG_SETMASK, &sigmask, &save_mask);
3d8df260
SK
436 if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
437 {
438 /* otherwise undefined after error */
439 FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
440 }
9e4abcb5 441 sigprocmask(SIG_SETMASK, &save_mask, NULL);
3d8df260 442
9e4abcb5
SK
443 }
444#endif
9e4abcb5 445 }
3d8df260 446
9e4abcb5 447 first_loop = 0;
3be34541 448 now = dnsmasq_time(daemon->uptime_fd);
9e4abcb5
SK
449
450 /* Check for changes to resolv files once per second max. */
3d8df260
SK
451 /* Don't go silent for long periods if the clock goes backwards. */
452 if (last == 0 || difftime(now, last) > 1.0 || difftime(now, last) < 1.0)
9e4abcb5
SK
453 {
454 last = now;
33820b7e
SK
455
456#ifdef HAVE_ISC_READER
3be34541 457 if (daemon->lease_file && !daemon->dhcp)
fd9fa481 458 load_dhcp(daemon, now);
33820b7e
SK
459#endif
460
3be34541 461 if (!(daemon->options & OPT_NO_POLL))
9e4abcb5 462 {
3be34541 463 struct resolvc *res = daemon->resolv_files, *latest = NULL;
9e4abcb5 464 struct stat statbuf;
33820b7e 465 time_t last_change = 0;
9e4abcb5
SK
466 /* There may be more than one possible file.
467 Go through and find the one which changed _last_.
468 Warn of any which can't be read. */
469 while (res)
470 {
471 if (stat(res->name, &statbuf) == -1)
472 {
473 if (!res->logged)
b8187c80 474 syslog(LOG_WARNING, _("failed to access %s: %m"), res->name);
9e4abcb5
SK
475 res->logged = 1;
476 }
477 else
478 {
479 res->logged = 0;
3d8df260 480 if (statbuf.st_mtime != res->mtime)
9e4abcb5 481 {
3d8df260
SK
482 res->mtime = statbuf.st_mtime;
483 if (difftime(res->mtime, last_change) > 0.0)
484 {
485 last_change = res->mtime;
486 latest = res;
487 }
9e4abcb5
SK
488 }
489 }
490 res = res->next;
491 }
492
3d8df260 493 if (latest)
9e4abcb5 494 {
3be34541 495 reload_servers(latest->name, daemon);
3d8df260 496 check_servers(daemon);
9e4abcb5
SK
497 }
498 }
499 }
3d8df260
SK
500
501#ifdef HAVE_DBUS
502 /* if we didn't create a DBus connection, retry now. */
503 if ((daemon->options & OPT_DBUS) && !daemon->dbus)
504 {
505 char *err;
506 if ((err = dbus_init(daemon)))
b8187c80 507 syslog(LOG_WARNING, _("DBus error: %s"), err);
3d8df260 508 if (daemon->dbus)
b8187c80 509 syslog(LOG_INFO, _("connected to system DBus"));
3d8df260
SK
510 }
511 check_dbus_listeners(daemon, &rset, &wset, &eset);
512#endif
513
3be34541 514 check_dns_listeners(daemon, &rset, now);
9e4abcb5 515
3be34541
SK
516 if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
517 dhcp_packet(daemon, now);
9e4abcb5
SK
518 }
519
b8187c80 520 syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
3d8df260 521
3be34541
SK
522 if (daemon->dhcp)
523 {
44a2a316 524#ifdef HAVE_BROKEN_RTC
3be34541 525 lease_update_file(1, now);
44a2a316 526#endif
3be34541
SK
527 close(daemon->lease_fd);
528 }
529
9e4abcb5
SK
530 return 0;
531}
532
3be34541
SK
533static void sig_handler(int sig)
534{
535 if (sig == SIGTERM)
536 sigterm = 1;
537 else if (sig == SIGHUP)
538 sighup = 1;
539 else if (sig == SIGUSR1)
540 sigusr1 = 1;
541 else if (sig == SIGALRM)
542 {
543 /* alarm is used to kill children after a fixed time. */
544 if (in_child)
545 exit(0);
546 else
547 sigalarm = 1;
548 }
549 else if (sig == SIGCHLD)
550 {
551 /* See Stevens 5.10 */
552
553 while (waitpid(-1, NULL, WNOHANG) > 0)
554 num_kids--;
555 }
556}
557
3d8df260
SK
558
559void clear_cache_and_reload(struct daemon *daemon, time_t now)
560{
561 cache_reload(daemon->options, daemon->namebuff, daemon->domain_suffix, daemon->addn_hosts);
562 if (daemon->dhcp)
563 {
564 if (daemon->options & OPT_ETHERS)
565 dhcp_read_ethers(daemon);
566 dhcp_update_configs(daemon->dhcp_conf);
b8187c80 567 lease_update_from_configs(daemon);
3d8df260
SK
568 lease_update_file(0, now);
569 lease_update_dns(daemon);
570 }
571}
572
3be34541
SK
573static int set_dns_listeners(struct daemon *daemon, fd_set *set, int maxfd)
574{
575 struct serverfd *serverfdp;
576 struct listener *listener;
9e4abcb5 577
3be34541
SK
578 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
579 {
580 FD_SET(serverfdp->fd, set);
581 if (serverfdp->fd > maxfd)
582 maxfd = serverfdp->fd;
583 }
584
585 for (listener = daemon->listeners; listener; listener = listener->next)
586 {
587 FD_SET(listener->fd, set);
588 if (listener->fd > maxfd)
589 maxfd = listener->fd;
590 FD_SET(listener->tcpfd, set);
591 if (listener->tcpfd > maxfd)
592 maxfd = listener->tcpfd;
593 }
9e4abcb5 594
3be34541
SK
595 return maxfd;
596}
9e4abcb5 597
3be34541
SK
598static void check_dns_listeners(struct daemon *daemon, fd_set *set, time_t now)
599{
600 struct serverfd *serverfdp;
601 struct listener *listener;
602
603 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
604 if (FD_ISSET(serverfdp->fd, set))
605 reply_query(serverfdp, daemon, now);
606
607 for (listener = daemon->listeners; listener; listener = listener->next)
608 {
609 if (FD_ISSET(listener->fd, set))
610 receive_query(listener, daemon, now);
611
612 if (FD_ISSET(listener->tcpfd, set))
613 {
614 int confd;
f6b7dc47 615 struct in_addr netmask, dst_addr_4;
3be34541
SK
616
617 while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
618
619 if (confd != -1)
620 {
f6b7dc47
SK
621 union mysockaddr tcp_addr;
622 socklen_t tcp_len = sizeof(union mysockaddr);
623
624 /* Check for allowed interfaces when binding the wildcard address:
625 we do this by looking for an interface with the same address as
626 the local address of the TCP connection, then looking to see if that's
627 an allowed interface. As a side effect, we get the netmask of the
628 interface too, for localisation. */
629
630 if ((num_kids >= MAX_PROCS) ||
631 (!(daemon->options & OPT_NOWILD) &&
632 (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1 ||
633 !enumerate_interfaces(daemon, NULL, &tcp_addr, &netmask))))
3be34541 634 close(confd);
59353a6b 635#ifndef NO_FORK
3be34541
SK
636 else if (!(daemon->options & OPT_DEBUG) && fork())
637 {
638 num_kids++;
639 close(confd);
640 }
59353a6b 641#endif
3be34541
SK
642 else
643 {
3d8df260 644 unsigned char *buff;
3be34541
SK
645 struct server *s;
646 int flags;
647
648 /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
649 terminate the process. */
650 if (!(daemon->options & OPT_DEBUG))
651 {
652 sigset_t mask;
653 sigemptyset(&mask);
654 sigaddset(&mask, SIGALRM);
655 sigprocmask(SIG_UNBLOCK, &mask, NULL);
656 alarm(CHILD_LIFETIME);
657 in_child = 1;
658 }
659
660 /* start with no upstream connections. */
661 for (s = daemon->servers; s; s = s->next)
662 s->tcpfd = -1;
663
664 /* The connected socket inherits non-blocking
665 attribute from the listening socket.
666 Reset that here. */
667 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
668 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
669
f6b7dc47
SK
670 if (listener->family == AF_INET)
671 {
672 if (daemon->options & OPT_NOWILD)
673 {
674 netmask = listener->iface->netmask;
675 dst_addr_4 = listener->iface->addr.in.sin_addr;
676 }
677 else
678 /* netmask already set by enumerate_interfaces */
679 dst_addr_4 = tcp_addr.in.sin_addr;
680 }
681 else
682 dst_addr_4.s_addr = 0;
683
684 buff = tcp_request(daemon, confd, now, dst_addr_4, netmask);
3be34541
SK
685
686 if (!(daemon->options & OPT_DEBUG))
687 exit(0);
688
689 close(confd);
690 if (buff)
691 free(buff);
692 for (s = daemon->servers; s; s = s->next)
693 if (s->tcpfd != -1)
694 close(s->tcpfd);
695 }
696 }
697 }
698 }
699}
700
701int icmp_ping(struct daemon *daemon, struct in_addr addr)
702{
703 /* Try and get an ICMP echo from a machine.
704 Note that we can't create the raw socket each time
705 we do this, since that needs root. Therefore the socket has to hang
706 around all the time. Since most of the time we won't read the
707 socket, it will accumulate buffers full of ICMP messages,
708 wasting memory. To avoid that we set the receive buffer
709 length to zero except when we're actively pinging. */
710
711 /* Note that whilst in the three second wait, we check for
712 (and service) events on the DNS sockets, (so doing that
713 better not use any resources our caller has in use...)
714 but we remain deaf to signals or further DHCP packets. */
715
716 struct sockaddr_in saddr;
717 struct {
718 struct ip ip;
719 struct icmp icmp;
720 } packet;
721 unsigned short id = rand16();
722 unsigned int i, j;
723 int opt = 2000, gotreply = 0;
724 time_t start, now;
725
726 saddr.sin_family = AF_INET;
727 saddr.sin_port = 0;
728 saddr.sin_addr = addr;
729#ifdef HAVE_SOCKADDR_SA_LEN
730 saddr.sin_len = sizeof(struct sockaddr_in);
731#endif
732
733 memset(&packet.icmp, 0, sizeof(packet.icmp));
734 packet.icmp.icmp_type = ICMP_ECHO;
735 packet.icmp.icmp_id = id;
736 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
737 j += ((u16 *)&packet.icmp)[i];
738 while (j>>16)
739 j = (j & 0xffff) + (j >> 16);
740 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
741
742 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
743
fd9fa481
SK
744 while (sendto(daemon->dhcp_icmp_fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
745 (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
746 retry_send());
747
748 for (now = start = dnsmasq_time(daemon->uptime_fd); difftime(now, start) < 3.0;)
749 {
750 struct timeval tv;
751 fd_set rset;
752 struct sockaddr_in faddr;
3d8df260
SK
753 int maxfd;
754 socklen_t len = sizeof(faddr);
fd9fa481
SK
755
756 tv.tv_usec = 250000;
757 tv.tv_sec = 0;
758
759 FD_ZERO(&rset);
760 FD_SET(daemon->dhcp_icmp_fd, &rset);
761 maxfd = set_dns_listeners(daemon, &rset, daemon->dhcp_icmp_fd);
3be34541 762
fd9fa481
SK
763 if (select(maxfd+1, &rset, NULL, NULL, &tv) < 0)
764 FD_ZERO(&rset);
765
766 now = dnsmasq_time(daemon->uptime_fd);
767 check_dns_listeners(daemon, &rset, now);
768
769 if (FD_ISSET(daemon->dhcp_icmp_fd, &rset) &&
770 recvfrom(daemon->dhcp_icmp_fd, &packet, sizeof(packet), 0,
771 (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
772 saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
773 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
774 packet.icmp.icmp_seq == 0 &&
775 packet.icmp.icmp_id == id)
776 {
777 gotreply = 1;
778 break;
779 }
780 }
781
3be34541
SK
782 opt = 1;
783 setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
fd9fa481 784
3be34541
SK
785 return gotreply;
786}
0a852541
SK
787
788