blob: c9588c4360da516604f639fe0d3b3ebc0ad7e86b [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelleyc72daea2012-01-05 21:33:27 +000017/* Declare static char *compiler_opts in config.h */
18#define DNSMASQ_COMPILE_OPTS
19
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020#include "dnsmasq.h"
21
Simon Kelley5aabfc72007-08-29 11:24:47 +010022struct daemon *daemon;
23
Simon Kelley5aabfc72007-08-29 11:24:47 +010024static volatile pid_t pid = 0;
25static volatile int pipewrite;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000026
Simon Kelleyb842bc92015-07-12 21:09:11 +010027static int set_dns_listeners(time_t now);
28static void check_dns_listeners(time_t now);
Simon Kelley3be34542004-09-11 19:12:13 +010029static void sig_handler(int sig);
Simon Kelley5aabfc72007-08-29 11:24:47 +010030static void async_event(int pipe, time_t now);
Simon Kelleyc72daea2012-01-05 21:33:27 +000031static void fatal_event(struct event_desc *ev, char *msg);
32static int read_event(int fd, struct event_desc *evp, char **msg);
Simon Kelley47a95162014-07-08 22:22:02 +010033static void poll_resolv(int force, int do_reload, time_t now);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000034
35int main (int argc, char **argv)
36{
Simon Kelleyde379512004-06-22 20:23:33 +010037 int bind_fallback = 0;
Simon Kelley9009d742008-11-14 20:04:27 +000038 time_t now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000039 struct sigaction sigact;
Simon Kelley26128d22004-11-14 16:43:54 +000040 struct iname *if_tmp;
Simon Kelley1a6bca82008-07-11 11:11:42 +010041 int piperead, pipefd[2], err_pipe[2];
42 struct passwd *ent_pw = NULL;
Simon Kelleyc72daea2012-01-05 21:33:27 +000043#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +010044 uid_t script_uid = 0;
45 gid_t script_gid = 0;
Simon Kelley7622fc02009-06-04 20:32:05 +010046#endif
47 struct group *gp = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +010048 long i, max_fd = sysconf(_SC_OPEN_MAX);
Simon Kelley1a6bca82008-07-11 11:11:42 +010049 char *baduser = NULL;
50 int log_err;
Simon Kelley6b54d692018-02-08 21:23:05 +000051 int chown_warn = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010052#if defined(HAVE_LINUX_NETWORK)
53 cap_user_header_t hdr = NULL;
54 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010055 char *bound_device = NULL;
56 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010057#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010058#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000059 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010060 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010061#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010062#ifdef HAVE_TFTP
63 int tftp_prefix_missing = 0;
64#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010065
Simon Kelley824af852008-02-12 20:43:05 +000066#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000067 setlocale(LC_ALL, "");
68 bindtextdomain("dnsmasq", LOCALEDIR);
69 textdomain("dnsmasq");
70#endif
71
Simon Kelley9e4abcb2004-01-22 19:47:41 +000072 sigact.sa_handler = sig_handler;
73 sigact.sa_flags = 0;
74 sigemptyset(&sigact.sa_mask);
75 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010076 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000077 sigaction(SIGHUP, &sigact, NULL);
78 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000079 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010080 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000081 sigaction(SIGINT, &sigact, NULL);
82
Simon Kelleyfeba5c12004-07-27 20:28:58 +010083 /* ignore SIGPIPE */
84 sigact.sa_handler = SIG_IGN;
85 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000086
Simon Kelley5aabfc72007-08-29 11:24:47 +010087 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010088
89 rand_init(); /* Must precede read_opts() */
90
Simon Kelley5aabfc72007-08-29 11:24:47 +010091 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000092
Simon Kelley3be34542004-09-11 19:12:13 +010093 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000094 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000095
Simon Kelleyd3a8b392015-12-23 12:27:37 +000096 /* Min buffer size: we check after adding each record, so there must be
97 memory for the largest packet, and the largest record so the
98 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
99 This might be increased is EDNS packet size if greater than the minimum. */
100 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000101 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000102
Simon Kelleyc72daea2012-01-05 21:33:27 +0000103 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000104 if (option_bool(OPT_EXTRALOG))
105 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000106
107#ifdef HAVE_DNSSEC
108 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000109 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100110 /* Note that both /000 and '.' are allowed within labels. These get
111 represented in presentation format using NAME_ESCAPE as an escape
112 character when in DNSSEC mode.
113 In theory, if all the characters in a name were /000 or
114 '.' or NAME_ESCAPE then all would have to be escaped, so the
115 presentation format would be twice as long as the spec.
116
117 daemon->namebuff was previously allocated by the option-reading
118 code before we knew if we're in DNSSEC mode, so reallocate here. */
119 free(daemon->namebuff);
120 daemon->namebuff = safe_malloc(MAXDNAME * 2);
121 daemon->keyname = safe_malloc(MAXDNAME * 2);
122 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000123 /* one char flag per possible RR in answer section (may get extended). */
124 daemon->rr_status_sz = 64;
125 daemon->rr_status = safe_malloc(daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000126 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000127#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000128
Simon Kelley7622fc02009-06-04 20:32:05 +0100129#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100130 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000131 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000132 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100133 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000134 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100135#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000136
Simon Kelleya2761752012-01-18 16:07:21 +0000137 /* Close any file descriptors we inherited apart from std{in|out|err}
138
139 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
140 otherwise file descriptors we create can end up being 0, 1, or 2
141 and then get accidentally closed later when we make 0, 1, and 2
142 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
143 but it's not guaranteed. By opening /dev/null three times, we
144 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100145 for (i = 0; i < max_fd; i++)
146 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
147 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000148 else
149 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100150
Simon Kelley801ca9a2012-03-06 19:30:17 +0000151#ifndef HAVE_LINUX_NETWORK
152# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000153 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100154 {
155 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000156 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100157 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000158# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100159
160 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100161 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100162 {
163 bind_fallback = 1;
164 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100165 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100166 }
Simon Kelley04918052015-01-26 11:23:43 +0000167#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000168
Simon Kelley04918052015-01-26 11:23:43 +0000169#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000170 if (daemon->dynamic_dirs)
171 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100172#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100173
Simon Kelley0744ca62014-01-25 16:40:15 +0000174 if (option_bool(OPT_DNSSEC_VALID))
175 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000176#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000177 struct ds_config *ds;
178
179 /* Must have at least a root trust anchor, or the DNSSEC code
180 can loop forever. */
181 for (ds = daemon->ds; ds; ds = ds->next)
182 if (ds->name[0] == 0)
183 break;
184
185 if (!ds)
186 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000187
188 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000189 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000190#else
191 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000192#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000193 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000194
Simon Kelley832af0b2007-01-21 20:01:28 +0000195#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100196 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100197 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000198#endif
199
Simon Kelley7de060b2011-08-26 17:24:52 +0100200#ifdef HAVE_CONNTRACK
201 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000202 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100203#else
204 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000205 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100206#endif
207
Simon Kelley824af852008-02-12 20:43:05 +0000208#ifdef HAVE_SOLARIS_NETWORK
209 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000210 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000211#endif
212
Simon Kelley572b41e2011-02-18 18:11:18 +0000213#ifdef __ANDROID__
214 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000215 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000216#endif
217
Simon Kelley4820dce2012-12-18 18:30:30 +0000218#ifndef HAVE_AUTH
219 if (daemon->authserver)
220 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
221#endif
222
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100223#ifndef HAVE_LOOP
224 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000225 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100226#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000227
Hans Dedecker926332a2016-01-23 10:48:12 +0000228 if (daemon->max_port < daemon->min_port)
229 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
230
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100231 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000232
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000233 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000234 if (daemon->authinterface && daemon->soa_sn == 0)
235#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000236 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000237#else
238 daemon->soa_sn = now;
239#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000240
Simon Kelleyff7eea22013-09-04 18:01:38 +0100241#ifdef HAVE_DHCP6
242 if (daemon->dhcp6)
243 {
244 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000245
Simon Kelleyff7eea22013-09-04 18:01:38 +0100246 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000247 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100248 if (context->flags & CONTEXT_DHCP)
249 daemon->doing_dhcp6 = 1;
250 if (context->flags & CONTEXT_RA)
251 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000252#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100253 if (context->flags & CONTEXT_TEMPLATE)
254 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000255#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000256 }
Simon Kelley1f776932012-12-16 19:46:08 +0000257 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100258#endif
259
260#ifdef HAVE_DHCP
261 /* Note that order matters here, we must call lease_init before
262 creating any file descriptors which shouldn't be leaked
263 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000264 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000265 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000266 conditions below. */
267 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000268 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100269 {
270 dhcp_common_init();
271 if (daemon->dhcp || daemon->doing_dhcp6)
272 lease_init(now);
273 }
274
275 if (daemon->dhcp || daemon->relay4)
276 dhcp_init();
277
278# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100279 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100280 ra_init(now);
281
282 if (daemon->doing_dhcp6 || daemon->relay6)
283 dhcp6_init();
284# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000285
Simon Kelley7622fc02009-06-04 20:32:05 +0100286#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100287
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000288#ifdef HAVE_IPSET
289 if (daemon->ipsets)
290 ipset_init();
291#endif
292
Simon Kelley1ee9be42013-12-09 16:50:19 +0000293#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000294 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000295#elif defined(HAVE_BSD_NETWORK)
296 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000297#endif
298
Simon Kelley1ee9be42013-12-09 16:50:19 +0000299 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
300 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
301
Simon Kelley115ac3e2013-05-20 11:28:32 +0100302 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100303 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000304
Simon Kelley54dd3932012-06-20 11:23:38 +0100305 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100306 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100307 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100308
309 if (!option_bool(OPT_CLEVERBIND))
310 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
311 if (if_tmp->name && !if_tmp->used)
312 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100313
314#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
315 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100316 bound_device = whichdevice();
317
Simon Kelley9380ba72012-04-16 14:41:56 +0100318 if (daemon->dhcp)
319 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100320 if (!daemon->relay4 && bound_device)
321 {
322 bindtodevice(bound_device, daemon->dhcpfd);
323 did_bind = 1;
324 }
325 if (daemon->enable_pxe && bound_device)
326 {
327 bindtodevice(bound_device, daemon->pxefd);
328 did_bind = 1;
329 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100330 }
331#endif
332
333#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100334 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
335 {
336 bindtodevice(bound_device, daemon->dhcp6fd);
337 did_bind = 1;
338 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100339#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100340 }
Simon Kelley28866e92011-02-14 20:19:14 +0000341 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100342 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000343
344#ifdef HAVE_DHCP6
345 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100346 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000347 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000348
349 /* After netlink_init() and before create_helper() */
350 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000351#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100352
Simon Kelley824af852008-02-12 20:43:05 +0000353 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000354 {
355 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000356
Simon Kelley82e3f452014-01-31 21:05:48 +0000357#ifdef HAVE_DNSSEC
358 blockdata_init();
359#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000360 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000361
Simon Kelley04918052015-01-26 11:23:43 +0000362#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000363 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
364 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000365 inotify_dnsmasq_init();
366 else
367 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000368#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000369
Simon Kelley28866e92011-02-14 20:19:14 +0000370 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100371#ifdef HAVE_DBUS
372 {
373 char *err;
374 daemon->dbus = NULL;
375 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100376 if ((err = dbus_init()))
377 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100378 }
379#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100380 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100381#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100382
Simon Kelley824af852008-02-12 20:43:05 +0000383 if (daemon->port != 0)
384 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100385
Simon Kelleyc72daea2012-01-05 21:33:27 +0000386#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100387 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000388 if ((daemon->dhcp || daemon->dhcp6) &&
389 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000390 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100391 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000392 struct passwd *scr_pw;
393
394 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100395 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000396 script_uid = scr_pw->pw_uid;
397 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100398 }
399 else
400 baduser = daemon->scriptuser;
401 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100402#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000403
Simon Kelley1a6bca82008-07-11 11:11:42 +0100404 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
405 baduser = daemon->username;
406 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
407 baduser = daemon->groupname;
408
409 if (baduser)
410 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000411
Simon Kelley1a6bca82008-07-11 11:11:42 +0100412 /* implement group defaults, "dip" if available, or group associated with uid */
413 if (!daemon->group_set && !gp)
414 {
415 if (!(gp = getgrnam(CHGRP)) && ent_pw)
416 gp = getgrgid(ent_pw->pw_gid);
417
418 /* for error message */
419 if (gp)
420 daemon->groupname = gp->gr_name;
421 }
422
423#if defined(HAVE_LINUX_NETWORK)
424 /* determine capability API version here, while we can still
425 call safe_malloc */
426 if (ent_pw && ent_pw->pw_uid != 0)
427 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100428 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100429 hdr = safe_malloc(sizeof(*hdr));
430
Simon Kelley1a6bca82008-07-11 11:11:42 +0100431 /* find version supported by kernel */
432 memset(hdr, 0, sizeof(*hdr));
433 capget(hdr, NULL);
434
435 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
436 {
437 /* if unknown version, use largest supported version (3) */
438 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
439 hdr->version = LINUX_CAPABILITY_VERSION_3;
440 capsize = 2;
441 }
442
443 data = safe_malloc(sizeof(*data) * capsize);
444 memset(data, 0, sizeof(*data) * capsize);
445 }
446#endif
447
Simon Kelley5aabfc72007-08-29 11:24:47 +0100448 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100449 in a race-free manner and another to carry errors to daemon-invoking process */
450 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100451
452 piperead = pipefd[0];
453 pipewrite = pipefd[1];
454 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000455 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100456
457 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100458
Simon Kelley28866e92011-02-14 20:19:14 +0000459 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000460 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000461 /* The following code "daemonizes" the process.
462 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100463
Simon Kelley9e038942008-05-30 20:06:34 +0100464 if (chdir("/") != 0)
465 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
466
Simon Kelley16972692006-10-16 20:04:18 +0100467#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000468 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100469 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100470 pid_t pid;
471
Simon Kelley1a6bca82008-07-11 11:11:42 +0100472 /* pipe to carry errors back to original process.
473 When startup is complete we close this and the process terminates. */
474 safe_pipe(err_pipe, 0);
475
Simon Kelley7622fc02009-06-04 20:32:05 +0100476 if ((pid = fork()) == -1)
477 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000478 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100479
Simon Kelley5aabfc72007-08-29 11:24:47 +0100480 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100481 {
482 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000483 char *msg;
484
Simon Kelley1a6bca82008-07-11 11:11:42 +0100485 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000486 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100487
488 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000489 if (read_event(err_pipe[0], &ev, &msg))
490 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100491
492 _exit(EC_GOOD);
493 }
494
Simon Kelleyff841eb2015-03-11 21:36:30 +0000495 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100496
497 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100498
499 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100500
501 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000502 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100503
504 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100505 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100506 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000507#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100508
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000509 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100510 if (daemon->runfile)
511 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100512 int fd, err = 0;
513
514 sprintf(daemon->namebuff, "%d\n", (int) getpid());
515
516 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
517 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
518 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
519 extent that an attacker running as the unprivileged user could replace the pidfile with a
520 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
521
Josh Soref730c6742017-02-06 16:14:04 +0000522 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100523 ensuring that the open() fails should there be any existing file (because the unlink() failed,
524 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
525 attack can succeed.
526
527 Any compromise of the non-privileged user still theoretically allows the pid-file to be
528 replaced whilst dnsmasq is running. The worst that could allow is that the usual
529 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
530
531 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
532 failure to write the pid-file.
533 */
534
535 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100536
Simon Kelley79cfefd2012-09-02 13:29:51 +0100537 if ((fd = open(daemon->runfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100538 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100539 /* only complain if started as root */
540 if (getuid() == 0)
541 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100542 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100543 else
544 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000545 /* We're still running as root here. Change the ownership of the PID file
546 to the user we will be running as. Note that this is not to allow
547 us to delete the file, since that depends on the permissions
548 of the directory containing the file. That directory will
549 need to by owned by the dnsmasq user, and the ownership of the
550 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000551 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
552 chown_warn = errno;
553
554 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100555 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000556 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000557 {
558 while (retry_send(close(fd)));
559 if (errno != 0)
560 err = 1;
561 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100562 }
563
564 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100565 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000566 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100567 _exit(0);
568 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000569 }
Simon Kelley16972692006-10-16 20:04:18 +0100570 }
571
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100572 log_err = log_start(ent_pw, err_pipe[1]);
573
Simon Kelley28866e92011-02-14 20:19:14 +0000574 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100575 {
576 /* open stdout etc to /dev/null */
577 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000578 if (nullfd != -1)
579 {
580 dup2(nullfd, STDOUT_FILENO);
581 dup2(nullfd, STDERR_FILENO);
582 dup2(nullfd, STDIN_FILENO);
583 close(nullfd);
584 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100585 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100586
Simon Kelley1a6bca82008-07-11 11:11:42 +0100587 /* if we are to run scripts, we need to fork a helper before dropping root. */
588 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000589#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000590 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000591 (daemon->lease_change_command || daemon->luascript))
592 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100593#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100594
Simon Kelley28866e92011-02-14 20:19:14 +0000595 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100596 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100597 int bad_capabilities = 0;
598 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100599
Josh Soref730c6742017-02-06 16:14:04 +0000600 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100601 if (gp &&
602 (setgroups(0, &dummy) == -1 ||
603 setgid(gp->gr_gid) == -1))
604 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000605 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100606 _exit(0);
607 }
608
Simon Kelley7cebd202006-05-06 14:13:33 +0100609 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100610 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100611#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100612 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100613 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100614 ports because of DAD, or we're doing it dynamically,
615 we need CAP_NET_BIND_SERVICE too. */
616 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100617 data->effective = data->permitted = data->inheritable =
618 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
619 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
620 else
621 data->effective = data->permitted = data->inheritable =
622 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100623
Simon Kelley16972692006-10-16 20:04:18 +0100624 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000625 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100626 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100627
Simon Kelley7622fc02009-06-04 20:32:05 +0100628#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000629 /* http://developers.sun.com/solaris/articles/program_privileges.html */
630 priv_set_t *priv_set;
631
632 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
633 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
634 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
635 bad_capabilities = errno;
636
637 if (priv_set && bad_capabilities == 0)
638 {
639 priv_inverse(priv_set);
640
641 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
642 bad_capabilities = errno;
643 }
644
645 if (priv_set)
646 priv_freeset(priv_set);
647
Simon Kelley824af852008-02-12 20:43:05 +0000648#endif
649
Simon Kelley1a6bca82008-07-11 11:11:42 +0100650 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100651 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000652 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100653 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100654 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100655
656 /* finally drop root */
657 if (setuid(ent_pw->pw_uid) == -1)
658 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000659 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100660 _exit(0);
661 }
662
663#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100664 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100665 data->effective = data->permitted =
666 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
667 else
668 data->effective = data->permitted =
669 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100670 data->inheritable = 0;
671
Josh Soref730c6742017-02-06 16:14:04 +0000672 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100673 if (capset(hdr, data) == -1)
674 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000675 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100676 _exit(0);
677 }
678#endif
679
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000680 }
Simon Kelley849a8352006-06-09 21:02:31 +0100681 }
Simon Kelley16972692006-10-16 20:04:18 +0100682
Simon Kelley16972692006-10-16 20:04:18 +0100683#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000684 free(hdr);
685 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000686 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000687 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100688#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100689
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100690#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100691 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100692 {
693 DIR *dir;
694 struct tftp_prefix *p;
695
696 if (daemon->tftp_prefix)
697 {
698 if (!((dir = opendir(daemon->tftp_prefix))))
699 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100700 tftp_prefix_missing = 1;
701 if (!option_bool(OPT_TFTP_NO_FAIL))
702 {
703 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
704 _exit(0);
705 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100706 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100707 else
708 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100709 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100710
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100711 for (p = daemon->if_prefix; p; p = p->next)
712 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100713 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100714 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100715 {
716 p->missing = 1;
717 if (!option_bool(OPT_TFTP_NO_FAIL))
718 {
719 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
720 _exit(0);
721 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100722 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100723 else
724 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100725 }
726 }
727#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100728
Simon Kelley824af852008-02-12 20:43:05 +0000729 if (daemon->port == 0)
730 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000731 else
732 {
733 if (daemon->cachesize != 0)
734 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
735 else
736 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
737
738 if (option_bool(OPT_LOCAL_SERVICE))
739 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
740 }
Simon Kelley16972692006-10-16 20:04:18 +0100741
Simon Kelleyf2621c72007-04-29 19:47:21 +0100742 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000743
744 if (chown_warn != 0)
745 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100746
Simon Kelley3d8df262005-08-29 12:19:27 +0100747#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000748 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100749 {
750 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100751 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100752 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100753 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100754 }
755#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000756
Simon Kelley1d97ac42014-01-31 11:12:27 +0000757#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000758 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000759 {
Simon Kelley360f2512015-03-07 18:28:06 +0000760 int rc;
761
762 /* Delay creating the timestamp file until here, after we've changed user, so that
763 it has the correct owner to allow updating the mtime later.
764 This means we have to report fatal errors via the pipe. */
765 if ((rc = setup_timestamp()) == -1)
766 {
767 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
768 _exit(0);
769 }
770
Simon Kelleye98bd522014-03-28 20:41:23 +0000771 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000772
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100773 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
774 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000775 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000776
777 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000778 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000779 }
Simon Kelleydb737462014-01-31 10:32:45 +0000780#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100781
Simon Kelley1a6bca82008-07-11 11:11:42 +0100782 if (log_err != 0)
783 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
784 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000785
Simon Kelleyde379512004-06-22 20:23:33 +0100786 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100787 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100788
Simon Kelleyf7029f52013-11-21 15:09:09 +0000789 if (option_bool(OPT_NOWILD))
790 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000791 else if (!option_bool(OPT_CLEVERBIND))
792 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000793
794 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100795
Simon Kelley28866e92011-02-14 20:19:14 +0000796 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000797 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
798 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100799 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100800
Simon Kelley28866e92011-02-14 20:19:14 +0000801 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100802 {
803 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100804 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100805 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000806 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100807 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100808 }
809
Simon Kelleyf2621c72007-04-29 19:47:21 +0100810 if (daemon->max_logs != 0)
811 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000812
Simon Kelleyf2621c72007-04-29 19:47:21 +0100813
Simon Kelley7622fc02009-06-04 20:32:05 +0100814#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000815 for (context = daemon->dhcp; context; context = context->next)
816 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100817
Simon Kelleyff7eea22013-09-04 18:01:38 +0100818 for (relay = daemon->relay4; relay; relay = relay->next)
819 log_relay(AF_INET, relay);
820
Simon Kelley1f776932012-12-16 19:46:08 +0000821# ifdef HAVE_DHCP6
822 for (context = daemon->dhcp6; context; context = context->next)
823 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000824
Simon Kelleyff7eea22013-09-04 18:01:38 +0100825 for (relay = daemon->relay6; relay; relay = relay->next)
826 log_relay(AF_INET6, relay);
827
Simon Kelley1f776932012-12-16 19:46:08 +0000828 if (daemon->doing_dhcp6 || daemon->doing_ra)
829 dhcp_construct_contexts(now);
830
831 if (option_bool(OPT_RA))
832 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
833# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000834
Simon Kelley3b3f4412013-10-11 16:33:28 +0100835# ifdef HAVE_LINUX_NETWORK
836 if (did_bind)
837 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
838# endif
839
Josh Soref730c6742017-02-06 16:14:04 +0000840 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000841 if (daemon->dhcp || daemon->doing_dhcp6)
842 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000843#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000844
Simon Kelley832af0b2007-01-21 20:01:28 +0000845#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000846 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100847 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100848 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000849
Simon Kelley7622fc02009-06-04 20:32:05 +0100850 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100851 daemon->tftp_prefix ? _("root is ") : _("enabled"),
852 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000853 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100854
Stefan Tomanek30d08792015-03-31 22:32:11 +0100855 if (tftp_prefix_missing)
856 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100857
Stefan Tomanek30d08792015-03-31 22:32:11 +0100858 for (p = daemon->if_prefix; p; p = p->next)
859 if (p->missing)
860 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
861
Simon Kelley832af0b2007-01-21 20:01:28 +0000862 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100863 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000864 a single file will be sent to may clients (the file only needs
865 one fd). */
866
867 max_fd -= 30; /* use other than TFTP */
868
869 if (max_fd < 0)
870 max_fd = 5;
871 else if (max_fd < 100)
872 max_fd = max_fd/2;
873 else
874 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000875
876 /* if we have to use a limited range of ports,
877 that will limit the number of transfers */
878 if (daemon->start_tftp_port != 0 &&
879 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
880 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000881
882 if (daemon->tftp_max > max_fd)
883 {
884 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100885 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100886 _("restricting maximum simultaneous TFTP transfers to %d"),
887 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000888 }
889 }
890#endif
891
Simon Kelley1a6bca82008-07-11 11:11:42 +0100892 /* finished start-up - release original process */
893 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000894 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000895
Simon Kelley824af852008-02-12 20:43:05 +0000896 if (daemon->port != 0)
897 check_servers();
898
Simon Kelley7cebd202006-05-06 14:13:33 +0100899 pid = getpid();
900
Simon Kelley04918052015-01-26 11:23:43 +0000901#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000902 /* Using inotify, have to select a resolv file at startup */
903 poll_resolv(1, 0, now);
904#endif
905
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100906 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000907 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100908 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000909
Simon Kelleyb842bc92015-07-12 21:09:11 +0100910 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000911
Simon Kelley16972692006-10-16 20:04:18 +0100912 /* if we are out of resources, find how long we have to wait
913 for some to come free, we'll loop around then and restart
914 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100915 if ((t = set_dns_listeners(now)) != 0)
916 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100917
Simon Kelley832af0b2007-01-21 20:01:28 +0000918 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
919 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000920 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100921 timeout = 250;
922
Simon Kelley74c95c22011-10-19 09:33:39 +0100923 /* Wake every second whilst waiting for DAD to complete */
924 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100925 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100926
Simon Kelley832af0b2007-01-21 20:01:28 +0000927#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100928 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100929#endif
930
Simon Kelley7622fc02009-06-04 20:32:05 +0100931#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100932 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100933 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100934 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000935 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100936 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100937 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100938#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100939
Simon Kelley52b92f42012-01-22 16:05:15 +0000940#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100941 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100942 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100943
Simon Kelley1f776932012-12-16 19:46:08 +0000944 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100945 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000946#endif
Simon Kelley04918052015-01-26 11:23:43 +0000947
948#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000949 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100950 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000951#endif
952
953#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100954 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000955#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100956 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100957#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000958
Simon Kelleyb842bc92015-07-12 21:09:11 +0100959 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100960
Simon Kelley33702ab2015-12-28 23:17:15 +0000961#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000962# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000963 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000964# endif
965
Simon Kelley1e505122016-01-25 21:29:23 +0000966 /* Refresh cache */
967 if (option_bool(OPT_SCRIPT_ARP))
968 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +0000969 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +0100970
Simon Kelleya9530962012-03-20 22:07:35 +0000971# ifdef HAVE_TFTP
972 while (helper_buf_empty() && do_tftp_script_run());
973# endif
974
Simon Kelley16972692006-10-16 20:04:18 +0100975 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100976 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +0000977#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100978 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +0000979# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100980 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000981# endif
982
Simon Kelleyb633de92016-01-06 22:51:17 +0000983 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +0000984
985# ifdef HAVE_TFTP
986 while (do_tftp_script_run());
987# endif
988
Simon Kelley5aabfc72007-08-29 11:24:47 +0100989#endif
Simon Kelley33702ab2015-12-28 23:17:15 +0000990
Simon Kelley7622fc02009-06-04 20:32:05 +0100991
Simon Kelleyf2621c72007-04-29 19:47:21 +0100992 /* must do this just before select(), when we know no
993 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100994 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +0100995
Simon Kelleyb842bc92015-07-12 21:09:11 +0100996 if (do_poll(timeout) < 0)
997 continue;
998
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100999 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001000
Simon Kelleyb842bc92015-07-12 21:09:11 +01001001 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001002
1003 /* prime. */
1004 enumerate_interfaces(1);
1005
Simon Kelley74c95c22011-10-19 09:33:39 +01001006 /* Check the interfaces to see if any have exited DAD state
1007 and if so, bind the address. */
1008 if (is_dad_listeners())
1009 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001010 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001011 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1012 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001013 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001014 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001015
Simon Kelley1ee9be42013-12-09 16:50:19 +00001016#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001017 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001018 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001019#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001020 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001021 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001022#endif
1023
Simon Kelley04918052015-01-26 11:23:43 +00001024#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001025 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001026 {
1027 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1028 poll_resolv(1, 1, now);
1029 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001030#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001031 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001032 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001033 if (daemon->last_resolv == 0 ||
1034 difftime(now, daemon->last_resolv) > 1.0 ||
1035 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001036 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001037 /* poll_resolv doesn't need to reload first time through, since
1038 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001039
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001040 poll_resolv(0, daemon->last_resolv != 0, now);
1041 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001042 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001043#endif
1044
Simon Kelleyb842bc92015-07-12 21:09:11 +01001045 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001046 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001047
Simon Kelley3d8df262005-08-29 12:19:27 +01001048#ifdef HAVE_DBUS
1049 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001050 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001051 {
1052 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001053 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001054 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001055 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001056 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001057 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001058 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001059#endif
Simon Kelley824af852008-02-12 20:43:05 +00001060
Simon Kelleyb842bc92015-07-12 21:09:11 +01001061 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001062
1063#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001064 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001065#endif
1066
Simon Kelley7622fc02009-06-04 20:32:05 +01001067#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001068 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001069 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001070 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001071 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001072 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001073 dhcp_packet(now, 1);
1074 }
Simon Kelley16972692006-10-16 20:04:18 +01001075
Simon Kelley52b92f42012-01-22 16:05:15 +00001076#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001077 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001078 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001079
Simon Kelleyb842bc92015-07-12 21:09:11 +01001080 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001081 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001082#endif
1083
Simon Kelley1f15b812009-10-13 17:49:32 +01001084# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001085 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001086 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001087# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001088#endif
1089
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001090 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001091}
1092
Simon Kelley3be34542004-09-11 19:12:13 +01001093static void sig_handler(int sig)
1094{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001095 if (pid == 0)
1096 {
Simon Kelley16972692006-10-16 20:04:18 +01001097 /* ignore anything other than TERM during startup
1098 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001099 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001100 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001101 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001102 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001103 {
Simon Kelley16972692006-10-16 20:04:18 +01001104 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001105 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001106 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001107 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001108 else
1109 {
1110 /* master process */
1111 int event, errsave = errno;
1112
1113 if (sig == SIGHUP)
1114 event = EVENT_RELOAD;
1115 else if (sig == SIGCHLD)
1116 event = EVENT_CHILD;
1117 else if (sig == SIGALRM)
1118 event = EVENT_ALARM;
1119 else if (sig == SIGTERM)
1120 event = EVENT_TERM;
1121 else if (sig == SIGUSR1)
1122 event = EVENT_DUMP;
1123 else if (sig == SIGUSR2)
1124 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001125 else if (sig == SIGINT)
1126 {
1127 /* Handle SIGINT normally in debug mode, so
1128 ctrl-c continues to operate. */
1129 if (option_bool(OPT_DEBUG))
1130 exit(EC_MISC);
1131 else
1132 event = EVENT_TIME;
1133 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001134 else
1135 return;
1136
Simon Kelleyc72daea2012-01-05 21:33:27 +00001137 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001138 errno = errsave;
1139 }
Simon Kelley3be34542004-09-11 19:12:13 +01001140}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001141
Simon Kelley353ae4d2012-03-19 20:07:51 +00001142/* now == 0 -> queue immediate callback */
1143void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001144{
Simon Kelley884a6df2012-03-20 16:20:22 +00001145 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001146 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001147 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1148 if ((now == 0 || difftime(event, now) <= 0.0))
1149 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1150 else
1151 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001152 }
Simon Kelley741c2952012-02-25 13:09:18 +00001153}
1154
Simon Kelley47a95162014-07-08 22:22:02 +01001155void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001156{
Simon Kelley47a95162014-07-08 22:22:02 +01001157 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001158}
1159
Simon Kelleyc72daea2012-01-05 21:33:27 +00001160void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001161{
1162 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001163 struct iovec iov[2];
1164
Simon Kelley5aabfc72007-08-29 11:24:47 +01001165 ev.event = event;
1166 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001167 ev.msg_sz = msg ? strlen(msg) : 0;
1168
1169 iov[0].iov_base = &ev;
1170 iov[0].iov_len = sizeof(ev);
1171 iov[1].iov_base = msg;
1172 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001173
1174 /* error pipe, debug mode. */
1175 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001176 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001177 else
1178 /* pipe is non-blocking and struct event_desc is smaller than
1179 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001180 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001181}
Simon Kelley3d8df262005-08-29 12:19:27 +01001182
Simon Kelleyc72daea2012-01-05 21:33:27 +00001183/* NOTE: the memory used to return msg is leaked: use msgs in events only
1184 to describe fatal errors. */
1185static int read_event(int fd, struct event_desc *evp, char **msg)
1186{
1187 char *buf;
1188
1189 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1190 return 0;
1191
1192 *msg = NULL;
1193
1194 if (evp->msg_sz != 0 &&
1195 (buf = malloc(evp->msg_sz + 1)) &&
1196 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1197 {
1198 buf[evp->msg_sz] = 0;
1199 *msg = buf;
1200 }
1201
1202 return 1;
1203}
1204
1205static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001206{
1207 errno = ev->data;
1208
1209 switch (ev->event)
1210 {
1211 case EVENT_DIE:
1212 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001213
1214 case EVENT_FORK_ERR:
1215 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001216
1217 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001218 case EVENT_PIPE_ERR:
1219 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001220
1221 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001222 case EVENT_CAP_ERR:
1223 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1224
Simon Kelleye7a4af82018-02-16 21:27:35 +00001225 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001226 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001227 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001228
Simon Kelleye7a4af82018-02-16 21:27:35 +00001229 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001230 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001231 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001232
1233 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001234 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001235 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001236
Simon Kelleye7a4af82018-02-16 21:27:35 +00001237 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001238 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001239 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001240
1241 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001242 case EVENT_LUA_ERR:
1243 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001244
Simon Kelleye7a4af82018-02-16 21:27:35 +00001245 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001246 case EVENT_TFTP_ERR:
1247 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001248
1249 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001250 case EVENT_TIME_ERR:
1251 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001252 }
1253}
1254
Simon Kelley5aabfc72007-08-29 11:24:47 +01001255static void async_event(int pipe, time_t now)
1256{
1257 pid_t p;
1258 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001259 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001260 char *msg;
1261
1262 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1263 to describe fatal errors. */
1264
1265 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001266 switch (ev.event)
1267 {
1268 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001269 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001270
Simon Kelleye98bd522014-03-28 20:41:23 +00001271 /* fall through */
1272
1273 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001274 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001275
Simon Kelley7b1eae42014-02-20 13:43:28 +00001276 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001277 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001278 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1279 {
1280 reload_servers(daemon->resolv_files->name);
1281 check = 1;
1282 }
1283
1284 if (daemon->servers_file)
1285 {
1286 read_servers_file();
1287 check = 1;
1288 }
1289
1290 if (check)
1291 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001292 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001293
Simon Kelley7622fc02009-06-04 20:32:05 +01001294#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001295 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001296#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001297 break;
1298
1299 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001300 if (daemon->port != 0)
1301 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001302 break;
1303
1304 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001305#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001306 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001307 {
1308 lease_prune(NULL, now);
1309 lease_update_file(now);
1310 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001311#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001312 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001313 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1314 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001315#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001316#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001317 break;
1318
1319 case EVENT_CHILD:
1320 /* See Stevens 5.10 */
1321 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1322 if (p == -1)
1323 {
1324 if (errno != EINTR)
1325 break;
1326 }
1327 else
1328 for (i = 0 ; i < MAX_PROCS; i++)
1329 if (daemon->tcp_pids[i] == p)
1330 daemon->tcp_pids[i] = 0;
1331 break;
1332
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001333#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001334 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001335 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001336 break;
1337
1338 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001339 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001340 break;
1341
1342 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001343 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1344 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001345 break;
1346
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001347 case EVENT_SCRIPT_LOG:
1348 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1349 free(msg);
1350 msg = NULL;
1351 break;
1352
Simon Kelley1a6bca82008-07-11 11:11:42 +01001353 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001354 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001355 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001356 case EVENT_LUA_ERR:
1357 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001358 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001359#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001360
Simon Kelley5aabfc72007-08-29 11:24:47 +01001361 case EVENT_REOPEN:
1362 /* Note: this may leave TCP-handling processes with the old file still open.
1363 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1364 we leave them logging to the old file. */
1365 if (daemon->log_file != NULL)
1366 log_reopen(daemon->log_file);
1367 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001368
1369 case EVENT_NEWADDR:
1370 newaddress(now);
1371 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001372
1373 case EVENT_NEWROUTE:
1374 resend_query();
1375 /* Force re-reading resolv file right now, for luck. */
1376 poll_resolv(0, 1, now);
1377 break;
1378
Simon Kelley3c973ad2018-01-14 21:05:37 +00001379 case EVENT_TIME:
1380#ifdef HAVE_DNSSEC
1381 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1382 {
1383 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1384 daemon->dnssec_no_time_check = 0;
1385 clear_cache_and_reload(now);
1386 }
1387#endif
1388 break;
1389
Simon Kelley5aabfc72007-08-29 11:24:47 +01001390 case EVENT_TERM:
1391 /* Knock all our children on the head. */
1392 for (i = 0; i < MAX_PROCS; i++)
1393 if (daemon->tcp_pids[i] != 0)
1394 kill(daemon->tcp_pids[i], SIGALRM);
1395
Simon Kelley53a91732016-01-06 17:59:13 +00001396#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001397 /* handle pending lease transitions */
1398 if (daemon->helperfd != -1)
1399 {
1400 /* block in writes until all done */
1401 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1402 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1403 do {
1404 helper_write();
1405 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001406 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001407 }
1408#endif
1409
1410 if (daemon->lease_stream)
1411 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001412
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001413#ifdef HAVE_DNSSEC
1414 /* update timestamp file on TERM if time is considered valid */
1415 if (daemon->back_to_the_future)
1416 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001417 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001418 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1419 }
1420#endif
1421
Simon Kelley73a08a22009-02-05 20:28:08 +00001422 if (daemon->runfile)
1423 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001424
1425 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1426 flush_log();
1427 exit(EC_GOOD);
1428 }
1429}
1430
Simon Kelley47a95162014-07-08 22:22:02 +01001431static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001432{
1433 struct resolvc *res, *latest;
1434 struct stat statbuf;
1435 time_t last_change = 0;
1436 /* There may be more than one possible file.
1437 Go through and find the one which changed _last_.
1438 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001439
Simon Kelley28866e92011-02-14 20:19:14 +00001440 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001441 return;
1442
Simon Kelley5aabfc72007-08-29 11:24:47 +01001443 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1444 if (stat(res->name, &statbuf) == -1)
1445 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001446 if (force)
1447 {
1448 res->mtime = 0;
1449 continue;
1450 }
1451
Simon Kelley5aabfc72007-08-29 11:24:47 +01001452 if (!res->logged)
1453 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1454 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001455
1456 if (res->mtime != 0)
1457 {
1458 /* existing file evaporated, force selection of the latest
1459 file even if its mtime hasn't changed since we last looked */
1460 poll_resolv(1, do_reload, now);
1461 return;
1462 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001463 }
1464 else
1465 {
1466 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001467 if (force || (statbuf.st_mtime != res->mtime))
1468 {
1469 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001470 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1471 {
1472 last_change = statbuf.st_mtime;
1473 latest = res;
1474 }
1475 }
1476 }
1477
1478 if (latest)
1479 {
1480 static int warned = 0;
1481 if (reload_servers(latest->name))
1482 {
1483 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1484 warned = 0;
1485 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001486 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001487 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001488 }
1489 else
1490 {
1491 latest->mtime = 0;
1492 if (!warned)
1493 {
1494 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1495 warned = 1;
1496 }
1497 }
1498 }
1499}
1500
1501void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001502{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001503 (void)now;
1504
Simon Kelley824af852008-02-12 20:43:05 +00001505 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001506 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001507
Simon Kelley7622fc02009-06-04 20:32:05 +01001508#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001509 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001510 {
Simon Kelley28866e92011-02-14 20:19:14 +00001511 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001512 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001513 reread_dhcp();
Simon Kelley04918052015-01-26 11:23:43 +00001514#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +00001515 set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001516#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001517 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001518 lease_update_from_configs();
1519 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001520 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001521 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001522#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001523 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001524 /* Not doing DHCP, so no lease system, manage
1525 alarms for ra only */
1526 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001527#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001528#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001529}
1530
Simon Kelleyb842bc92015-07-12 21:09:11 +01001531static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001532{
1533 struct serverfd *serverfdp;
1534 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001535 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001536
1537#ifdef HAVE_TFTP
1538 int tftp = 0;
1539 struct tftp_transfer *transfer;
1540 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1541 {
1542 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001543 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001544 }
1545#endif
1546
Simon Kelley16972692006-10-16 20:04:18 +01001547 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001548 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001549 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001550
Simon Kelley3be34542004-09-11 19:12:13 +01001551 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001552 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001553
Simon Kelley1a6bca82008-07-11 11:11:42 +01001554 if (daemon->port != 0 && !daemon->osport)
1555 for (i = 0; i < RANDOM_SOCKS; i++)
1556 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001557 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001558
Simon Kelley3be34542004-09-11 19:12:13 +01001559 for (listener = daemon->listeners; listener; listener = listener->next)
1560 {
Simon Kelley16972692006-10-16 20:04:18 +01001561 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001562 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001563 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001564
Simon Kelley16972692006-10-16 20:04:18 +01001565 /* death of a child goes through the select loop, so
1566 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001567 if (listener->tcpfd != -1)
1568 for (i = 0; i < MAX_PROCS; i++)
1569 if (daemon->tcp_pids[i] == 0)
1570 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001571 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001572 break;
1573 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001574
Simon Kelley832af0b2007-01-21 20:01:28 +00001575#ifdef HAVE_TFTP
1576 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001577 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001578#endif
1579
1580 }
1581
Simon Kelley16972692006-10-16 20:04:18 +01001582 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001583}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001584
Simon Kelleyb842bc92015-07-12 21:09:11 +01001585static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001586{
1587 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001588 struct listener *listener;
1589 int i;
1590
Simon Kelley832af0b2007-01-21 20:01:28 +00001591 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001592 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001593 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1594
1595 if (daemon->port != 0 && !daemon->osport)
1596 for (i = 0; i < RANDOM_SOCKS; i++)
1597 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001598 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001599 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001600
1601 for (listener = daemon->listeners; listener; listener = listener->next)
1602 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001603 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001604 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001605
Simon Kelley832af0b2007-01-21 20:01:28 +00001606#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001607 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001608 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001609#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001610
Simon Kelleyb842bc92015-07-12 21:09:11 +01001611 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001612 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001613 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001614 struct irec *iface = NULL;
1615 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001616 union mysockaddr tcp_addr;
1617 socklen_t tcp_len = sizeof(union mysockaddr);
1618
1619 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001620
Simon Kelley46b06652013-02-04 21:47:59 +00001621 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001622 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001623
Simon Kelley46b06652013-02-04 21:47:59 +00001624 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1625 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001626 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001627 continue;
1628 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001629
1630 /* Make sure that the interface list is up-to-date.
1631
1632 We do this here as we may need the results below, and
1633 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001634
Simon Kelley76dd75d2013-05-23 10:04:25 +01001635 Multiple calls to enumerate_interfaces() per select loop are
1636 inhibited, so calls to it in the child process (which doesn't select())
1637 have no effect. This avoids two processes reading from the same
1638 netlink fd and screwing the pooch entirely.
1639 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001640
Simon Kelley76dd75d2013-05-23 10:04:25 +01001641 enumerate_interfaces(0);
1642
1643 if (option_bool(OPT_NOWILD))
1644 iface = listener->iface; /* May be NULL */
1645 else
1646 {
1647 int if_index;
1648 char intr_name[IF_NAMESIZE];
1649
1650 /* if we can find the arrival interface, check it's one that's allowed */
1651 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1652 indextoname(listener->tcpfd, if_index, intr_name))
1653 {
1654 struct all_addr addr;
1655 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001656#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001657 if (tcp_addr.sa.sa_family == AF_INET6)
1658 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001659#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001660
1661 for (iface = daemon->interfaces; iface; iface = iface->next)
1662 if (iface->index == if_index)
1663 break;
1664
1665 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1666 client_ok = 0;
1667 }
1668
1669 if (option_bool(OPT_CLEVERBIND))
1670 iface = listener->iface; /* May be NULL */
1671 else
1672 {
1673 /* Check for allowed interfaces when binding the wildcard address:
1674 we do this by looking for an interface with the same address as
1675 the local address of the TCP connection, then looking to see if that's
1676 an allowed interface. As a side effect, we get the netmask of the
1677 interface too, for localisation. */
1678
1679 for (iface = daemon->interfaces; iface; iface = iface->next)
1680 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1681 break;
1682
1683 if (!iface)
1684 client_ok = 0;
1685 }
1686 }
1687
Simon Kelley22ce5502013-01-22 13:53:04 +00001688 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001689 {
1690 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001691 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001692 }
1693#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001694 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001695 {
1696 if (p != -1)
1697 {
1698 int i;
1699 for (i = 0; i < MAX_PROCS; i++)
1700 if (daemon->tcp_pids[i] == 0)
1701 {
1702 daemon->tcp_pids[i] = p;
1703 break;
1704 }
1705 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001706 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001707
1708 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1709 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001710 }
1711#endif
1712 else
1713 {
1714 unsigned char *buff;
1715 struct server *s;
1716 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001717 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001718 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001719
1720 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001721 {
1722 netmask = iface->netmask;
1723 auth_dns = iface->dns_auth;
1724 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001725 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001726 {
1727 netmask.s_addr = 0;
1728 auth_dns = 0;
1729 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001730
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001731#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001732 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001733 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001734 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001735 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001736#endif
1737
Simon Kelley832af0b2007-01-21 20:01:28 +00001738 /* start with no upstream connections. */
1739 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001740 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001741
1742 /* The connected socket inherits non-blocking
1743 attribute from the listening socket.
1744 Reset that here. */
1745 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1746 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1747
Simon Kelley4f7b3042012-11-28 21:27:02 +00001748 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001749
Simon Kelley832af0b2007-01-21 20:01:28 +00001750 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001751 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001752
1753 if (buff)
1754 free(buff);
1755
1756 for (s = daemon->servers; s; s = s->next)
1757 if (s->tcpfd != -1)
1758 {
1759 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001760 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001761 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001762#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001763 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001764 {
1765 flush_log();
1766 _exit(0);
1767 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001768#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001769 }
1770 }
1771 }
Simon Kelley3be34542004-09-11 19:12:13 +01001772}
1773
Simon Kelley7622fc02009-06-04 20:32:05 +01001774#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001775int make_icmp_sock(void)
1776{
Simon Kelley7cebd202006-05-06 14:13:33 +01001777 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001778 int zeroopt = 0;
1779
1780 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1781 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001782 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001783 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1784 {
1785 close(fd);
1786 fd = -1;
1787 }
1788 }
1789
1790 return fd;
1791}
1792
Simon Kelley5aabfc72007-08-29 11:24:47 +01001793int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001794{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001795 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001796
Floris Bos503c6092017-04-09 23:07:13 +01001797 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001798 struct sockaddr_in saddr;
1799 struct {
1800 struct ip ip;
1801 struct icmp icmp;
1802 } packet;
1803 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001804 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001805 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001806
Simon Kelley824af852008-02-12 20:43:05 +00001807#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001808 if ((fd = make_icmp_sock()) == -1)
1809 return 0;
1810#else
1811 int opt = 2000;
1812 fd = daemon->dhcp_icmp_fd;
1813 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1814#endif
1815
Simon Kelley3be34542004-09-11 19:12:13 +01001816 saddr.sin_family = AF_INET;
1817 saddr.sin_port = 0;
1818 saddr.sin_addr = addr;
1819#ifdef HAVE_SOCKADDR_SA_LEN
1820 saddr.sin_len = sizeof(struct sockaddr_in);
1821#endif
1822
1823 memset(&packet.icmp, 0, sizeof(packet.icmp));
1824 packet.icmp.icmp_type = ICMP_ECHO;
1825 packet.icmp.icmp_id = id;
1826 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1827 j += ((u16 *)&packet.icmp)[i];
1828 while (j>>16)
1829 j = (j & 0xffff) + (j >> 16);
1830 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1831
Simon Kelleyff841eb2015-03-11 21:36:30 +00001832 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1833 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001834
Floris Bos503c6092017-04-09 23:07:13 +01001835 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1836
1837#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1838 while (retry_send(close(fd)));
1839#else
1840 opt = 1;
1841 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1842#endif
1843
1844 return gotreply;
1845}
1846
1847int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1848{
1849 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1850 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1851 from "addr" with ICMP ID "id" and return 1 */
1852
1853 /* Note that whilst waiting, we check for
1854 (and service) events on the DNS and TFTP sockets, (so doing that
1855 better not use any resources our caller has in use...)
1856 but we remain deaf to signals or further DHCP packets. */
1857
1858 /* There can be a problem using dnsmasq_time() to end the loop, since
1859 it's not monotonic, and can go backwards if the system clock is
1860 tweaked, leading to the code getting stuck in this loop and
1861 ignoring DHCP requests. To fix this, we check to see if select returned
1862 as a result of a timeout rather than a socket becoming available. We
1863 only allow this to happen as many times as it takes to get to the wait time
1864 in quarter-second chunks. This provides a fallback way to end loop. */
1865
1866 int rc, timeout_count;
1867 time_t now;
1868
1869 for (now = dnsmasq_time(), timeout_count = 0;
1870 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001871 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001872 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001873 if (fd != -1)
1874 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001875 set_dns_listeners(now);
1876 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001877
1878#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001879 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001880 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001881#endif
1882
Simon Kelleyb842bc92015-07-12 21:09:11 +01001883 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001884
1885 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001886 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001887 else if (rc == 0)
1888 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001889
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001890 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001891
Simon Kelleyb842bc92015-07-12 21:09:11 +01001892 check_log_writer(0);
1893 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001894
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001895#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001896 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001897 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001898#endif
1899
Simon Kelley832af0b2007-01-21 20:01:28 +00001900#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001901 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001902#endif
1903
Floris Bos503c6092017-04-09 23:07:13 +01001904 if (fd != -1)
1905 {
1906 struct {
1907 struct ip ip;
1908 struct icmp icmp;
1909 } packet;
1910 struct sockaddr_in faddr;
1911 socklen_t len = sizeof(faddr);
1912
1913 if (poll_check(fd, POLLIN) &&
1914 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1915 addr == faddr.sin_addr.s_addr &&
1916 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1917 packet.icmp.icmp_seq == 0 &&
1918 packet.icmp.icmp_id == id)
1919 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001920 }
1921 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001922
Floris Bos503c6092017-04-09 23:07:13 +01001923 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001924}
Simon Kelley7622fc02009-06-04 20:32:05 +01001925#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001926
1927