1ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat/* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
3ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is free software; you can redistribute it and/or modify
4ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   it under the terms of the GNU General Public License as published by
5ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   the Free Software Foundation; version 2 dated June, 1991, or
6ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   (at your option) version 3 dated 29 June, 2007.
7ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
8ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   This program is distributed in the hope that it will be useful,
9ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   but WITHOUT ANY WARRANTY; without even the implied warranty of
10ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   GNU General Public License for more details.
12ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
13ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   You should have received a copy of the GNU General Public License
14ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat*/
16ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
17ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#include "dnsmasq.h"
18ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
19ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstruct daemon *daemon;
20ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
21ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic char *compile_opts =
22ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_IPV6
23ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
24ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
25ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"IPv6 "
26ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_GETOPT_LONG
27ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
28ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
29ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"GNU-getopt "
30ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_BROKEN_RTC
31ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-RTC "
32ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
33ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef NO_FORK
34ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-MMU "
35ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
36ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_DBUS
37ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
38ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
39ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"DBus "
40ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef LOCALEDIR
41ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
42ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
43ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"I18N "
44ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_DHCP
45ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
46ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
47ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"DHCP "
48ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
49ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-scripts "
50ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
51ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_TFTP
52ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"no-"
53ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
54ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat"TFTP";
55ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
56ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
57ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
58ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic volatile pid_t pid = 0;
59ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic volatile int pipewrite;
60ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
61ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
62ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void check_dns_listeners(fd_set *set, time_t now);
63ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void sig_handler(int sig);
64ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void async_event(int pipe, time_t now);
65ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void fatal_event(struct event_desc *ev);
66ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void poll_resolv(void);
6733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__
6833b344454b95ed99bad7d3fe4d493870923deaf6San Mehatstatic int set_android_listeners(fd_set *set, int *maxfdp);
6933b344454b95ed99bad7d3fe4d493870923deaf6San Mehatstatic int check_android_listeners(fd_set *set);
7033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
71ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
72ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint main (int argc, char **argv)
73ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
74ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int bind_fallback = 0;
75ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  time_t now;
76ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct sigaction sigact;
77ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct iname *if_tmp;
78ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int piperead, pipefd[2], err_pipe[2];
79ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct passwd *ent_pw = NULL;
80ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
81ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  uid_t script_uid = 0;
82ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  gid_t script_gid = 0;
83ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
84ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct group *gp = NULL;
85ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  long i, max_fd = sysconf(_SC_OPEN_MAX);
86ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  char *baduser = NULL;
87ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int log_err;
88ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK)
89ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  cap_user_header_t hdr = NULL;
90ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  cap_user_data_t data = NULL;
91ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
92ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
93ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef LOCALEDIR
94ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  setlocale(LC_ALL, "");
95ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  bindtextdomain("dnsmasq", LOCALEDIR);
96ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  textdomain("dnsmasq");
97ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
98ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
99ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigact.sa_handler = sig_handler;
100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigact.sa_flags = 0;
101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigemptyset(&sigact.sa_mask);
102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGUSR1, &sigact, NULL);
103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGUSR2, &sigact, NULL);
104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGHUP, &sigact, NULL);
105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGTERM, &sigact, NULL);
106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGALRM, &sigact, NULL);
107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGCHLD, &sigact, NULL);
108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* ignore SIGPIPE */
110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigact.sa_handler = SIG_IGN;
111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  sigaction(SIGPIPE, &sigact, NULL);
112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  umask(022); /* known umask, create leases and pid files as 0644 */
114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  read_opts(argc, argv, compile_opts);
116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->edns_pktsz < PACKETSZ)
118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    daemon->edns_pktsz = PACKETSZ;
119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    daemon->edns_pktsz : DNSMASQ_PACKETSZ;
121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->packet = safe_malloc(daemon->packet_buff_sz);
122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!daemon->lease_file)
125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dhcp)
127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->lease_file = LEASEFILE;
128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Close any file descriptors we inherited apart from std{in|out|err} */
132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (i = 0; i < max_fd; i++)
133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      close(i);
135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK
137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  netlink_init();
138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#elif !(defined(IP_RECVDSTADDR) && \
139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	defined(IP_RECVIF) && \
140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	defined(IP_SENDSRCADDR))
141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(daemon->options & OPT_NOWILD))
142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      bind_fallback = 1;
144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->options |= OPT_NOWILD;
145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef HAVE_TFTP
149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_TFTP)
150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOLARIS_NETWORK
154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->max_logs != 0)
155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  rand_init();
159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  now = dnsmasq_time();
161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp)
164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Note that order matters here, we must call lease_init before
166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 creating any file descriptors which shouldn't be leaked
167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 to the lease-script init process. */
168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      lease_init(now);
169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dhcp_init();
170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!enumerate_interfaces())
174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_NOWILD)
177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->listeners = create_bound_listeners();
179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (if_tmp->name && !if_tmp->used)
182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!if_tmp->used)
186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    prettyprint_addr(&if_tmp->addr, daemon->namebuff);
188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) &&
192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   !(daemon->listeners = create_wildcard_listeners()))
193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0)
196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    cache_init();
197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_DBUS)
199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS
200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      char *err;
202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->dbus = NULL;
203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->watches = NULL;
204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((err = dbus_init()))
205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("DBus error: %s"), err, EC_MISC);
206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0)
212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    pre_allocate_sfds();
213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Note getpwnam returns static storage */
216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser)
217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((ent_pw = getpwnam(daemon->scriptuser)))
219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  script_uid = ent_pw->pw_uid;
221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  script_gid = ent_pw->pw_gid;
222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 }
223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	baduser = daemon->scriptuser;
225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    baduser = daemon->username;
230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    baduser = daemon->groupname;
232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (baduser)
234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    die(_("unknown user or group: %s"), baduser, EC_BADCONF);
235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* implement group defaults, "dip" if available, or group associated with uid */
237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!daemon->group_set && !gp)
238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!(gp = getgrnam(CHGRP)) && ent_pw)
240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	gp = getgrgid(ent_pw->pw_gid);
241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* for error message */
243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (gp)
244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	daemon->groupname = gp->gr_name;
245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK)
248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* determine capability API version here, while we can still
249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     call safe_malloc */
250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (ent_pw && ent_pw->pw_uid != 0)
251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int capsize = 1; /* for header version 1 */
253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      hdr = safe_malloc(sizeof(*hdr));
254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* find version supported by kernel */
256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      memset(hdr, 0, sizeof(*hdr));
257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      capget(hdr, NULL);
258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (hdr->version != LINUX_CAPABILITY_VERSION_1)
260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* if unknown version, use largest supported version (3) */
262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (hdr->version != LINUX_CAPABILITY_VERSION_2)
263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    hdr->version = LINUX_CAPABILITY_VERSION_3;
264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  capsize = 2;
265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      data = safe_malloc(sizeof(*data) * capsize);
268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      memset(data, 0, sizeof(*data) * capsize);
269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Use a pipe to carry signals and other events back to the event loop
273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     in a race-free manner and another to carry errors to daemon-invoking process */
274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  safe_pipe(pipefd, 1);
275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  piperead = pipefd[0];
277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  pipewrite = pipefd[1];
278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* prime the pipe to load stuff first time. */
279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  send_event(pipewrite, EVENT_RELOAD, 0);
280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  err_pipe[1] = -1;
282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(daemon->options & OPT_DEBUG))
284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
28533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifndef __ANDROID__
286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int nullfd;
28733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* The following code "daemonizes" the process.
290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 See Stevens section 12.4 */
291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (chdir("/") != 0)
293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef NO_FORK
296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!(daemon->options & OPT_NO_FORK))
297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  pid_t pid;
299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* pipe to carry errors back to original process.
301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     When startup is complete we close this and the process terminates. */
302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  safe_pipe(err_pipe, 0);
303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((pid = fork()) == -1)
305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* fd == -1 since we've not forked, never returns. */
306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    send_event(-1, EVENT_FORK_ERR, errno);
307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (pid != 0)
309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      struct event_desc ev;
311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* close our copy of write-end */
313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      close(err_pipe[1]);
314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* check for errors after the fork */
316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (read_write(err_pipe[0], (unsigned char *)&ev, sizeof(ev), 1))
317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		fatal_event(&ev);
318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      _exit(EC_GOOD);
320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  close(err_pipe[0]);
323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* NO calls to die() from here on. */
325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  setsid();
327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((pid = fork()) == -1)
329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    send_event(err_pipe[1], EVENT_FORK_ERR, errno);
330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (pid != 0)
332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    _exit(0);
333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* write pidfile _after_ forking ! */
337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->runfile)
338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FILE *pidfile;
340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* only complain if started as root */
342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((pidfile = fopen(daemon->runfile, "w")))
343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      fprintf(pidfile, "%d\n", (int) getpid());
345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      fclose(pidfile);
346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (getuid() == 0)
348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      send_event(err_pipe[1], EVENT_PIDFILE, errno);
350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      _exit(0);
351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
35333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
35433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifndef __ANDROID__
355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* open  stdout etc to /dev/null */
356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      nullfd = open("/dev/null", O_RDWR);
357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dup2(nullfd, STDOUT_FILENO);
358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dup2(nullfd, STDERR_FILENO);
359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dup2(nullfd, STDIN_FILENO);
360ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      close(nullfd);
36133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
362ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
363ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
364ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   log_err = log_start(ent_pw, err_pipe[1]);
365ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
366ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat   /* if we are to run scripts, we need to fork a helper before dropping root. */
367ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  daemon->helperfd = -1;
368ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
369ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp && daemon->lease_change_command)
370ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
371ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
372ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
373ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(daemon->options & OPT_DEBUG) && getuid() == 0)
374ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
375ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int bad_capabilities = 0;
376ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      gid_t dummy;
377ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
378ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* remove all supplimentary groups */
379ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (gp &&
380ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  (setgroups(0, &dummy) == -1 ||
381ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   setgid(gp->gr_gid) == -1))
382ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
383ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
384ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  _exit(0);
385ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
386ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
387ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (ent_pw && ent_pw->pw_uid != 0)
388ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
389ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK)
390ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
391ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	     CAP_NET_RAW (for icmp) if we're doing dhcp */
392ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  data->effective = data->permitted = data->inheritable =
39341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID__
39441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt	    (1 << CAP_NET_BIND_SERVICE) |
39541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif
396ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
397ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
398ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* Tell kernel to not clear capabilities when dropping root */
3995658bcb797978c3472335d93554405aba8236f66San Mehat	  if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
400ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    bad_capabilities = errno;
401ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
402ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#elif defined(HAVE_SOLARIS_NETWORK)
403ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* http://developers.sun.com/solaris/articles/program_privileges.html */
404ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  priv_set_t *priv_set;
405ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
406ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
407ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
408ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
409ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    bad_capabilities = errno;
410ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
411ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (priv_set && bad_capabilities == 0)
412ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
413ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      priv_inverse(priv_set);
414ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
415ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
416ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		bad_capabilities = errno;
417ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
418ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
419ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (priv_set)
420ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    priv_freeset(priv_set);
421ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
422ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
423ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
424ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (bad_capabilities != 0)
425ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
426ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
427ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      _exit(0);
428ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
429ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
430ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* finally drop root */
431ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (setuid(ent_pw->pw_uid) == -1)
432ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
433ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      send_event(err_pipe[1], EVENT_USER_ERR, errno);
434ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      _exit(0);
435ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
436ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
437ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK
438ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  data->effective = data->permitted =
43941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#ifdef __ANDROID__
44041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt	    (1 << CAP_NET_BIND_SERVICE) |
44141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt#endif
442ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
443ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  data->inheritable = 0;
444ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
445ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* lose the setuid and setgid capbilities */
446ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (capset(hdr, data) == -1)
447ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
448ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      send_event(err_pipe[1], EVENT_CAP_ERR, errno);
449ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      _exit(0);
450ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
451ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
452ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
453ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
454ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
455ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
456ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK
457ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_DEBUG)
4585658bcb797978c3472335d93554405aba8236f66San Mehat    prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
459ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
460ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
461ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port == 0)
462ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
463ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (daemon->cachesize != 0)
464ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
465ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
466ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
467ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
468ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
469ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
470ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS
471ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_DBUS)
472ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
473ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dbus)
474ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
475ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
476ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
477ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
478ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
479ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
480ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (log_err != 0)
481ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
482ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      daemon->log_file, strerror(log_err));
483ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
484ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (bind_fallback)
485ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
486ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
487ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (!(daemon->options & OPT_NOWILD))
488ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
489ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (if_tmp->name && !if_tmp->used)
490ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
491ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
492ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0 && (daemon->options & OPT_NO_RESOLV))
493ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
494ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->resolv_files && !daemon->resolv_files->is_default)
495ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
496ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      daemon->resolv_files = NULL;
497ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!daemon->servers)
498ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
499ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
500ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
501ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->max_logs != 0)
502ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
503ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
504ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
505ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp)
506ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
507ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct dhcp_context *dhcp_tmp;
508ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
509ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next)
510ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
511ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
512ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
513ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  my_syslog(MS_DHCP | LOG_INFO,
514ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    (dhcp_tmp->flags & CONTEXT_STATIC) ?
515ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    _("DHCP, static leases only on %.0s%s, lease time %s") :
516ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    (dhcp_tmp->flags & CONTEXT_PROXY) ?
517ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    _("DHCP, proxy on subnet %.0s%s%.0s") :
518ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    _("DHCP, IP range %s -- %s, lease time %s"),
519ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
520ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
521ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
522ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
523ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
524ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
525ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->options & OPT_TFTP)
526ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
527ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef FD_SETSIZE
528ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (FD_SETSIZE < (unsigned)max_fd)
529ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	max_fd = FD_SETSIZE;
530ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
531ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
532ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
533ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->tftp_prefix ? _("root is ") : _("enabled"),
534ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->tftp_prefix ? daemon->tftp_prefix: "",
535ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
536ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
537ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* This is a guess, it assumes that for small limits,
538ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 disjoint files might be served, but for large limits,
539ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 a single file will be sent to may clients (the file only needs
540ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 one fd). */
541ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
542ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      max_fd -= 30; /* use other than TFTP */
543ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
544ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (max_fd < 0)
545ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	max_fd = 5;
546ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (max_fd < 100)
547ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	max_fd = max_fd/2;
548ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
549ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	max_fd = max_fd - 20;
550ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
551ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* if we have to use a limited range of ports,
552ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 that will limit the number of transfers */
553ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->start_tftp_port != 0 &&
554ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
555ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
556ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
557ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->tftp_max > max_fd)
558ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
559ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->tftp_max = max_fd;
560ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  my_syslog(MS_TFTP | LOG_WARNING,
561ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    _("restricting maximum simultaneous TFTP transfers to %d"),
562ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    daemon->tftp_max);
563ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
564ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
565ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
566ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
567ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* finished start-up - release original process */
568ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (err_pipe[1] != -1)
569ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    close(err_pipe[1]);
570ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
571ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0)
572ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    check_servers();
573ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
574ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  pid = getpid();
575ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
576ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (1)
577ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
578ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int maxfd = -1;
579ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct timeval t, *tp = NULL;
580ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      fd_set rset, wset, eset;
581ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
582ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_ZERO(&rset);
583ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_ZERO(&wset);
584ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_ZERO(&eset);
585ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
586ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* if we are out of resources, find how long we have to wait
587ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 for some to come free, we'll loop around then and restart
588ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 listening for queries */
589ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
590ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
591ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  t.tv_usec = 0;
592ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  tp = &t;
593ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
59433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__
59533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat      set_android_listeners(&rset, &maxfd);
59633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
597ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
598ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
599ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->tftp_trans ||
600ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  ((daemon->options & OPT_DBUS) && !daemon->dbus))
601ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
602ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  t.tv_sec = 0;
603ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  t.tv_usec = 250000;
604ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  tp = &t;
605ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
606ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
607ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS
608ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      set_dbus_listeners(&maxfd, &rset, &wset, &eset);
609ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
610ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
611ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
612ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dhcp)
613ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
614ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_SET(daemon->dhcpfd, &rset);
615ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  bump_maxfd(daemon->dhcpfd, &maxfd);
616ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
617ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
618ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
619ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK
620ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_SET(daemon->netlinkfd, &rset);
621ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      bump_maxfd(daemon->netlinkfd, &maxfd);
622ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
623ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
624ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_SET(piperead, &rset);
625ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      bump_maxfd(piperead, &maxfd);
626ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
627ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
628ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  ifdef HAVE_SCRIPT
629ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      while (helper_buf_empty() && do_script_run(now));
630ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
631ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!helper_buf_empty())
632ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
633ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_SET(daemon->helperfd, &wset);
634ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  bump_maxfd(daemon->helperfd, &maxfd);
635ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
636ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  else
637ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* need this for other side-effects */
638ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      while (do_script_run(now));
639ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  endif
640ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
641ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
642ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* must do this just before select(), when we know no
643ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 more calls to my_syslog() can occur */
644ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      set_log_writer(&wset, &maxfd);
645ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
646ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
647ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
648ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  /* otherwise undefined after error */
649ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
650ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
651ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
652ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      now = dnsmasq_time();
653ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
654ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_log_writer(&wset);
655ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
656ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Check for changes to resolv files once per second max. */
657ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* Don't go silent for long periods if the clock goes backwards. */
658ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->last_resolv == 0 ||
659ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  difftime(now, daemon->last_resolv) > 1.0 ||
660ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  difftime(now, daemon->last_resolv) < -1.0)
661ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
662ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  daemon->last_resolv = now;
663ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
664ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
665ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    poll_resolv();
666ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
667ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
668ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (FD_ISSET(piperead, &rset))
669ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	async_event(piperead, now);
670ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
671ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_LINUX_NETWORK
672ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (FD_ISSET(daemon->netlinkfd, &rset))
673ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	netlink_multicast();
674ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
675ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
676ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DBUS
677ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* if we didn't create a DBus connection, retry now. */
678ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     if ((daemon->options & OPT_DBUS) && !daemon->dbus)
679ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
680ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  char *err;
681ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if ((err = dbus_init()))
682ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    my_syslog(LOG_WARNING, _("DBus error: %s"), err);
683ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->dbus)
684ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    my_syslog(LOG_INFO, _("connected to system DBus"));
685ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
686ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_dbus_listeners(&rset, &wset, &eset);
687ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
68833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
68933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__
69033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat      check_android_listeners(&rset);
69133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
692ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
693ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_dns_listeners(&rset, now);
694ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
695ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
696ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_tftp_listeners(&rset, now);
697ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
698ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
699ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
700ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset))
701ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	dhcp_packet(now);
702ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
703ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  ifdef HAVE_SCRIPT
704ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
705ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	helper_write();
706ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#  endif
707ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
708ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
709ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
710ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
711ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
712ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void sig_handler(int sig)
713ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
714ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (pid == 0)
715ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
716ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* ignore anything other than TERM during startup
717ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 and in helper proc. (helper ignore TERM too) */
718ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (sig == SIGTERM)
719ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	exit(EC_MISC);
720ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
721ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else if (pid != getpid())
722ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
723ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* alarm is used to kill TCP children after a fixed time. */
724ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (sig == SIGALRM)
725ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	_exit(0);
726ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
727ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
728ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
729ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* master process */
730ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int event, errsave = errno;
731ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
732ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (sig == SIGHUP)
733ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_RELOAD;
734ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (sig == SIGCHLD)
735ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_CHILD;
736ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (sig == SIGALRM)
737ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_ALARM;
738ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (sig == SIGTERM)
739ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_TERM;
740ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (sig == SIGUSR1)
741ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_DUMP;
742ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else if (sig == SIGUSR2)
743ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	event = EVENT_REOPEN;
744ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
745ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	return;
746ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
747ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      send_event(pipewrite, event, 0);
748ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      errno = errsave;
749ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
750ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
751ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
752ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid send_event(int fd, int event, int data)
753ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
754ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct event_desc ev;
755ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
756ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  ev.event = event;
757ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  ev.data = data;
758ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
759ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* error pipe, debug mode. */
760ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (fd == -1)
761ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    fatal_event(&ev);
762ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  else
763ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    /* pipe is non-blocking and struct event_desc is smaller than
764ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       PIPE_BUF, so this either fails or writes everything */
765ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR);
766ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
767ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
768ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void fatal_event(struct event_desc *ev)
769ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
770ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  errno = ev->data;
771ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
772ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  switch (ev->event)
773ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
774ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_DIE:
775ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      exit(0);
776ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
777ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_FORK_ERR:
778ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("cannot fork into background: %s"), NULL, EC_MISC);
779ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
780ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_PIPE_ERR:
781ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("failed to create helper: %s"), NULL, EC_MISC);
782ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
783ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_CAP_ERR:
784ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("setting capabilities failed: %s"), NULL, EC_MISC);
785ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
786ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_USER_ERR:
787ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_HUSER_ERR:
788ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("failed to change user-id to %s: %s"),
789ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  ev->event == EVENT_USER_ERR ? daemon->username : daemon->scriptuser,
790ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  EC_MISC);
791ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
792ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_GROUP_ERR:
793ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("failed to change group-id to %s: %s"), daemon->groupname, EC_MISC);
794ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
795ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_PIDFILE:
796ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("failed to open pidfile %s: %s"), daemon->runfile, EC_FILE);
797ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
798ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    case EVENT_LOG_ERR:
799ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
800ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
801ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
802ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
803ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void async_event(int pipe, time_t now)
804ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
805ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  pid_t p;
806ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct event_desc ev;
807ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
808ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
809ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (read_write(pipe, (unsigned char *)&ev, sizeof(ev), 1))
810ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    switch (ev.event)
811ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
812ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_RELOAD:
813ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	clear_cache_and_reload(now);
814ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->port != 0 && daemon->resolv_files && (daemon->options & OPT_NO_POLL))
815ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
816ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    reload_servers(daemon->resolv_files->name);
817ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    check_servers();
818ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
819ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
820ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	rerun_scripts();
821ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
822ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
823ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
824ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_DUMP:
825ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->port != 0)
826ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  dump_cache(now);
827ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
828ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
829ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_ALARM:
830ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
831ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->dhcp)
832ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
833ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    lease_prune(NULL, now);
834ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    lease_update_file(now);
835ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
836ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
837ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
838ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
839ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_CHILD:
840ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* See Stevens 5.10 */
841ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
842ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (p == -1)
843ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
844ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (errno != EINTR)
845ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		break;
846ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
847ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
848ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    for (i = 0 ; i < MAX_PROCS; i++)
849ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (daemon->tcp_pids[i] == p)
850ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		daemon->tcp_pids[i] = 0;
851ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
852ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
853ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_KILLED:
854ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_WARNING, _("child process killed by signal %d"), ev.data);
855ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
856ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
857ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_EXITED:
858ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_WARNING, _("child process exited with status %d"), ev.data);
859ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
860ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
861ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_EXEC_ERR:
862ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_ERR, _("failed to execute %s: %s"),
863ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  daemon->lease_change_command, strerror(ev.data));
864ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
865ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
866ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* necessary for fatal errors in helper */
867ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_HUSER_ERR:
868ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_DIE:
869ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	fatal_event(&ev);
870ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
871ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
872ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_REOPEN:
873ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* Note: this may leave TCP-handling processes with the old file still open.
874ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   Since any such process will die in CHILD_LIFETIME or probably much sooner,
875ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	   we leave them logging to the old file. */
876ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->log_file != NULL)
877ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  log_reopen(daemon->log_file);
878ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	break;
879ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
880ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      case EVENT_TERM:
881ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* Knock all our children on the head. */
882ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (i = 0; i < MAX_PROCS; i++)
883ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->tcp_pids[i] != 0)
884ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    kill(daemon->tcp_pids[i], SIGALRM);
885ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
886ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
887ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	/* handle pending lease transitions */
888ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->helperfd != -1)
889ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
890ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    /* block in writes until all done */
891ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
892ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
893ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    do {
894ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      helper_write();
895ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    } while (!helper_buf_empty() || do_script_run(now));
896ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    close(daemon->helperfd);
897ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
898ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
899ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
900ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->lease_stream)
901ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  fclose(daemon->lease_stream);
902ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
903ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (daemon->runfile)
904ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  unlink(daemon->runfile);
905ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
906ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
907ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	flush_log();
908ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	exit(EC_GOOD);
909ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
910ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
911ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
912ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void poll_resolv()
913ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
914ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct resolvc *res, *latest;
915ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct stat statbuf;
916ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  time_t last_change = 0;
917ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* There may be more than one possible file.
918ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     Go through and find the one which changed _last_.
919ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     Warn of any which can't be read. */
920ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
921ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (stat(res->name, &statbuf) == -1)
922ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
923ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (!res->logged)
924ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
925ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	res->logged = 1;
926ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
927ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    else
928ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      {
929ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	res->logged = 0;
930ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	if (statbuf.st_mtime != res->mtime)
931ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  {
932ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    res->mtime = statbuf.st_mtime;
933ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    if (difftime(statbuf.st_mtime, last_change) > 0.0)
934ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      {
935ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		last_change = statbuf.st_mtime;
936ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		latest = res;
937ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      }
938ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  }
939ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      }
940ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
941ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (latest)
942ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
943ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      static int warned = 0;
944ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (reload_servers(latest->name))
945ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
946ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  my_syslog(LOG_INFO, _("reading %s"), latest->name);
947ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  warned = 0;
948ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  check_servers();
949ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->options & OPT_RELOAD)
950ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    cache_reload();
951ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
952ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      else
953ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
954ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  latest->mtime = 0;
955ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!warned)
956ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
957ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
958ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      warned = 1;
959ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
960ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
961ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
962ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
963ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
964ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatvoid clear_cache_and_reload(time_t now)
965ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
966ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0)
967ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    cache_reload();
968ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
969ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
970ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->dhcp)
971ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
972ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->options & OPT_ETHERS)
973ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	dhcp_read_ethers();
974ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      reread_dhcp();
975ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      dhcp_update_configs(daemon->dhcp_conf);
976ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_dhcp_hosts(0);
977ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      lease_update_from_configs();
978ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      lease_update_file(now);
979ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      lease_update_dns();
980ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
981ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
982ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
983ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
98433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#ifdef __ANDROID__
98533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
98633b344454b95ed99bad7d3fe4d493870923deaf6San Mehatstatic int set_android_listeners(fd_set *set, int *maxfdp) {
98733b344454b95ed99bad7d3fe4d493870923deaf6San Mehat    FD_SET(STDIN_FILENO, set);
98833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat    bump_maxfd(STDIN_FILENO, maxfdp);
98933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat    return 0;
99033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat}
99133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
99233b344454b95ed99bad7d3fe4d493870923deaf6San Mehatstatic int check_android_listeners(fd_set *set) {
99300b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux    int retcode = 0;
99433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat    if (FD_ISSET(STDIN_FILENO, set)) {
99533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        char buffer[1024];
99633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        int rc;
99700b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux        int consumed = 0;
99833b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
99933b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        if ((rc = read(STDIN_FILENO, buffer, sizeof(buffer) -1)) < 0) {
100033b344454b95ed99bad7d3fe4d493870923deaf6San Mehat            my_syslog(LOG_ERR, _("Error reading from stdin (%s)"), strerror(errno));
100133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat            return -1;
100233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        }
100333b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        buffer[rc] = '\0';
100400b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux        while(consumed < rc) {
100500b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            char *cmd;
100600b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            char *current_cmd = &buffer[consumed];
100700b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            char *params = current_cmd;
100800b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            int len = strlen(current_cmd);
100900b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux
101000b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            cmd = strsep(&params, ":");
101100b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            if (!strcmp(cmd, "update_dns")) {
101200b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                if (params != NULL) {
101300b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                    set_servers(params);
101400b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                    check_servers();
101500b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                } else {
101600b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                    my_syslog(LOG_ERR, _("Malformatted msg '%s'"), current_cmd);
101700b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                    retcode = -1;
101800b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                }
101941cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt            } else if (!strcmp(cmd, "update_ifaces")) {
102041cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                if (params != NULL) {
102141cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                    set_interfaces(params);
102241cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                } else {
102341cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                    my_syslog(LOG_ERR, _("Malformatted msg '%s'"), current_cmd);
102441cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                    retcode = -1;
102541cd7ed80eb5e97ef9893633d05f0877da7d6d0cRobert Greenwalt                }
102600b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            } else {
102700b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                 my_syslog(LOG_ERR, _("Unknown cmd '%s'"), cmd);
102800b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux                 retcode = -1;
102900b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            }
103000b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux            consumed += len + 1;
103133b344454b95ed99bad7d3fe4d493870923deaf6San Mehat        }
103233b344454b95ed99bad7d3fe4d493870923deaf6San Mehat    }
103300b7b3528890a27c04b2a6da87b790151cea8721Pierre Crépieux    return retcode;
103433b344454b95ed99bad7d3fe4d493870923deaf6San Mehat}
103533b344454b95ed99bad7d3fe4d493870923deaf6San Mehat#endif
103633b344454b95ed99bad7d3fe4d493870923deaf6San Mehat
1037ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
1038ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
1039ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct serverfd *serverfdp;
1040ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct listener *listener;
1041ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int wait = 0, i;
1042ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1043ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
1044ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int  tftp = 0;
1045ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct tftp_transfer *transfer;
1046ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1047ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1048ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      tftp++;
1049ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_SET(transfer->sockfd, set);
1050ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      bump_maxfd(transfer->sockfd, maxfdp);
1051ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1052ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1053ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1054ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* will we be able to get memory? */
1055ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0)
1056ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    get_new_frec(now, &wait);
1057ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1058ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1059ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1060ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_SET(serverfdp->fd, set);
1061ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      bump_maxfd(serverfdp->fd, maxfdp);
1062ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1063ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1064ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0 && !daemon->osport)
1065ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (i = 0; i < RANDOM_SOCKS; i++)
1066ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->randomsocks[i].refcount != 0)
1067ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1068ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_SET(daemon->randomsocks[i].fd, set);
1069ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
1070ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1071ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1072ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (listener = daemon->listeners; listener; listener = listener->next)
1073ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1074ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* only listen for queries if we have resources */
1075ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (listener->fd != -1 && wait == 0)
1076ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1077ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_SET(listener->fd, set);
1078ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  bump_maxfd(listener->fd, maxfdp);
1079ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1080ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1081ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      /* death of a child goes through the select loop, so
1082ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 we don't need to explicitly arrange to wake up here */
1083ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if  (listener->tcpfd != -1)
1084ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	for (i = 0; i < MAX_PROCS; i++)
1085ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->tcp_pids[i] == 0)
1086ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1087ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      FD_SET(listener->tcpfd, set);
1088ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      bump_maxfd(listener->tcpfd, maxfdp);
1089ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      break;
1090ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1091ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1092ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
1093ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
1094ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1095ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_SET(listener->tftpfd, set);
1096ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  bump_maxfd(listener->tftpfd, maxfdp);
1097ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1098ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1099ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1100ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1101ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1102ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return wait;
1103ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
1104ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1105ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatstatic void check_dns_listeners(fd_set *set, time_t now)
1106ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
1107ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct serverfd *serverfdp;
1108ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct listener *listener;
1109ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int i;
1110ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1111ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1112ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    if (FD_ISSET(serverfdp->fd, set))
1113ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1114ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1115ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if (daemon->port != 0 && !daemon->osport)
1116ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    for (i = 0; i < RANDOM_SOCKS; i++)
1117ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (daemon->randomsocks[i].refcount != 0 &&
1118ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_ISSET(daemon->randomsocks[i].fd, set))
1119ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
1120ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1121ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (listener = daemon->listeners; listener; listener = listener->next)
1122ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1123ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (listener->fd != -1 && FD_ISSET(listener->fd, set))
1124ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	receive_query(listener, now);
1125ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1126ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
1127ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
1128ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	tftp_request(listener, now);
1129ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1130ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1131ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
1132ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1133ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  int confd;
1134ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  struct irec *iface = NULL;
1135ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  pid_t p;
1136ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1137ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  while((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
1138ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1139ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (confd == -1)
1140ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    continue;
1141ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1142ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (daemon->options & OPT_NOWILD)
1143ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    iface = listener->iface;
1144ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
1145ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1146ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      union mysockaddr tcp_addr;
1147ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      socklen_t tcp_len = sizeof(union mysockaddr);
1148ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* Check for allowed interfaces when binding the wildcard address:
1149ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 we do this by looking for an interface with the same address as
1150ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 the local address of the TCP connection, then looking to see if that's
1151ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 an allowed interface. As a side effect, we get the netmask of the
1152ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 interface too, for localisation. */
1153ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1154ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* interface may be new since startup */
1155ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (enumerate_interfaces() &&
1156ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) != -1)
1157ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		for (iface = daemon->interfaces; iface; iface = iface->next)
1158ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  if (sockaddr_isequal(&iface->addr, &tcp_addr))
1159ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    break;
1160ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1161ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1162ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  if (!iface)
1163ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1164ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      shutdown(confd, SHUT_RDWR);
1165ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      close(confd);
1166ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1167ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef NO_FORK
1168ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
1169ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1170ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (p != -1)
1171ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1172ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  int i;
1173ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  for (i = 0; i < MAX_PROCS; i++)
1174ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    if (daemon->tcp_pids[i] == 0)
1175ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      {
1176ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			daemon->tcp_pids[i] = p;
1177ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat			break;
1178ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		      }
1179ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1180ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      close(confd);
1181ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1182ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1183ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  else
1184ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    {
1185ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      unsigned char *buff;
1186ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      struct server *s;
1187ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      int flags;
1188ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      struct in_addr dst_addr_4;
1189ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1190ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      dst_addr_4.s_addr = 0;
1191ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1192ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	       /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
1193ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  terminate the process. */
1194ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (!(daemon->options & OPT_DEBUG))
1195ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		alarm(CHILD_LIFETIME);
1196ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1197ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* start with no upstream connections. */
1198ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for (s = daemon->servers; s; s = s->next)
1199ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 s->tcpfd = -1;
1200ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1201ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      /* The connected socket inherits non-blocking
1202ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 attribute from the listening socket.
1203ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		 Reset that here. */
1204ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1205ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1206ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1207ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (listener->family == AF_INET)
1208ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		dst_addr_4 = iface->addr.in.sin_addr;
1209ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1210ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      buff = tcp_request(confd, now, dst_addr_4, iface->netmask);
1211ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1212ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      shutdown(confd, SHUT_RDWR);
1213ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      close(confd);
1214ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1215ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (buff)
1216ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		free(buff);
1217ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1218ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      for (s = daemon->servers; s; s = s->next)
1219ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		if (s->tcpfd != -1)
1220ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  {
1221ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    shutdown(s->tcpfd, SHUT_RDWR);
1222ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		    close(s->tcpfd);
1223ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  }
1224ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifndef NO_FORK
1225ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	      if (!(daemon->options & OPT_DEBUG))
1226ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		{
1227ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  flush_log();
1228ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		  _exit(0);
1229ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		}
1230ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1231ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	    }
1232ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1233ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1234ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
1235ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1236ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_DHCP
1237ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint make_icmp_sock(void)
1238ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
1239ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int fd;
1240ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int zeroopt = 0;
1241ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1242ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1243ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1244ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (!fix_fd(fd) ||
1245ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1246ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1247ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  close(fd);
1248ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  fd = -1;
1249ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1250ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1251ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1252ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return fd;
1253ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
1254ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1255ffd68729961f7383f2e35494a03ccdef20f86c98San Mehatint icmp_ping(struct in_addr addr)
1256ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat{
1257ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Try and get an ICMP echo from a machine. */
1258ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1259ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  /* Note that whilst in the three second wait, we check for
1260ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     (and service) events on the DNS and TFTP  sockets, (so doing that
1261ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     better not use any resources our caller has in use...)
1262ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat     but we remain deaf to signals or further DHCP packets. */
1263ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1264ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int fd;
1265ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct sockaddr_in saddr;
1266ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  struct {
1267ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    struct ip ip;
1268ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    struct icmp icmp;
1269ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  } packet;
1270ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned short id = rand16();
1271ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  unsigned int i, j;
1272ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int gotreply = 0;
1273ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  time_t start, now;
1274ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1275ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
1276ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  if ((fd = make_icmp_sock()) == -1)
1277ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    return 0;
1278ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
1279ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  int opt = 2000;
1280ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  fd = daemon->dhcp_icmp_fd;
1281ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1282ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1283ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1284ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  saddr.sin_family = AF_INET;
1285ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  saddr.sin_port = 0;
1286ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  saddr.sin_addr = addr;
1287ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_SOCKADDR_SA_LEN
1288ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  saddr.sin_len = sizeof(struct sockaddr_in);
1289ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1290ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1291ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  memset(&packet.icmp, 0, sizeof(packet.icmp));
1292ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  packet.icmp.icmp_type = ICMP_ECHO;
1293ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  packet.icmp.icmp_id = id;
1294ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1295ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    j += ((u16 *)&packet.icmp)[i];
1296ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (j>>16)
1297ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    j = (j & 0xffff) + (j >> 16);
1298ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1299ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1300ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1301ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		(struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
1302ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	 retry_send());
1303ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1304ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  for (now = start = dnsmasq_time();
1305ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat       difftime(now, start) < (float)PING_WAIT;)
1306ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    {
1307ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct timeval tv;
1308ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      fd_set rset, wset;
1309ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      struct sockaddr_in faddr;
1310ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      int maxfd = fd;
1311ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      socklen_t len = sizeof(faddr);
1312ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1313ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      tv.tv_usec = 250000;
1314ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      tv.tv_sec = 0;
1315ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1316ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_ZERO(&rset);
1317ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_ZERO(&wset);
1318ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      FD_SET(fd, &rset);
1319ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      set_dns_listeners(now, &rset, &maxfd);
1320ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      set_log_writer(&wset, &maxfd);
1321ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1322ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
1323ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1324ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_ZERO(&rset);
1325ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  FD_ZERO(&wset);
1326ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1327ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1328ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      now = dnsmasq_time();
1329ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1330ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_log_writer(&wset);
1331ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_dns_listeners(&rset, now);
1332ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1333ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#ifdef HAVE_TFTP
1334ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      check_tftp_listeners(&rset, now);
1335ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1336ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1337ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat      if (FD_ISSET(fd, &rset) &&
1338ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  recvfrom(fd, &packet, sizeof(packet), 0,
1339ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat		   (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1340ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
1341ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1342ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  packet.icmp.icmp_seq == 0 &&
1343ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  packet.icmp.icmp_id == id)
1344ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	{
1345ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  gotreply = 1;
1346ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	  break;
1347ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat	}
1348ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat    }
1349ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1350ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1351ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  close(fd);
1352ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#else
1353ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  opt = 1;
1354ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1355ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1356ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat
1357ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat  return gotreply;
1358ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat}
1359ffd68729961f7383f2e35494a03ccdef20f86c98San Mehat#endif
1360