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