blob: 1ae7aad22aad83b861454d1c50f0f9d61dc54f4f [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;
51#if defined(HAVE_LINUX_NETWORK)
52 cap_user_header_t hdr = NULL;
53 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010054 char *bound_device = NULL;
55 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010056#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010057#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000058 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010059 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010060#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010061#ifdef HAVE_TFTP
62 int tftp_prefix_missing = 0;
63#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010064
Simon Kelley824af852008-02-12 20:43:05 +000065#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000066 setlocale(LC_ALL, "");
67 bindtextdomain("dnsmasq", LOCALEDIR);
68 textdomain("dnsmasq");
69#endif
70
Simon Kelley9e4abcb2004-01-22 19:47:41 +000071 sigact.sa_handler = sig_handler;
72 sigact.sa_flags = 0;
73 sigemptyset(&sigact.sa_mask);
74 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010075 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000076 sigaction(SIGHUP, &sigact, NULL);
77 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000078 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010079 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000080 sigaction(SIGINT, &sigact, NULL);
81
Simon Kelleyfeba5c12004-07-27 20:28:58 +010082 /* ignore SIGPIPE */
83 sigact.sa_handler = SIG_IGN;
84 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000085
Simon Kelley5aabfc72007-08-29 11:24:47 +010086 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010087
88 rand_init(); /* Must precede read_opts() */
89
Simon Kelley5aabfc72007-08-29 11:24:47 +010090 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000091
Simon Kelley3be34542004-09-11 19:12:13 +010092 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000093 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000094
Simon Kelleyd3a8b392015-12-23 12:27:37 +000095 /* Min buffer size: we check after adding each record, so there must be
96 memory for the largest packet, and the largest record so the
97 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
98 This might be increased is EDNS packet size if greater than the minimum. */
99 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000100 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000101
Simon Kelleyc72daea2012-01-05 21:33:27 +0000102 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000103 if (option_bool(OPT_EXTRALOG))
104 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000105
106#ifdef HAVE_DNSSEC
107 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000108 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100109 /* Note that both /000 and '.' are allowed within labels. These get
110 represented in presentation format using NAME_ESCAPE as an escape
111 character when in DNSSEC mode.
112 In theory, if all the characters in a name were /000 or
113 '.' or NAME_ESCAPE then all would have to be escaped, so the
114 presentation format would be twice as long as the spec.
115
116 daemon->namebuff was previously allocated by the option-reading
117 code before we knew if we're in DNSSEC mode, so reallocate here. */
118 free(daemon->namebuff);
119 daemon->namebuff = safe_malloc(MAXDNAME * 2);
120 daemon->keyname = safe_malloc(MAXDNAME * 2);
121 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000122 /* one char flag per possible RR in answer section (may get extended). */
123 daemon->rr_status_sz = 64;
124 daemon->rr_status = safe_malloc(daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000125 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000126#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000127
Simon Kelley7622fc02009-06-04 20:32:05 +0100128#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100129 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000130 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000131 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100132 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000133 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100134#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000135
Simon Kelleya2761752012-01-18 16:07:21 +0000136 /* Close any file descriptors we inherited apart from std{in|out|err}
137
138 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
139 otherwise file descriptors we create can end up being 0, 1, or 2
140 and then get accidentally closed later when we make 0, 1, and 2
141 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
142 but it's not guaranteed. By opening /dev/null three times, we
143 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100144 for (i = 0; i < max_fd; i++)
145 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
146 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000147 else
148 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100149
Simon Kelley801ca9a2012-03-06 19:30:17 +0000150#ifndef HAVE_LINUX_NETWORK
151# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000152 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100153 {
154 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000155 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100156 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000157# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100158
159 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100160 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100161 {
162 bind_fallback = 1;
163 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100164 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100165 }
Simon Kelley04918052015-01-26 11:23:43 +0000166#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000167
Simon Kelley04918052015-01-26 11:23:43 +0000168#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000169 if (daemon->dynamic_dirs)
170 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100171#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100172
Simon Kelley0744ca62014-01-25 16:40:15 +0000173 if (option_bool(OPT_DNSSEC_VALID))
174 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000175#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000176 struct ds_config *ds;
177
178 /* Must have at least a root trust anchor, or the DNSSEC code
179 can loop forever. */
180 for (ds = daemon->ds; ds; ds = ds->next)
181 if (ds->name[0] == 0)
182 break;
183
184 if (!ds)
185 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000186
187 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000188 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000189#else
190 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000191#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000192 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000193
Simon Kelley832af0b2007-01-21 20:01:28 +0000194#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100195 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100196 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000197#endif
198
Simon Kelley7de060b2011-08-26 17:24:52 +0100199#ifdef HAVE_CONNTRACK
200 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000201 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100202#else
203 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000204 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100205#endif
206
Simon Kelley824af852008-02-12 20:43:05 +0000207#ifdef HAVE_SOLARIS_NETWORK
208 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000209 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000210#endif
211
Simon Kelley572b41e2011-02-18 18:11:18 +0000212#ifdef __ANDROID__
213 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000214 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000215#endif
216
Simon Kelley4820dce2012-12-18 18:30:30 +0000217#ifndef HAVE_AUTH
218 if (daemon->authserver)
219 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
220#endif
221
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100222#ifndef HAVE_LOOP
223 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000224 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100225#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000226
Hans Dedecker926332a2016-01-23 10:48:12 +0000227 if (daemon->max_port < daemon->min_port)
228 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
229
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100230 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000231
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000232 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000233 if (daemon->authinterface && daemon->soa_sn == 0)
234#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000235 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000236#else
237 daemon->soa_sn = now;
238#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000239
Simon Kelleyff7eea22013-09-04 18:01:38 +0100240#ifdef HAVE_DHCP6
241 if (daemon->dhcp6)
242 {
243 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000244
Simon Kelleyff7eea22013-09-04 18:01:38 +0100245 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000246 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100247 if (context->flags & CONTEXT_DHCP)
248 daemon->doing_dhcp6 = 1;
249 if (context->flags & CONTEXT_RA)
250 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000251#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100252 if (context->flags & CONTEXT_TEMPLATE)
253 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000254#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000255 }
Simon Kelley1f776932012-12-16 19:46:08 +0000256 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100257#endif
258
259#ifdef HAVE_DHCP
260 /* Note that order matters here, we must call lease_init before
261 creating any file descriptors which shouldn't be leaked
262 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000263 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000264 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000265 conditions below. */
266 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000267 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100268 {
269 dhcp_common_init();
270 if (daemon->dhcp || daemon->doing_dhcp6)
271 lease_init(now);
272 }
273
274 if (daemon->dhcp || daemon->relay4)
275 dhcp_init();
276
277# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100278 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100279 ra_init(now);
280
281 if (daemon->doing_dhcp6 || daemon->relay6)
282 dhcp6_init();
283# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000284
Simon Kelley7622fc02009-06-04 20:32:05 +0100285#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100286
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000287#ifdef HAVE_IPSET
288 if (daemon->ipsets)
289 ipset_init();
290#endif
291
Simon Kelley1ee9be42013-12-09 16:50:19 +0000292#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000293 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000294#elif defined(HAVE_BSD_NETWORK)
295 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000296#endif
297
Simon Kelley1ee9be42013-12-09 16:50:19 +0000298 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
299 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
300
Simon Kelley115ac3e2013-05-20 11:28:32 +0100301 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100302 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000303
Simon Kelley54dd3932012-06-20 11:23:38 +0100304 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100305 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100306 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100307
308 if (!option_bool(OPT_CLEVERBIND))
309 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
310 if (if_tmp->name && !if_tmp->used)
311 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100312
313#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
314 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100315 bound_device = whichdevice();
316
Simon Kelley9380ba72012-04-16 14:41:56 +0100317 if (daemon->dhcp)
318 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100319 if (!daemon->relay4 && bound_device)
320 {
321 bindtodevice(bound_device, daemon->dhcpfd);
322 did_bind = 1;
323 }
324 if (daemon->enable_pxe && bound_device)
325 {
326 bindtodevice(bound_device, daemon->pxefd);
327 did_bind = 1;
328 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100329 }
330#endif
331
332#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100333 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
334 {
335 bindtodevice(bound_device, daemon->dhcp6fd);
336 did_bind = 1;
337 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100338#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100339 }
Simon Kelley28866e92011-02-14 20:19:14 +0000340 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100341 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000342
343#ifdef HAVE_DHCP6
344 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100345 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000346 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000347
348 /* After netlink_init() and before create_helper() */
349 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000350#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100351
Simon Kelley824af852008-02-12 20:43:05 +0000352 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000353 {
354 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000355
Simon Kelley82e3f452014-01-31 21:05:48 +0000356#ifdef HAVE_DNSSEC
357 blockdata_init();
358#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000359 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000360
Simon Kelley04918052015-01-26 11:23:43 +0000361#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000362 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
363 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000364 inotify_dnsmasq_init();
365 else
366 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000367#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000368
Simon Kelley28866e92011-02-14 20:19:14 +0000369 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100370#ifdef HAVE_DBUS
371 {
372 char *err;
373 daemon->dbus = NULL;
374 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100375 if ((err = dbus_init()))
376 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100377 }
378#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100379 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100380#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100381
Simon Kelley824af852008-02-12 20:43:05 +0000382 if (daemon->port != 0)
383 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100384
Simon Kelleyc72daea2012-01-05 21:33:27 +0000385#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100386 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000387 if ((daemon->dhcp || daemon->dhcp6) &&
388 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000389 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100390 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000391 struct passwd *scr_pw;
392
393 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100394 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000395 script_uid = scr_pw->pw_uid;
396 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100397 }
398 else
399 baduser = daemon->scriptuser;
400 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100401#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000402
Simon Kelley1a6bca82008-07-11 11:11:42 +0100403 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
404 baduser = daemon->username;
405 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
406 baduser = daemon->groupname;
407
408 if (baduser)
409 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000410
Simon Kelley1a6bca82008-07-11 11:11:42 +0100411 /* implement group defaults, "dip" if available, or group associated with uid */
412 if (!daemon->group_set && !gp)
413 {
414 if (!(gp = getgrnam(CHGRP)) && ent_pw)
415 gp = getgrgid(ent_pw->pw_gid);
416
417 /* for error message */
418 if (gp)
419 daemon->groupname = gp->gr_name;
420 }
421
422#if defined(HAVE_LINUX_NETWORK)
423 /* determine capability API version here, while we can still
424 call safe_malloc */
425 if (ent_pw && ent_pw->pw_uid != 0)
426 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100427 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100428 hdr = safe_malloc(sizeof(*hdr));
429
Simon Kelley1a6bca82008-07-11 11:11:42 +0100430 /* find version supported by kernel */
431 memset(hdr, 0, sizeof(*hdr));
432 capget(hdr, NULL);
433
434 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
435 {
436 /* if unknown version, use largest supported version (3) */
437 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
438 hdr->version = LINUX_CAPABILITY_VERSION_3;
439 capsize = 2;
440 }
441
442 data = safe_malloc(sizeof(*data) * capsize);
443 memset(data, 0, sizeof(*data) * capsize);
444 }
445#endif
446
Simon Kelley5aabfc72007-08-29 11:24:47 +0100447 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100448 in a race-free manner and another to carry errors to daemon-invoking process */
449 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100450
451 piperead = pipefd[0];
452 pipewrite = pipefd[1];
453 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000454 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100455
456 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100457
Simon Kelley28866e92011-02-14 20:19:14 +0000458 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000459 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000460 /* The following code "daemonizes" the process.
461 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100462
Simon Kelley9e038942008-05-30 20:06:34 +0100463 if (chdir("/") != 0)
464 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
465
Simon Kelley16972692006-10-16 20:04:18 +0100466#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000467 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100468 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100469 pid_t pid;
470
Simon Kelley1a6bca82008-07-11 11:11:42 +0100471 /* pipe to carry errors back to original process.
472 When startup is complete we close this and the process terminates. */
473 safe_pipe(err_pipe, 0);
474
Simon Kelley7622fc02009-06-04 20:32:05 +0100475 if ((pid = fork()) == -1)
476 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000477 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100478
Simon Kelley5aabfc72007-08-29 11:24:47 +0100479 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100480 {
481 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000482 char *msg;
483
Simon Kelley1a6bca82008-07-11 11:11:42 +0100484 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000485 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100486
487 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000488 if (read_event(err_pipe[0], &ev, &msg))
489 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100490
491 _exit(EC_GOOD);
492 }
493
Simon Kelleyff841eb2015-03-11 21:36:30 +0000494 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100495
496 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100497
498 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100499
500 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000501 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100502
503 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100504 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100505 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000506#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100507
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000508 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100509 if (daemon->runfile)
510 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100511 int fd, err = 0;
512
513 sprintf(daemon->namebuff, "%d\n", (int) getpid());
514
515 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
516 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
517 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
518 extent that an attacker running as the unprivileged user could replace the pidfile with a
519 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
520
Josh Soref730c6742017-02-06 16:14:04 +0000521 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100522 ensuring that the open() fails should there be any existing file (because the unlink() failed,
523 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
524 attack can succeed.
525
526 Any compromise of the non-privileged user still theoretically allows the pid-file to be
527 replaced whilst dnsmasq is running. The worst that could allow is that the usual
528 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
529
530 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
531 failure to write the pid-file.
532 */
533
534 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100535
Simon Kelley79cfefd2012-09-02 13:29:51 +0100536 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 +0100537 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100538 /* only complain if started as root */
539 if (getuid() == 0)
540 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100541 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100542 else
543 {
544 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
545 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000546 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000547 {
548 while (retry_send(close(fd)));
549 if (errno != 0)
550 err = 1;
551 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100552 }
553
554 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100555 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000556 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100557 _exit(0);
558 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000559 }
Simon Kelley16972692006-10-16 20:04:18 +0100560 }
561
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100562 log_err = log_start(ent_pw, err_pipe[1]);
563
Simon Kelley28866e92011-02-14 20:19:14 +0000564 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100565 {
566 /* open stdout etc to /dev/null */
567 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000568 if (nullfd != -1)
569 {
570 dup2(nullfd, STDOUT_FILENO);
571 dup2(nullfd, STDERR_FILENO);
572 dup2(nullfd, STDIN_FILENO);
573 close(nullfd);
574 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100575 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100576
Simon Kelley1a6bca82008-07-11 11:11:42 +0100577 /* if we are to run scripts, we need to fork a helper before dropping root. */
578 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000579#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000580 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000581 (daemon->lease_change_command || daemon->luascript))
582 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100583#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100584
Simon Kelley28866e92011-02-14 20:19:14 +0000585 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100586 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100587 int bad_capabilities = 0;
588 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100589
Josh Soref730c6742017-02-06 16:14:04 +0000590 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100591 if (gp &&
592 (setgroups(0, &dummy) == -1 ||
593 setgid(gp->gr_gid) == -1))
594 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000595 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100596 _exit(0);
597 }
598
Simon Kelley7cebd202006-05-06 14:13:33 +0100599 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100600 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100601#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100602 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100603 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100604 ports because of DAD, or we're doing it dynamically,
605 we need CAP_NET_BIND_SERVICE too. */
606 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100607 data->effective = data->permitted = data->inheritable =
608 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
609 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
610 else
611 data->effective = data->permitted = data->inheritable =
612 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100613
Simon Kelley16972692006-10-16 20:04:18 +0100614 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000615 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100616 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100617
Simon Kelley7622fc02009-06-04 20:32:05 +0100618#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000619 /* http://developers.sun.com/solaris/articles/program_privileges.html */
620 priv_set_t *priv_set;
621
622 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
623 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
624 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
625 bad_capabilities = errno;
626
627 if (priv_set && bad_capabilities == 0)
628 {
629 priv_inverse(priv_set);
630
631 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
632 bad_capabilities = errno;
633 }
634
635 if (priv_set)
636 priv_freeset(priv_set);
637
Simon Kelley824af852008-02-12 20:43:05 +0000638#endif
639
Simon Kelley1a6bca82008-07-11 11:11:42 +0100640 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100641 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000642 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100643 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100644 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100645
646 /* finally drop root */
647 if (setuid(ent_pw->pw_uid) == -1)
648 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000649 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100650 _exit(0);
651 }
652
653#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100654 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100655 data->effective = data->permitted =
656 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
657 else
658 data->effective = data->permitted =
659 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100660 data->inheritable = 0;
661
Josh Soref730c6742017-02-06 16:14:04 +0000662 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100663 if (capset(hdr, data) == -1)
664 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000665 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100666 _exit(0);
667 }
668#endif
669
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000670 }
Simon Kelley849a8352006-06-09 21:02:31 +0100671 }
Simon Kelley16972692006-10-16 20:04:18 +0100672
Simon Kelley16972692006-10-16 20:04:18 +0100673#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000674 free(hdr);
675 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000676 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000677 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100678#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100679
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100680#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100681 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100682 {
683 DIR *dir;
684 struct tftp_prefix *p;
685
686 if (daemon->tftp_prefix)
687 {
688 if (!((dir = opendir(daemon->tftp_prefix))))
689 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100690 tftp_prefix_missing = 1;
691 if (!option_bool(OPT_TFTP_NO_FAIL))
692 {
693 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
694 _exit(0);
695 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100696 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100697 else
698 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100699 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100700
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100701 for (p = daemon->if_prefix; p; p = p->next)
702 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100703 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100704 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100705 {
706 p->missing = 1;
707 if (!option_bool(OPT_TFTP_NO_FAIL))
708 {
709 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
710 _exit(0);
711 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100712 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100713 else
714 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100715 }
716 }
717#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100718
Simon Kelley824af852008-02-12 20:43:05 +0000719 if (daemon->port == 0)
720 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000721 else
722 {
723 if (daemon->cachesize != 0)
724 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
725 else
726 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
727
728 if (option_bool(OPT_LOCAL_SERVICE))
729 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
730 }
Simon Kelley16972692006-10-16 20:04:18 +0100731
Simon Kelleyf2621c72007-04-29 19:47:21 +0100732 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley16972692006-10-16 20:04:18 +0100733
Simon Kelley3d8df262005-08-29 12:19:27 +0100734#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000735 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100736 {
737 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100738 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100739 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100740 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100741 }
742#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000743
Simon Kelley1d97ac42014-01-31 11:12:27 +0000744#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000745 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000746 {
Simon Kelley360f2512015-03-07 18:28:06 +0000747 int rc;
748
749 /* Delay creating the timestamp file until here, after we've changed user, so that
750 it has the correct owner to allow updating the mtime later.
751 This means we have to report fatal errors via the pipe. */
752 if ((rc = setup_timestamp()) == -1)
753 {
754 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
755 _exit(0);
756 }
757
Simon Kelleye98bd522014-03-28 20:41:23 +0000758 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000759
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100760 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
761 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000762 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000763
764 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000765 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000766 }
Simon Kelleydb737462014-01-31 10:32:45 +0000767#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100768
Simon Kelley1a6bca82008-07-11 11:11:42 +0100769 if (log_err != 0)
770 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
771 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000772
Simon Kelleyde379512004-06-22 20:23:33 +0100773 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100774 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100775
Simon Kelleyf7029f52013-11-21 15:09:09 +0000776 if (option_bool(OPT_NOWILD))
777 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000778 else if (!option_bool(OPT_CLEVERBIND))
779 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000780
781 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100782
Simon Kelley28866e92011-02-14 20:19:14 +0000783 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000784 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
785 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100786 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100787
Simon Kelley28866e92011-02-14 20:19:14 +0000788 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100789 {
790 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100791 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100792 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000793 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100794 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100795 }
796
Simon Kelleyf2621c72007-04-29 19:47:21 +0100797 if (daemon->max_logs != 0)
798 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000799
Simon Kelleyf2621c72007-04-29 19:47:21 +0100800
Simon Kelley7622fc02009-06-04 20:32:05 +0100801#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000802 for (context = daemon->dhcp; context; context = context->next)
803 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100804
Simon Kelleyff7eea22013-09-04 18:01:38 +0100805 for (relay = daemon->relay4; relay; relay = relay->next)
806 log_relay(AF_INET, relay);
807
Simon Kelley1f776932012-12-16 19:46:08 +0000808# ifdef HAVE_DHCP6
809 for (context = daemon->dhcp6; context; context = context->next)
810 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000811
Simon Kelleyff7eea22013-09-04 18:01:38 +0100812 for (relay = daemon->relay6; relay; relay = relay->next)
813 log_relay(AF_INET6, relay);
814
Simon Kelley1f776932012-12-16 19:46:08 +0000815 if (daemon->doing_dhcp6 || daemon->doing_ra)
816 dhcp_construct_contexts(now);
817
818 if (option_bool(OPT_RA))
819 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
820# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000821
Simon Kelley3b3f4412013-10-11 16:33:28 +0100822# ifdef HAVE_LINUX_NETWORK
823 if (did_bind)
824 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
825# endif
826
Josh Soref730c6742017-02-06 16:14:04 +0000827 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000828 if (daemon->dhcp || daemon->doing_dhcp6)
829 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000830#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000831
Simon Kelley832af0b2007-01-21 20:01:28 +0000832#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000833 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100834 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100835 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000836
Simon Kelley7622fc02009-06-04 20:32:05 +0100837 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100838 daemon->tftp_prefix ? _("root is ") : _("enabled"),
839 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000840 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100841
Stefan Tomanek30d08792015-03-31 22:32:11 +0100842 if (tftp_prefix_missing)
843 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100844
Stefan Tomanek30d08792015-03-31 22:32:11 +0100845 for (p = daemon->if_prefix; p; p = p->next)
846 if (p->missing)
847 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
848
Simon Kelley832af0b2007-01-21 20:01:28 +0000849 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100850 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000851 a single file will be sent to may clients (the file only needs
852 one fd). */
853
854 max_fd -= 30; /* use other than TFTP */
855
856 if (max_fd < 0)
857 max_fd = 5;
858 else if (max_fd < 100)
859 max_fd = max_fd/2;
860 else
861 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000862
863 /* if we have to use a limited range of ports,
864 that will limit the number of transfers */
865 if (daemon->start_tftp_port != 0 &&
866 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
867 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000868
869 if (daemon->tftp_max > max_fd)
870 {
871 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100872 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100873 _("restricting maximum simultaneous TFTP transfers to %d"),
874 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000875 }
876 }
877#endif
878
Simon Kelley1a6bca82008-07-11 11:11:42 +0100879 /* finished start-up - release original process */
880 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000881 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000882
Simon Kelley824af852008-02-12 20:43:05 +0000883 if (daemon->port != 0)
884 check_servers();
885
Simon Kelley7cebd202006-05-06 14:13:33 +0100886 pid = getpid();
887
Simon Kelley04918052015-01-26 11:23:43 +0000888#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000889 /* Using inotify, have to select a resolv file at startup */
890 poll_resolv(1, 0, now);
891#endif
892
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100893 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000894 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100895 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000896
Simon Kelleyb842bc92015-07-12 21:09:11 +0100897 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000898
Simon Kelley16972692006-10-16 20:04:18 +0100899 /* if we are out of resources, find how long we have to wait
900 for some to come free, we'll loop around then and restart
901 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100902 if ((t = set_dns_listeners(now)) != 0)
903 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100904
Simon Kelley832af0b2007-01-21 20:01:28 +0000905 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
906 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000907 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100908 timeout = 250;
909
Simon Kelley74c95c22011-10-19 09:33:39 +0100910 /* Wake every second whilst waiting for DAD to complete */
911 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100912 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100913
Simon Kelley832af0b2007-01-21 20:01:28 +0000914#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100915 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100916#endif
917
Simon Kelley7622fc02009-06-04 20:32:05 +0100918#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100919 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100920 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100921 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000922 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100923 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100924 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100925#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100926
Simon Kelley52b92f42012-01-22 16:05:15 +0000927#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100928 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100929 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100930
Simon Kelley1f776932012-12-16 19:46:08 +0000931 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100932 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000933#endif
Simon Kelley04918052015-01-26 11:23:43 +0000934
935#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000936 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100937 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000938#endif
939
940#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100941 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000942#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100943 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100944#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000945
Simon Kelleyb842bc92015-07-12 21:09:11 +0100946 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100947
Simon Kelley33702ab2015-12-28 23:17:15 +0000948#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000949# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000950 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000951# endif
952
Simon Kelley1e505122016-01-25 21:29:23 +0000953 /* Refresh cache */
954 if (option_bool(OPT_SCRIPT_ARP))
955 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +0000956 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +0100957
Simon Kelleya9530962012-03-20 22:07:35 +0000958# ifdef HAVE_TFTP
959 while (helper_buf_empty() && do_tftp_script_run());
960# endif
961
Simon Kelley16972692006-10-16 20:04:18 +0100962 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100963 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +0000964#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100965 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +0000966# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100967 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000968# endif
969
Simon Kelleyb633de92016-01-06 22:51:17 +0000970 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +0000971
972# ifdef HAVE_TFTP
973 while (do_tftp_script_run());
974# endif
975
Simon Kelley5aabfc72007-08-29 11:24:47 +0100976#endif
Simon Kelley33702ab2015-12-28 23:17:15 +0000977
Simon Kelley7622fc02009-06-04 20:32:05 +0100978
Simon Kelleyf2621c72007-04-29 19:47:21 +0100979 /* must do this just before select(), when we know no
980 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100981 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +0100982
Simon Kelleyb842bc92015-07-12 21:09:11 +0100983 if (do_poll(timeout) < 0)
984 continue;
985
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100986 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000987
Simon Kelleyb842bc92015-07-12 21:09:11 +0100988 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100989
990 /* prime. */
991 enumerate_interfaces(1);
992
Simon Kelley74c95c22011-10-19 09:33:39 +0100993 /* Check the interfaces to see if any have exited DAD state
994 and if so, bind the address. */
995 if (is_dad_listeners())
996 {
Simon Kelley115ac3e2013-05-20 11:28:32 +0100997 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +0100998 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
999 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001000 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001001 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001002
Simon Kelley1ee9be42013-12-09 16:50:19 +00001003#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001004 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001005 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001006#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001007 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001008 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001009#endif
1010
Simon Kelley04918052015-01-26 11:23:43 +00001011#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001012 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001013 {
1014 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1015 poll_resolv(1, 1, now);
1016 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001017#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001018 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001019 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001020 if (daemon->last_resolv == 0 ||
1021 difftime(now, daemon->last_resolv) > 1.0 ||
1022 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001023 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001024 /* poll_resolv doesn't need to reload first time through, since
1025 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001026
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001027 poll_resolv(0, daemon->last_resolv != 0, now);
1028 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001029 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001030#endif
1031
Simon Kelleyb842bc92015-07-12 21:09:11 +01001032 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001033 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001034
Simon Kelley3d8df262005-08-29 12:19:27 +01001035#ifdef HAVE_DBUS
1036 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001037 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001038 {
1039 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001040 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001041 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001042 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001043 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001044 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001045 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001046#endif
Simon Kelley824af852008-02-12 20:43:05 +00001047
Simon Kelleyb842bc92015-07-12 21:09:11 +01001048 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001049
1050#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001051 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001052#endif
1053
Simon Kelley7622fc02009-06-04 20:32:05 +01001054#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001055 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001056 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001057 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001058 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001059 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001060 dhcp_packet(now, 1);
1061 }
Simon Kelley16972692006-10-16 20:04:18 +01001062
Simon Kelley52b92f42012-01-22 16:05:15 +00001063#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001064 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001065 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001066
Simon Kelleyb842bc92015-07-12 21:09:11 +01001067 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001068 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001069#endif
1070
Simon Kelley1f15b812009-10-13 17:49:32 +01001071# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001072 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001073 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001074# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001075#endif
1076
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001077 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001078}
1079
Simon Kelley3be34542004-09-11 19:12:13 +01001080static void sig_handler(int sig)
1081{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001082 if (pid == 0)
1083 {
Simon Kelley16972692006-10-16 20:04:18 +01001084 /* ignore anything other than TERM during startup
1085 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001086 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001087 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001088 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001089 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001090 {
Simon Kelley16972692006-10-16 20:04:18 +01001091 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001092 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001093 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001094 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001095 else
1096 {
1097 /* master process */
1098 int event, errsave = errno;
1099
1100 if (sig == SIGHUP)
1101 event = EVENT_RELOAD;
1102 else if (sig == SIGCHLD)
1103 event = EVENT_CHILD;
1104 else if (sig == SIGALRM)
1105 event = EVENT_ALARM;
1106 else if (sig == SIGTERM)
1107 event = EVENT_TERM;
1108 else if (sig == SIGUSR1)
1109 event = EVENT_DUMP;
1110 else if (sig == SIGUSR2)
1111 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001112 else if (sig == SIGINT)
1113 {
1114 /* Handle SIGINT normally in debug mode, so
1115 ctrl-c continues to operate. */
1116 if (option_bool(OPT_DEBUG))
1117 exit(EC_MISC);
1118 else
1119 event = EVENT_TIME;
1120 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001121 else
1122 return;
1123
Simon Kelleyc72daea2012-01-05 21:33:27 +00001124 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001125 errno = errsave;
1126 }
Simon Kelley3be34542004-09-11 19:12:13 +01001127}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001128
Simon Kelley353ae4d2012-03-19 20:07:51 +00001129/* now == 0 -> queue immediate callback */
1130void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001131{
Simon Kelley884a6df2012-03-20 16:20:22 +00001132 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001133 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001134 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1135 if ((now == 0 || difftime(event, now) <= 0.0))
1136 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1137 else
1138 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001139 }
Simon Kelley741c2952012-02-25 13:09:18 +00001140}
1141
Simon Kelley47a95162014-07-08 22:22:02 +01001142void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001143{
Simon Kelley47a95162014-07-08 22:22:02 +01001144 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001145}
1146
Simon Kelleyc72daea2012-01-05 21:33:27 +00001147void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001148{
1149 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001150 struct iovec iov[2];
1151
Simon Kelley5aabfc72007-08-29 11:24:47 +01001152 ev.event = event;
1153 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001154 ev.msg_sz = msg ? strlen(msg) : 0;
1155
1156 iov[0].iov_base = &ev;
1157 iov[0].iov_len = sizeof(ev);
1158 iov[1].iov_base = msg;
1159 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001160
1161 /* error pipe, debug mode. */
1162 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001163 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001164 else
1165 /* pipe is non-blocking and struct event_desc is smaller than
1166 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001167 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001168}
Simon Kelley3d8df262005-08-29 12:19:27 +01001169
Simon Kelleyc72daea2012-01-05 21:33:27 +00001170/* NOTE: the memory used to return msg is leaked: use msgs in events only
1171 to describe fatal errors. */
1172static int read_event(int fd, struct event_desc *evp, char **msg)
1173{
1174 char *buf;
1175
1176 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1177 return 0;
1178
1179 *msg = NULL;
1180
1181 if (evp->msg_sz != 0 &&
1182 (buf = malloc(evp->msg_sz + 1)) &&
1183 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1184 {
1185 buf[evp->msg_sz] = 0;
1186 *msg = buf;
1187 }
1188
1189 return 1;
1190}
1191
1192static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001193{
1194 errno = ev->data;
1195
1196 switch (ev->event)
1197 {
1198 case EVENT_DIE:
1199 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001200
1201 case EVENT_FORK_ERR:
1202 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001203
1204 case EVENT_PIPE_ERR:
1205 die(_("failed to create helper: %s"), NULL, EC_MISC);
1206
1207 case EVENT_CAP_ERR:
1208 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1209
1210 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001211 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001212
1213 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001214 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001215
1216 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001217 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001218
1219 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001220 die(_("cannot open log %s: %s"), msg, EC_FILE);
1221
1222 case EVENT_LUA_ERR:
1223 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001224
1225 case EVENT_TFTP_ERR:
1226 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelley360f2512015-03-07 18:28:06 +00001227
1228 case EVENT_TIME_ERR:
1229 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001230 }
1231}
1232
Simon Kelley5aabfc72007-08-29 11:24:47 +01001233static void async_event(int pipe, time_t now)
1234{
1235 pid_t p;
1236 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001237 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001238 char *msg;
1239
1240 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1241 to describe fatal errors. */
1242
1243 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001244 switch (ev.event)
1245 {
1246 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001247 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001248
Simon Kelleye98bd522014-03-28 20:41:23 +00001249 /* fall through */
1250
1251 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001252 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001253
Simon Kelley7b1eae42014-02-20 13:43:28 +00001254 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001255 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001256 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1257 {
1258 reload_servers(daemon->resolv_files->name);
1259 check = 1;
1260 }
1261
1262 if (daemon->servers_file)
1263 {
1264 read_servers_file();
1265 check = 1;
1266 }
1267
1268 if (check)
1269 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001270 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001271
Simon Kelley7622fc02009-06-04 20:32:05 +01001272#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001273 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001274#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001275 break;
1276
1277 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001278 if (daemon->port != 0)
1279 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001280 break;
1281
1282 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001283#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001284 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001285 {
1286 lease_prune(NULL, now);
1287 lease_update_file(now);
1288 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001289#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001290 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001291 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1292 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001293#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001294#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001295 break;
1296
1297 case EVENT_CHILD:
1298 /* See Stevens 5.10 */
1299 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1300 if (p == -1)
1301 {
1302 if (errno != EINTR)
1303 break;
1304 }
1305 else
1306 for (i = 0 ; i < MAX_PROCS; i++)
1307 if (daemon->tcp_pids[i] == p)
1308 daemon->tcp_pids[i] = 0;
1309 break;
1310
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001311#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001312 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001313 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001314 break;
1315
1316 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001317 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001318 break;
1319
1320 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001321 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1322 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001323 break;
1324
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001325 case EVENT_SCRIPT_LOG:
1326 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1327 free(msg);
1328 msg = NULL;
1329 break;
1330
Simon Kelley1a6bca82008-07-11 11:11:42 +01001331 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001332 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001333 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001334 case EVENT_LUA_ERR:
1335 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001336 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001337#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001338
Simon Kelley5aabfc72007-08-29 11:24:47 +01001339 case EVENT_REOPEN:
1340 /* Note: this may leave TCP-handling processes with the old file still open.
1341 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1342 we leave them logging to the old file. */
1343 if (daemon->log_file != NULL)
1344 log_reopen(daemon->log_file);
1345 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001346
1347 case EVENT_NEWADDR:
1348 newaddress(now);
1349 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001350
1351 case EVENT_NEWROUTE:
1352 resend_query();
1353 /* Force re-reading resolv file right now, for luck. */
1354 poll_resolv(0, 1, now);
1355 break;
1356
Simon Kelley3c973ad2018-01-14 21:05:37 +00001357 case EVENT_TIME:
1358#ifdef HAVE_DNSSEC
1359 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1360 {
1361 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1362 daemon->dnssec_no_time_check = 0;
1363 clear_cache_and_reload(now);
1364 }
1365#endif
1366 break;
1367
Simon Kelley5aabfc72007-08-29 11:24:47 +01001368 case EVENT_TERM:
1369 /* Knock all our children on the head. */
1370 for (i = 0; i < MAX_PROCS; i++)
1371 if (daemon->tcp_pids[i] != 0)
1372 kill(daemon->tcp_pids[i], SIGALRM);
1373
Simon Kelley53a91732016-01-06 17:59:13 +00001374#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001375 /* handle pending lease transitions */
1376 if (daemon->helperfd != -1)
1377 {
1378 /* block in writes until all done */
1379 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1380 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1381 do {
1382 helper_write();
1383 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001384 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001385 }
1386#endif
1387
1388 if (daemon->lease_stream)
1389 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001390
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001391#ifdef HAVE_DNSSEC
1392 /* update timestamp file on TERM if time is considered valid */
1393 if (daemon->back_to_the_future)
1394 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001395 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001396 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1397 }
1398#endif
1399
Simon Kelley73a08a22009-02-05 20:28:08 +00001400 if (daemon->runfile)
1401 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001402
1403 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1404 flush_log();
1405 exit(EC_GOOD);
1406 }
1407}
1408
Simon Kelley47a95162014-07-08 22:22:02 +01001409static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001410{
1411 struct resolvc *res, *latest;
1412 struct stat statbuf;
1413 time_t last_change = 0;
1414 /* There may be more than one possible file.
1415 Go through and find the one which changed _last_.
1416 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001417
Simon Kelley28866e92011-02-14 20:19:14 +00001418 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001419 return;
1420
Simon Kelley5aabfc72007-08-29 11:24:47 +01001421 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1422 if (stat(res->name, &statbuf) == -1)
1423 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001424 if (force)
1425 {
1426 res->mtime = 0;
1427 continue;
1428 }
1429
Simon Kelley5aabfc72007-08-29 11:24:47 +01001430 if (!res->logged)
1431 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1432 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001433
1434 if (res->mtime != 0)
1435 {
1436 /* existing file evaporated, force selection of the latest
1437 file even if its mtime hasn't changed since we last looked */
1438 poll_resolv(1, do_reload, now);
1439 return;
1440 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001441 }
1442 else
1443 {
1444 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001445 if (force || (statbuf.st_mtime != res->mtime))
1446 {
1447 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001448 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1449 {
1450 last_change = statbuf.st_mtime;
1451 latest = res;
1452 }
1453 }
1454 }
1455
1456 if (latest)
1457 {
1458 static int warned = 0;
1459 if (reload_servers(latest->name))
1460 {
1461 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1462 warned = 0;
1463 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001464 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001465 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001466 }
1467 else
1468 {
1469 latest->mtime = 0;
1470 if (!warned)
1471 {
1472 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1473 warned = 1;
1474 }
1475 }
1476 }
1477}
1478
1479void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001480{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001481 (void)now;
1482
Simon Kelley824af852008-02-12 20:43:05 +00001483 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001484 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001485
Simon Kelley7622fc02009-06-04 20:32:05 +01001486#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001487 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001488 {
Simon Kelley28866e92011-02-14 20:19:14 +00001489 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001490 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001491 reread_dhcp();
Simon Kelley04918052015-01-26 11:23:43 +00001492#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +00001493 set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001494#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001495 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001496 lease_update_from_configs();
1497 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001498 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001499 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001500#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001501 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001502 /* Not doing DHCP, so no lease system, manage
1503 alarms for ra only */
1504 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001505#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001506#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001507}
1508
Simon Kelleyb842bc92015-07-12 21:09:11 +01001509static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001510{
1511 struct serverfd *serverfdp;
1512 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001513 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001514
1515#ifdef HAVE_TFTP
1516 int tftp = 0;
1517 struct tftp_transfer *transfer;
1518 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1519 {
1520 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001521 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001522 }
1523#endif
1524
Simon Kelley16972692006-10-16 20:04:18 +01001525 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001526 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001527 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001528
Simon Kelley3be34542004-09-11 19:12:13 +01001529 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001530 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001531
Simon Kelley1a6bca82008-07-11 11:11:42 +01001532 if (daemon->port != 0 && !daemon->osport)
1533 for (i = 0; i < RANDOM_SOCKS; i++)
1534 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001535 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001536
Simon Kelley3be34542004-09-11 19:12:13 +01001537 for (listener = daemon->listeners; listener; listener = listener->next)
1538 {
Simon Kelley16972692006-10-16 20:04:18 +01001539 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001540 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001541 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001542
Simon Kelley16972692006-10-16 20:04:18 +01001543 /* death of a child goes through the select loop, so
1544 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001545 if (listener->tcpfd != -1)
1546 for (i = 0; i < MAX_PROCS; i++)
1547 if (daemon->tcp_pids[i] == 0)
1548 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001549 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001550 break;
1551 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001552
Simon Kelley832af0b2007-01-21 20:01:28 +00001553#ifdef HAVE_TFTP
1554 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001555 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001556#endif
1557
1558 }
1559
Simon Kelley16972692006-10-16 20:04:18 +01001560 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001561}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001562
Simon Kelleyb842bc92015-07-12 21:09:11 +01001563static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001564{
1565 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001566 struct listener *listener;
1567 int i;
1568
Simon Kelley832af0b2007-01-21 20:01:28 +00001569 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001570 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001571 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1572
1573 if (daemon->port != 0 && !daemon->osport)
1574 for (i = 0; i < RANDOM_SOCKS; i++)
1575 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001576 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001577 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001578
1579 for (listener = daemon->listeners; listener; listener = listener->next)
1580 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001581 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001582 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001583
Simon Kelley832af0b2007-01-21 20:01:28 +00001584#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001585 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001586 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001587#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001588
Simon Kelleyb842bc92015-07-12 21:09:11 +01001589 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001590 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001591 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001592 struct irec *iface = NULL;
1593 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001594 union mysockaddr tcp_addr;
1595 socklen_t tcp_len = sizeof(union mysockaddr);
1596
1597 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001598
Simon Kelley46b06652013-02-04 21:47:59 +00001599 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001600 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001601
Simon Kelley46b06652013-02-04 21:47:59 +00001602 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1603 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001604 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001605 continue;
1606 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001607
1608 /* Make sure that the interface list is up-to-date.
1609
1610 We do this here as we may need the results below, and
1611 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001612
Simon Kelley76dd75d2013-05-23 10:04:25 +01001613 Multiple calls to enumerate_interfaces() per select loop are
1614 inhibited, so calls to it in the child process (which doesn't select())
1615 have no effect. This avoids two processes reading from the same
1616 netlink fd and screwing the pooch entirely.
1617 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001618
Simon Kelley76dd75d2013-05-23 10:04:25 +01001619 enumerate_interfaces(0);
1620
1621 if (option_bool(OPT_NOWILD))
1622 iface = listener->iface; /* May be NULL */
1623 else
1624 {
1625 int if_index;
1626 char intr_name[IF_NAMESIZE];
1627
1628 /* if we can find the arrival interface, check it's one that's allowed */
1629 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1630 indextoname(listener->tcpfd, if_index, intr_name))
1631 {
1632 struct all_addr addr;
1633 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001634#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001635 if (tcp_addr.sa.sa_family == AF_INET6)
1636 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001637#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001638
1639 for (iface = daemon->interfaces; iface; iface = iface->next)
1640 if (iface->index == if_index)
1641 break;
1642
1643 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1644 client_ok = 0;
1645 }
1646
1647 if (option_bool(OPT_CLEVERBIND))
1648 iface = listener->iface; /* May be NULL */
1649 else
1650 {
1651 /* Check for allowed interfaces when binding the wildcard address:
1652 we do this by looking for an interface with the same address as
1653 the local address of the TCP connection, then looking to see if that's
1654 an allowed interface. As a side effect, we get the netmask of the
1655 interface too, for localisation. */
1656
1657 for (iface = daemon->interfaces; iface; iface = iface->next)
1658 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1659 break;
1660
1661 if (!iface)
1662 client_ok = 0;
1663 }
1664 }
1665
Simon Kelley22ce5502013-01-22 13:53:04 +00001666 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001667 {
1668 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001669 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001670 }
1671#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001672 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001673 {
1674 if (p != -1)
1675 {
1676 int i;
1677 for (i = 0; i < MAX_PROCS; i++)
1678 if (daemon->tcp_pids[i] == 0)
1679 {
1680 daemon->tcp_pids[i] = p;
1681 break;
1682 }
1683 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001684 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001685
1686 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1687 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001688 }
1689#endif
1690 else
1691 {
1692 unsigned char *buff;
1693 struct server *s;
1694 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001695 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001696 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001697
1698 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001699 {
1700 netmask = iface->netmask;
1701 auth_dns = iface->dns_auth;
1702 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001703 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001704 {
1705 netmask.s_addr = 0;
1706 auth_dns = 0;
1707 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001708
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001709#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001710 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001711 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001712 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001713 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001714#endif
1715
Simon Kelley832af0b2007-01-21 20:01:28 +00001716 /* start with no upstream connections. */
1717 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001718 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001719
1720 /* The connected socket inherits non-blocking
1721 attribute from the listening socket.
1722 Reset that here. */
1723 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1724 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1725
Simon Kelley4f7b3042012-11-28 21:27:02 +00001726 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001727
Simon Kelley832af0b2007-01-21 20:01:28 +00001728 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001729 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001730
1731 if (buff)
1732 free(buff);
1733
1734 for (s = daemon->servers; s; s = s->next)
1735 if (s->tcpfd != -1)
1736 {
1737 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001738 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001739 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001740#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001741 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001742 {
1743 flush_log();
1744 _exit(0);
1745 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001746#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001747 }
1748 }
1749 }
Simon Kelley3be34542004-09-11 19:12:13 +01001750}
1751
Simon Kelley7622fc02009-06-04 20:32:05 +01001752#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001753int make_icmp_sock(void)
1754{
Simon Kelley7cebd202006-05-06 14:13:33 +01001755 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001756 int zeroopt = 0;
1757
1758 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1759 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001760 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001761 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1762 {
1763 close(fd);
1764 fd = -1;
1765 }
1766 }
1767
1768 return fd;
1769}
1770
Simon Kelley5aabfc72007-08-29 11:24:47 +01001771int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001772{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001773 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001774
Floris Bos503c6092017-04-09 23:07:13 +01001775 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001776 struct sockaddr_in saddr;
1777 struct {
1778 struct ip ip;
1779 struct icmp icmp;
1780 } packet;
1781 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001782 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001783 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001784
Simon Kelley824af852008-02-12 20:43:05 +00001785#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001786 if ((fd = make_icmp_sock()) == -1)
1787 return 0;
1788#else
1789 int opt = 2000;
1790 fd = daemon->dhcp_icmp_fd;
1791 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1792#endif
1793
Simon Kelley3be34542004-09-11 19:12:13 +01001794 saddr.sin_family = AF_INET;
1795 saddr.sin_port = 0;
1796 saddr.sin_addr = addr;
1797#ifdef HAVE_SOCKADDR_SA_LEN
1798 saddr.sin_len = sizeof(struct sockaddr_in);
1799#endif
1800
1801 memset(&packet.icmp, 0, sizeof(packet.icmp));
1802 packet.icmp.icmp_type = ICMP_ECHO;
1803 packet.icmp.icmp_id = id;
1804 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1805 j += ((u16 *)&packet.icmp)[i];
1806 while (j>>16)
1807 j = (j & 0xffff) + (j >> 16);
1808 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1809
Simon Kelleyff841eb2015-03-11 21:36:30 +00001810 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1811 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001812
Floris Bos503c6092017-04-09 23:07:13 +01001813 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1814
1815#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1816 while (retry_send(close(fd)));
1817#else
1818 opt = 1;
1819 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1820#endif
1821
1822 return gotreply;
1823}
1824
1825int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1826{
1827 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1828 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1829 from "addr" with ICMP ID "id" and return 1 */
1830
1831 /* Note that whilst waiting, we check for
1832 (and service) events on the DNS and TFTP sockets, (so doing that
1833 better not use any resources our caller has in use...)
1834 but we remain deaf to signals or further DHCP packets. */
1835
1836 /* There can be a problem using dnsmasq_time() to end the loop, since
1837 it's not monotonic, and can go backwards if the system clock is
1838 tweaked, leading to the code getting stuck in this loop and
1839 ignoring DHCP requests. To fix this, we check to see if select returned
1840 as a result of a timeout rather than a socket becoming available. We
1841 only allow this to happen as many times as it takes to get to the wait time
1842 in quarter-second chunks. This provides a fallback way to end loop. */
1843
1844 int rc, timeout_count;
1845 time_t now;
1846
1847 for (now = dnsmasq_time(), timeout_count = 0;
1848 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001849 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001850 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001851 if (fd != -1)
1852 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001853 set_dns_listeners(now);
1854 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001855
1856#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001857 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001858 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001859#endif
1860
Simon Kelleyb842bc92015-07-12 21:09:11 +01001861 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001862
1863 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001864 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001865 else if (rc == 0)
1866 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001867
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001868 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001869
Simon Kelleyb842bc92015-07-12 21:09:11 +01001870 check_log_writer(0);
1871 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001872
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001873#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001874 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001875 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001876#endif
1877
Simon Kelley832af0b2007-01-21 20:01:28 +00001878#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001879 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001880#endif
1881
Floris Bos503c6092017-04-09 23:07:13 +01001882 if (fd != -1)
1883 {
1884 struct {
1885 struct ip ip;
1886 struct icmp icmp;
1887 } packet;
1888 struct sockaddr_in faddr;
1889 socklen_t len = sizeof(faddr);
1890
1891 if (poll_check(fd, POLLIN) &&
1892 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1893 addr == faddr.sin_addr.s_addr &&
1894 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1895 packet.icmp.icmp_seq == 0 &&
1896 packet.icmp.icmp_id == id)
1897 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001898 }
1899 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001900
Floris Bos503c6092017-04-09 23:07:13 +01001901 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001902}
Simon Kelley7622fc02009-06-04 20:32:05 +01001903#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001904
1905