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