blob: db3ff5a82cdf3191a98489e4d1e014f14bf59454 [file] [log] [blame]
Simon Kelley50ca8552017-06-24 22:36:43 +01001/* dnsmasq is Copyright (c) 2000-2017 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelleyc72daea2012-01-05 21:33:27 +000017/* Declare static char *compiler_opts in config.h */
18#define DNSMASQ_COMPILE_OPTS
19
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020#include "dnsmasq.h"
21
Simon Kelley5aabfc72007-08-29 11:24:47 +010022struct daemon *daemon;
23
Simon Kelley5aabfc72007-08-29 11:24:47 +010024static volatile pid_t pid = 0;
25static volatile int pipewrite;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000026
Simon Kelleyb842bc92015-07-12 21:09:11 +010027static int set_dns_listeners(time_t now);
28static void check_dns_listeners(time_t now);
Simon Kelley3be34542004-09-11 19:12:13 +010029static void sig_handler(int sig);
Simon Kelley5aabfc72007-08-29 11:24:47 +010030static void async_event(int pipe, time_t now);
Simon Kelleyc72daea2012-01-05 21:33:27 +000031static void fatal_event(struct event_desc *ev, char *msg);
32static int read_event(int fd, struct event_desc *evp, char **msg);
Simon Kelley47a95162014-07-08 22:22:02 +010033static void poll_resolv(int force, int do_reload, time_t now);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000034
35int main (int argc, char **argv)
36{
Simon Kelleyde379512004-06-22 20:23:33 +010037 int bind_fallback = 0;
Simon Kelley9009d742008-11-14 20:04:27 +000038 time_t now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000039 struct sigaction sigact;
Simon Kelley26128d22004-11-14 16:43:54 +000040 struct iname *if_tmp;
Simon Kelley1a6bca82008-07-11 11:11:42 +010041 int piperead, pipefd[2], err_pipe[2];
42 struct passwd *ent_pw = NULL;
Simon Kelleyc72daea2012-01-05 21:33:27 +000043#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +010044 uid_t script_uid = 0;
45 gid_t script_gid = 0;
Simon Kelley7622fc02009-06-04 20:32:05 +010046#endif
47 struct group *gp = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +010048 long i, max_fd = sysconf(_SC_OPEN_MAX);
Simon Kelley1a6bca82008-07-11 11:11:42 +010049 char *baduser = NULL;
50 int log_err;
51#if defined(HAVE_LINUX_NETWORK)
52 cap_user_header_t hdr = NULL;
53 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010054 char *bound_device = NULL;
55 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010056#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010057#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000058 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010059 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010060#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010061#ifdef HAVE_TFTP
62 int tftp_prefix_missing = 0;
63#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010064
Simon Kelley824af852008-02-12 20:43:05 +000065#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000066 setlocale(LC_ALL, "");
67 bindtextdomain("dnsmasq", LOCALEDIR);
68 textdomain("dnsmasq");
69#endif
70
Simon Kelley9e4abcb2004-01-22 19:47:41 +000071 sigact.sa_handler = sig_handler;
72 sigact.sa_flags = 0;
73 sigemptyset(&sigact.sa_mask);
74 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010075 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000076 sigaction(SIGHUP, &sigact, NULL);
77 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000078 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010079 sigaction(SIGCHLD, &sigact, NULL);
80
81 /* ignore SIGPIPE */
82 sigact.sa_handler = SIG_IGN;
83 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000084
Simon Kelley5aabfc72007-08-29 11:24:47 +010085 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010086
87 rand_init(); /* Must precede read_opts() */
88
Simon Kelley5aabfc72007-08-29 11:24:47 +010089 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000090
Simon Kelley3be34542004-09-11 19:12:13 +010091 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000092 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000093
Simon Kelleyd3a8b392015-12-23 12:27:37 +000094 /* Min buffer size: we check after adding each record, so there must be
95 memory for the largest packet, and the largest record so the
96 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
97 This might be increased is EDNS packet size if greater than the minimum. */
98 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +000099 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000100
Simon Kelleyc72daea2012-01-05 21:33:27 +0000101 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000102 if (option_bool(OPT_EXTRALOG))
103 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000104
105#ifdef HAVE_DNSSEC
106 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000107 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100108 /* Note that both /000 and '.' are allowed within labels. These get
109 represented in presentation format using NAME_ESCAPE as an escape
110 character when in DNSSEC mode.
111 In theory, if all the characters in a name were /000 or
112 '.' or NAME_ESCAPE then all would have to be escaped, so the
113 presentation format would be twice as long as the spec.
114
115 daemon->namebuff was previously allocated by the option-reading
116 code before we knew if we're in DNSSEC mode, so reallocate here. */
117 free(daemon->namebuff);
118 daemon->namebuff = safe_malloc(MAXDNAME * 2);
119 daemon->keyname = safe_malloc(MAXDNAME * 2);
120 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelleya6004d72017-10-25 17:48:19 +0100121 /* one char flag per possible RR in answer section. */
122 daemon->rr_status = safe_malloc(256);
Simon Kelley5107ace2014-02-23 10:48:32 +0000123 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000124#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000125
Simon Kelley7622fc02009-06-04 20:32:05 +0100126#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100127 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000128 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000129 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100130 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000131 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100132#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000133
Simon Kelleya2761752012-01-18 16:07:21 +0000134 /* Close any file descriptors we inherited apart from std{in|out|err}
135
136 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
137 otherwise file descriptors we create can end up being 0, 1, or 2
138 and then get accidentally closed later when we make 0, 1, and 2
139 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
140 but it's not guaranteed. By opening /dev/null three times, we
141 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100142 for (i = 0; i < max_fd; i++)
143 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
144 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000145 else
146 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100147
Simon Kelley801ca9a2012-03-06 19:30:17 +0000148#ifndef HAVE_LINUX_NETWORK
149# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000150 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100151 {
152 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000153 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100154 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000155# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100156
157 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100158 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100159 {
160 bind_fallback = 1;
161 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100162 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100163 }
Simon Kelley04918052015-01-26 11:23:43 +0000164#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000165
Simon Kelley04918052015-01-26 11:23:43 +0000166#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000167 if (daemon->dynamic_dirs)
168 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100169#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100170
Simon Kelley0744ca62014-01-25 16:40:15 +0000171 if (option_bool(OPT_DNSSEC_VALID))
172 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000173#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000174 struct ds_config *ds;
175
176 /* Must have at least a root trust anchor, or the DNSSEC code
177 can loop forever. */
178 for (ds = daemon->ds; ds; ds = ds->next)
179 if (ds->name[0] == 0)
180 break;
181
182 if (!ds)
183 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000184
185 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000186 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000187#else
188 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000189#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000190 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000191
Simon Kelley832af0b2007-01-21 20:01:28 +0000192#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100193 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100194 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000195#endif
196
Simon Kelley7de060b2011-08-26 17:24:52 +0100197#ifdef HAVE_CONNTRACK
198 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000199 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100200#else
201 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000202 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100203#endif
204
Simon Kelley824af852008-02-12 20:43:05 +0000205#ifdef HAVE_SOLARIS_NETWORK
206 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000207 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000208#endif
209
Simon Kelley572b41e2011-02-18 18:11:18 +0000210#ifdef __ANDROID__
211 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000212 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000213#endif
214
Simon Kelley4820dce2012-12-18 18:30:30 +0000215#ifndef HAVE_AUTH
216 if (daemon->authserver)
217 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
218#endif
219
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100220#ifndef HAVE_LOOP
221 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000222 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100223#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000224
225 if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
226 daemon->min_port = 1024u;
227
228 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 {
392 if ((ent_pw = getpwnam(daemon->scriptuser)))
393 {
394 script_uid = ent_pw->pw_uid;
395 script_gid = ent_pw->pw_gid;
396 }
397 else
398 baduser = daemon->scriptuser;
399 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100400#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000401
Simon Kelley1a6bca82008-07-11 11:11:42 +0100402 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
403 baduser = daemon->username;
404 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
405 baduser = daemon->groupname;
406
407 if (baduser)
408 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000409
Simon Kelley1a6bca82008-07-11 11:11:42 +0100410 /* implement group defaults, "dip" if available, or group associated with uid */
411 if (!daemon->group_set && !gp)
412 {
413 if (!(gp = getgrnam(CHGRP)) && ent_pw)
414 gp = getgrgid(ent_pw->pw_gid);
415
416 /* for error message */
417 if (gp)
418 daemon->groupname = gp->gr_name;
419 }
420
421#if defined(HAVE_LINUX_NETWORK)
422 /* determine capability API version here, while we can still
423 call safe_malloc */
424 if (ent_pw && ent_pw->pw_uid != 0)
425 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100426 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100427 hdr = safe_malloc(sizeof(*hdr));
428
Simon Kelley1a6bca82008-07-11 11:11:42 +0100429 /* find version supported by kernel */
430 memset(hdr, 0, sizeof(*hdr));
431 capget(hdr, NULL);
432
433 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
434 {
435 /* if unknown version, use largest supported version (3) */
436 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
437 hdr->version = LINUX_CAPABILITY_VERSION_3;
438 capsize = 2;
439 }
440
441 data = safe_malloc(sizeof(*data) * capsize);
442 memset(data, 0, sizeof(*data) * capsize);
443 }
444#endif
445
Simon Kelley5aabfc72007-08-29 11:24:47 +0100446 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100447 in a race-free manner and another to carry errors to daemon-invoking process */
448 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100449
450 piperead = pipefd[0];
451 pipewrite = pipefd[1];
452 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000453 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100454
455 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100456
Simon Kelley28866e92011-02-14 20:19:14 +0000457 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000458 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000459 /* The following code "daemonizes" the process.
460 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100461
Simon Kelley9e038942008-05-30 20:06:34 +0100462 if (chdir("/") != 0)
463 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
464
Simon Kelley16972692006-10-16 20:04:18 +0100465#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000466 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100467 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100468 pid_t pid;
469
Simon Kelley1a6bca82008-07-11 11:11:42 +0100470 /* pipe to carry errors back to original process.
471 When startup is complete we close this and the process terminates. */
472 safe_pipe(err_pipe, 0);
473
Simon Kelley7622fc02009-06-04 20:32:05 +0100474 if ((pid = fork()) == -1)
475 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000476 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100477
Simon Kelley5aabfc72007-08-29 11:24:47 +0100478 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100479 {
480 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000481 char *msg;
482
Simon Kelley1a6bca82008-07-11 11:11:42 +0100483 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000484 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100485
486 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000487 if (read_event(err_pipe[0], &ev, &msg))
488 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100489
490 _exit(EC_GOOD);
491 }
492
Simon Kelleyff841eb2015-03-11 21:36:30 +0000493 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100494
495 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100496
497 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100498
499 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000500 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100501
502 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100503 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100504 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000505#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100506
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000507 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100508 if (daemon->runfile)
509 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100510 int fd, err = 0;
511
512 sprintf(daemon->namebuff, "%d\n", (int) getpid());
513
514 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
515 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
516 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
517 extent that an attacker running as the unprivileged user could replace the pidfile with a
518 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
519
Josh Soref730c6742017-02-06 16:14:04 +0000520 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100521 ensuring that the open() fails should there be any existing file (because the unlink() failed,
522 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
523 attack can succeed.
524
525 Any compromise of the non-privileged user still theoretically allows the pid-file to be
526 replaced whilst dnsmasq is running. The worst that could allow is that the usual
527 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
528
529 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
530 failure to write the pid-file.
531 */
532
533 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100534
Simon Kelley79cfefd2012-09-02 13:29:51 +0100535 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 +0100536 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100537 /* only complain if started as root */
538 if (getuid() == 0)
539 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100540 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100541 else
542 {
543 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
544 err = 1;
Simon Kelleyff841eb2015-03-11 21:36:30 +0000545 else
546 {
547 while (retry_send(close(fd)));
548 if (errno != 0)
549 err = 1;
550 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100551 }
552
553 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100554 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000555 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100556 _exit(0);
557 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000558 }
Simon Kelley16972692006-10-16 20:04:18 +0100559 }
560
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100561 log_err = log_start(ent_pw, err_pipe[1]);
562
Simon Kelley28866e92011-02-14 20:19:14 +0000563 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100564 {
565 /* open stdout etc to /dev/null */
566 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000567 if (nullfd != -1)
568 {
569 dup2(nullfd, STDOUT_FILENO);
570 dup2(nullfd, STDERR_FILENO);
571 dup2(nullfd, STDIN_FILENO);
572 close(nullfd);
573 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100574 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100575
Simon Kelley1a6bca82008-07-11 11:11:42 +0100576 /* if we are to run scripts, we need to fork a helper before dropping root. */
577 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000578#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000579 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000580 (daemon->lease_change_command || daemon->luascript))
581 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100582#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100583
Simon Kelley28866e92011-02-14 20:19:14 +0000584 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100585 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100586 int bad_capabilities = 0;
587 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100588
Josh Soref730c6742017-02-06 16:14:04 +0000589 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100590 if (gp &&
591 (setgroups(0, &dummy) == -1 ||
592 setgid(gp->gr_gid) == -1))
593 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000594 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100595 _exit(0);
596 }
597
Simon Kelley7cebd202006-05-06 14:13:33 +0100598 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100599 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100600#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100601 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100602 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100603 ports because of DAD, or we're doing it dynamically,
604 we need CAP_NET_BIND_SERVICE too. */
605 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100606 data->effective = data->permitted = data->inheritable =
607 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
608 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
609 else
610 data->effective = data->permitted = data->inheritable =
611 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100612
Simon Kelley16972692006-10-16 20:04:18 +0100613 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000614 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100615 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100616
Simon Kelley7622fc02009-06-04 20:32:05 +0100617#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000618 /* http://developers.sun.com/solaris/articles/program_privileges.html */
619 priv_set_t *priv_set;
620
621 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
622 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
623 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
624 bad_capabilities = errno;
625
626 if (priv_set && bad_capabilities == 0)
627 {
628 priv_inverse(priv_set);
629
630 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
631 bad_capabilities = errno;
632 }
633
634 if (priv_set)
635 priv_freeset(priv_set);
636
Simon Kelley824af852008-02-12 20:43:05 +0000637#endif
638
Simon Kelley1a6bca82008-07-11 11:11:42 +0100639 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100640 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000641 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100642 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100643 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100644
645 /* finally drop root */
646 if (setuid(ent_pw->pw_uid) == -1)
647 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000648 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100649 _exit(0);
650 }
651
652#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100653 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100654 data->effective = data->permitted =
655 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
656 else
657 data->effective = data->permitted =
658 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100659 data->inheritable = 0;
660
Josh Soref730c6742017-02-06 16:14:04 +0000661 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100662 if (capset(hdr, data) == -1)
663 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000664 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100665 _exit(0);
666 }
667#endif
668
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000669 }
Simon Kelley849a8352006-06-09 21:02:31 +0100670 }
Simon Kelley16972692006-10-16 20:04:18 +0100671
Simon Kelley16972692006-10-16 20:04:18 +0100672#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000673 free(hdr);
674 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000675 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000676 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100677#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100678
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100679#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100680 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100681 {
682 DIR *dir;
683 struct tftp_prefix *p;
684
685 if (daemon->tftp_prefix)
686 {
687 if (!((dir = opendir(daemon->tftp_prefix))))
688 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100689 tftp_prefix_missing = 1;
690 if (!option_bool(OPT_TFTP_NO_FAIL))
691 {
692 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
693 _exit(0);
694 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100695 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100696 else
697 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100698 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100699
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100700 for (p = daemon->if_prefix; p; p = p->next)
701 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100702 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100703 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100704 {
705 p->missing = 1;
706 if (!option_bool(OPT_TFTP_NO_FAIL))
707 {
708 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
709 _exit(0);
710 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100711 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100712 else
713 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100714 }
715 }
716#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100717
Simon Kelley824af852008-02-12 20:43:05 +0000718 if (daemon->port == 0)
719 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000720 else
721 {
722 if (daemon->cachesize != 0)
723 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
724 else
725 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
726
727 if (option_bool(OPT_LOCAL_SERVICE))
728 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
729 }
Simon Kelley16972692006-10-16 20:04:18 +0100730
Simon Kelleyf2621c72007-04-29 19:47:21 +0100731 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley16972692006-10-16 20:04:18 +0100732
Simon Kelley3d8df262005-08-29 12:19:27 +0100733#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000734 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100735 {
736 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100737 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100738 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100739 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100740 }
741#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000742
Simon Kelley1d97ac42014-01-31 11:12:27 +0000743#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000744 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000745 {
Simon Kelley360f2512015-03-07 18:28:06 +0000746 int rc;
747
748 /* Delay creating the timestamp file until here, after we've changed user, so that
749 it has the correct owner to allow updating the mtime later.
750 This means we have to report fatal errors via the pipe. */
751 if ((rc = setup_timestamp()) == -1)
752 {
753 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
754 _exit(0);
755 }
756
Simon Kelleye98bd522014-03-28 20:41:23 +0000757 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000758
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100759 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
760 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelleye98bd522014-03-28 20:41:23 +0000761 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
Simon Kelley360f2512015-03-07 18:28:06 +0000762
763 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000764 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000765 }
Simon Kelleydb737462014-01-31 10:32:45 +0000766#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100767
Simon Kelley1a6bca82008-07-11 11:11:42 +0100768 if (log_err != 0)
769 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
770 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000771
Simon Kelleyde379512004-06-22 20:23:33 +0100772 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100773 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100774
Simon Kelleyf7029f52013-11-21 15:09:09 +0000775 if (option_bool(OPT_NOWILD))
776 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000777 else if (!option_bool(OPT_CLEVERBIND))
778 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000779
780 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100781
Simon Kelley28866e92011-02-14 20:19:14 +0000782 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000783 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
784 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100785 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100786
Simon Kelley28866e92011-02-14 20:19:14 +0000787 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100788 {
789 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100790 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100791 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000792 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100793 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100794 }
795
Simon Kelleyf2621c72007-04-29 19:47:21 +0100796 if (daemon->max_logs != 0)
797 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000798
Simon Kelleyf2621c72007-04-29 19:47:21 +0100799
Simon Kelley7622fc02009-06-04 20:32:05 +0100800#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000801 for (context = daemon->dhcp; context; context = context->next)
802 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100803
Simon Kelleyff7eea22013-09-04 18:01:38 +0100804 for (relay = daemon->relay4; relay; relay = relay->next)
805 log_relay(AF_INET, relay);
806
Simon Kelley1f776932012-12-16 19:46:08 +0000807# ifdef HAVE_DHCP6
808 for (context = daemon->dhcp6; context; context = context->next)
809 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000810
Simon Kelleyff7eea22013-09-04 18:01:38 +0100811 for (relay = daemon->relay6; relay; relay = relay->next)
812 log_relay(AF_INET6, relay);
813
Simon Kelley1f776932012-12-16 19:46:08 +0000814 if (daemon->doing_dhcp6 || daemon->doing_ra)
815 dhcp_construct_contexts(now);
816
817 if (option_bool(OPT_RA))
818 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
819# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000820
Simon Kelley3b3f4412013-10-11 16:33:28 +0100821# ifdef HAVE_LINUX_NETWORK
822 if (did_bind)
823 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
824# endif
825
Josh Soref730c6742017-02-06 16:14:04 +0000826 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000827 if (daemon->dhcp || daemon->doing_dhcp6)
828 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000829#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000830
Simon Kelley832af0b2007-01-21 20:01:28 +0000831#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000832 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100833 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100834 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000835
Simon Kelley7622fc02009-06-04 20:32:05 +0100836 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100837 daemon->tftp_prefix ? _("root is ") : _("enabled"),
838 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000839 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100840
Stefan Tomanek30d08792015-03-31 22:32:11 +0100841 if (tftp_prefix_missing)
842 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100843
Stefan Tomanek30d08792015-03-31 22:32:11 +0100844 for (p = daemon->if_prefix; p; p = p->next)
845 if (p->missing)
846 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
847
Simon Kelley832af0b2007-01-21 20:01:28 +0000848 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100849 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000850 a single file will be sent to may clients (the file only needs
851 one fd). */
852
853 max_fd -= 30; /* use other than TFTP */
854
855 if (max_fd < 0)
856 max_fd = 5;
857 else if (max_fd < 100)
858 max_fd = max_fd/2;
859 else
860 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000861
862 /* if we have to use a limited range of ports,
863 that will limit the number of transfers */
864 if (daemon->start_tftp_port != 0 &&
865 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
866 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000867
868 if (daemon->tftp_max > max_fd)
869 {
870 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100871 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100872 _("restricting maximum simultaneous TFTP transfers to %d"),
873 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000874 }
875 }
876#endif
877
Simon Kelley1a6bca82008-07-11 11:11:42 +0100878 /* finished start-up - release original process */
879 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000880 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000881
Simon Kelley824af852008-02-12 20:43:05 +0000882 if (daemon->port != 0)
883 check_servers();
884
Simon Kelley7cebd202006-05-06 14:13:33 +0100885 pid = getpid();
886
Simon Kelley04918052015-01-26 11:23:43 +0000887#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000888 /* Using inotify, have to select a resolv file at startup */
889 poll_resolv(1, 0, now);
890#endif
891
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100892 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000893 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100894 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000895
Simon Kelleyb842bc92015-07-12 21:09:11 +0100896 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000897
Simon Kelley16972692006-10-16 20:04:18 +0100898 /* if we are out of resources, find how long we have to wait
899 for some to come free, we'll loop around then and restart
900 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100901 if ((t = set_dns_listeners(now)) != 0)
902 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100903
Simon Kelley832af0b2007-01-21 20:01:28 +0000904 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
905 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000906 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100907 timeout = 250;
908
Simon Kelley74c95c22011-10-19 09:33:39 +0100909 /* Wake every second whilst waiting for DAD to complete */
910 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100911 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100912
Simon Kelley832af0b2007-01-21 20:01:28 +0000913#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100914 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100915#endif
916
Simon Kelley7622fc02009-06-04 20:32:05 +0100917#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100918 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100919 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100920 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000921 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100922 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100923 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100924#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100925
Simon Kelley52b92f42012-01-22 16:05:15 +0000926#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100927 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100928 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100929
Simon Kelley1f776932012-12-16 19:46:08 +0000930 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100931 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000932#endif
Simon Kelley04918052015-01-26 11:23:43 +0000933
934#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000935 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100936 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000937#endif
938
939#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100940 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000941#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100942 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100943#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000944
Simon Kelleyb842bc92015-07-12 21:09:11 +0100945 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100946
Simon Kelley33702ab2015-12-28 23:17:15 +0000947#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000948# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000949 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000950# endif
951
Simon Kelley1e505122016-01-25 21:29:23 +0000952 /* Refresh cache */
953 if (option_bool(OPT_SCRIPT_ARP))
954 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +0000955 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +0100956
Simon Kelleya9530962012-03-20 22:07:35 +0000957# ifdef HAVE_TFTP
958 while (helper_buf_empty() && do_tftp_script_run());
959# endif
960
Simon Kelley16972692006-10-16 20:04:18 +0100961 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100962 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +0000963#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100964 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +0000965# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100966 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000967# endif
968
Simon Kelleyb633de92016-01-06 22:51:17 +0000969 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +0000970
971# ifdef HAVE_TFTP
972 while (do_tftp_script_run());
973# endif
974
Simon Kelley5aabfc72007-08-29 11:24:47 +0100975#endif
Simon Kelley33702ab2015-12-28 23:17:15 +0000976
Simon Kelley7622fc02009-06-04 20:32:05 +0100977
Simon Kelleyf2621c72007-04-29 19:47:21 +0100978 /* must do this just before select(), when we know no
979 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100980 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +0100981
Simon Kelleyb842bc92015-07-12 21:09:11 +0100982 if (do_poll(timeout) < 0)
983 continue;
984
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100985 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000986
Simon Kelleyb842bc92015-07-12 21:09:11 +0100987 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100988
989 /* prime. */
990 enumerate_interfaces(1);
991
Simon Kelley74c95c22011-10-19 09:33:39 +0100992 /* Check the interfaces to see if any have exited DAD state
993 and if so, bind the address. */
994 if (is_dad_listeners())
995 {
Simon Kelley115ac3e2013-05-20 11:28:32 +0100996 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +0100997 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
998 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +0100999 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001000 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001001
Simon Kelley1ee9be42013-12-09 16:50:19 +00001002#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001003 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001004 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001005#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001006 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001007 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001008#endif
1009
Simon Kelley04918052015-01-26 11:23:43 +00001010#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001011 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001012 {
1013 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1014 poll_resolv(1, 1, now);
1015 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001016#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001017 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001018 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001019 if (daemon->last_resolv == 0 ||
1020 difftime(now, daemon->last_resolv) > 1.0 ||
1021 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001022 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001023 /* poll_resolv doesn't need to reload first time through, since
1024 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001025
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001026 poll_resolv(0, daemon->last_resolv != 0, now);
1027 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001028 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001029#endif
1030
Simon Kelleyb842bc92015-07-12 21:09:11 +01001031 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001032 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001033
Simon Kelley3d8df262005-08-29 12:19:27 +01001034#ifdef HAVE_DBUS
1035 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001036 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001037 {
1038 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001039 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001040 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001041 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001042 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001043 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001044 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001045#endif
Simon Kelley824af852008-02-12 20:43:05 +00001046
Simon Kelleyb842bc92015-07-12 21:09:11 +01001047 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001048
1049#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001050 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001051#endif
1052
Simon Kelley7622fc02009-06-04 20:32:05 +01001053#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001054 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001055 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001056 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001057 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001058 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001059 dhcp_packet(now, 1);
1060 }
Simon Kelley16972692006-10-16 20:04:18 +01001061
Simon Kelley52b92f42012-01-22 16:05:15 +00001062#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001063 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001064 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001065
Simon Kelleyb842bc92015-07-12 21:09:11 +01001066 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001067 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001068#endif
1069
Simon Kelley1f15b812009-10-13 17:49:32 +01001070# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001071 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001072 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001073# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001074#endif
1075
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001076 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001077}
1078
Simon Kelley3be34542004-09-11 19:12:13 +01001079static void sig_handler(int sig)
1080{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001081 if (pid == 0)
1082 {
Simon Kelley16972692006-10-16 20:04:18 +01001083 /* ignore anything other than TERM during startup
1084 and in helper proc. (helper ignore TERM too) */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001085 if (sig == SIGTERM)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001086 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001087 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001088 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001089 {
Simon Kelley16972692006-10-16 20:04:18 +01001090 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001091 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001092 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001093 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001094 else
1095 {
1096 /* master process */
1097 int event, errsave = errno;
1098
1099 if (sig == SIGHUP)
1100 event = EVENT_RELOAD;
1101 else if (sig == SIGCHLD)
1102 event = EVENT_CHILD;
1103 else if (sig == SIGALRM)
1104 event = EVENT_ALARM;
1105 else if (sig == SIGTERM)
1106 event = EVENT_TERM;
1107 else if (sig == SIGUSR1)
1108 event = EVENT_DUMP;
1109 else if (sig == SIGUSR2)
1110 event = EVENT_REOPEN;
1111 else
1112 return;
1113
Simon Kelleyc72daea2012-01-05 21:33:27 +00001114 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001115 errno = errsave;
1116 }
Simon Kelley3be34542004-09-11 19:12:13 +01001117}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001118
Simon Kelley353ae4d2012-03-19 20:07:51 +00001119/* now == 0 -> queue immediate callback */
1120void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001121{
Simon Kelley884a6df2012-03-20 16:20:22 +00001122 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001123 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001124 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1125 if ((now == 0 || difftime(event, now) <= 0.0))
1126 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1127 else
1128 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001129 }
Simon Kelley741c2952012-02-25 13:09:18 +00001130}
1131
Simon Kelley47a95162014-07-08 22:22:02 +01001132void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001133{
Simon Kelley47a95162014-07-08 22:22:02 +01001134 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001135}
1136
Simon Kelleyc72daea2012-01-05 21:33:27 +00001137void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001138{
1139 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001140 struct iovec iov[2];
1141
Simon Kelley5aabfc72007-08-29 11:24:47 +01001142 ev.event = event;
1143 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001144 ev.msg_sz = msg ? strlen(msg) : 0;
1145
1146 iov[0].iov_base = &ev;
1147 iov[0].iov_len = sizeof(ev);
1148 iov[1].iov_base = msg;
1149 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001150
1151 /* error pipe, debug mode. */
1152 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001153 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001154 else
1155 /* pipe is non-blocking and struct event_desc is smaller than
1156 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001157 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001158}
Simon Kelley3d8df262005-08-29 12:19:27 +01001159
Simon Kelleyc72daea2012-01-05 21:33:27 +00001160/* NOTE: the memory used to return msg is leaked: use msgs in events only
1161 to describe fatal errors. */
1162static int read_event(int fd, struct event_desc *evp, char **msg)
1163{
1164 char *buf;
1165
1166 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1167 return 0;
1168
1169 *msg = NULL;
1170
1171 if (evp->msg_sz != 0 &&
1172 (buf = malloc(evp->msg_sz + 1)) &&
1173 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1174 {
1175 buf[evp->msg_sz] = 0;
1176 *msg = buf;
1177 }
1178
1179 return 1;
1180}
1181
1182static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001183{
1184 errno = ev->data;
1185
1186 switch (ev->event)
1187 {
1188 case EVENT_DIE:
1189 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001190
1191 case EVENT_FORK_ERR:
1192 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001193
1194 case EVENT_PIPE_ERR:
1195 die(_("failed to create helper: %s"), NULL, EC_MISC);
1196
1197 case EVENT_CAP_ERR:
1198 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1199
1200 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001201 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001202
1203 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001204 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001205
1206 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001207 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001208
1209 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001210 die(_("cannot open log %s: %s"), msg, EC_FILE);
1211
1212 case EVENT_LUA_ERR:
1213 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001214
1215 case EVENT_TFTP_ERR:
1216 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelley360f2512015-03-07 18:28:06 +00001217
1218 case EVENT_TIME_ERR:
1219 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001220 }
1221}
1222
Simon Kelley5aabfc72007-08-29 11:24:47 +01001223static void async_event(int pipe, time_t now)
1224{
1225 pid_t p;
1226 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001227 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001228 char *msg;
1229
1230 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1231 to describe fatal errors. */
1232
1233 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001234 switch (ev.event)
1235 {
1236 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001237 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
1238
Simon Kelleye98bd522014-03-28 20:41:23 +00001239#ifdef HAVE_DNSSEC
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +01001240 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
Simon Kelleye98bd522014-03-28 20:41:23 +00001241 {
1242 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +01001243 daemon->dnssec_no_time_check = 0;
Simon Kelleye98bd522014-03-28 20:41:23 +00001244 }
1245#endif
1246 /* fall through */
1247
1248 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001249 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001250
Simon Kelley7b1eae42014-02-20 13:43:28 +00001251 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001252 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001253 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1254 {
1255 reload_servers(daemon->resolv_files->name);
1256 check = 1;
1257 }
1258
1259 if (daemon->servers_file)
1260 {
1261 read_servers_file();
1262 check = 1;
1263 }
1264
1265 if (check)
1266 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001267 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001268
Simon Kelley7622fc02009-06-04 20:32:05 +01001269#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001270 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001271#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001272 break;
1273
1274 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001275 if (daemon->port != 0)
1276 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001277 break;
1278
1279 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001280#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001281 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001282 {
1283 lease_prune(NULL, now);
1284 lease_update_file(now);
1285 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001286#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001287 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001288 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1289 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001290#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001291#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001292 break;
1293
1294 case EVENT_CHILD:
1295 /* See Stevens 5.10 */
1296 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1297 if (p == -1)
1298 {
1299 if (errno != EINTR)
1300 break;
1301 }
1302 else
1303 for (i = 0 ; i < MAX_PROCS; i++)
1304 if (daemon->tcp_pids[i] == p)
1305 daemon->tcp_pids[i] = 0;
1306 break;
1307
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001308#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001309 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001310 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001311 break;
1312
1313 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001314 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001315 break;
1316
1317 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001318 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1319 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001320 break;
1321
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001322 case EVENT_SCRIPT_LOG:
1323 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1324 free(msg);
1325 msg = NULL;
1326 break;
1327
Simon Kelley1a6bca82008-07-11 11:11:42 +01001328 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001329 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001330 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001331 case EVENT_LUA_ERR:
1332 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001333 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001334#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001335
Simon Kelley5aabfc72007-08-29 11:24:47 +01001336 case EVENT_REOPEN:
1337 /* Note: this may leave TCP-handling processes with the old file still open.
1338 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1339 we leave them logging to the old file. */
1340 if (daemon->log_file != NULL)
1341 log_reopen(daemon->log_file);
1342 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001343
1344 case EVENT_NEWADDR:
1345 newaddress(now);
1346 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001347
1348 case EVENT_NEWROUTE:
1349 resend_query();
1350 /* Force re-reading resolv file right now, for luck. */
1351 poll_resolv(0, 1, now);
1352 break;
1353
Simon Kelley5aabfc72007-08-29 11:24:47 +01001354 case EVENT_TERM:
1355 /* Knock all our children on the head. */
1356 for (i = 0; i < MAX_PROCS; i++)
1357 if (daemon->tcp_pids[i] != 0)
1358 kill(daemon->tcp_pids[i], SIGALRM);
1359
Simon Kelley53a91732016-01-06 17:59:13 +00001360#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001361 /* handle pending lease transitions */
1362 if (daemon->helperfd != -1)
1363 {
1364 /* block in writes until all done */
1365 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1366 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1367 do {
1368 helper_write();
1369 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001370 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001371 }
1372#endif
1373
1374 if (daemon->lease_stream)
1375 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001376
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001377#ifdef HAVE_DNSSEC
1378 /* update timestamp file on TERM if time is considered valid */
1379 if (daemon->back_to_the_future)
1380 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001381 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001382 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1383 }
1384#endif
1385
Simon Kelley73a08a22009-02-05 20:28:08 +00001386 if (daemon->runfile)
1387 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001388
1389 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1390 flush_log();
1391 exit(EC_GOOD);
1392 }
1393}
1394
Simon Kelley47a95162014-07-08 22:22:02 +01001395static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001396{
1397 struct resolvc *res, *latest;
1398 struct stat statbuf;
1399 time_t last_change = 0;
1400 /* There may be more than one possible file.
1401 Go through and find the one which changed _last_.
1402 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001403
Simon Kelley28866e92011-02-14 20:19:14 +00001404 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001405 return;
1406
Simon Kelley5aabfc72007-08-29 11:24:47 +01001407 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1408 if (stat(res->name, &statbuf) == -1)
1409 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001410 if (force)
1411 {
1412 res->mtime = 0;
1413 continue;
1414 }
1415
Simon Kelley5aabfc72007-08-29 11:24:47 +01001416 if (!res->logged)
1417 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1418 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001419
1420 if (res->mtime != 0)
1421 {
1422 /* existing file evaporated, force selection of the latest
1423 file even if its mtime hasn't changed since we last looked */
1424 poll_resolv(1, do_reload, now);
1425 return;
1426 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001427 }
1428 else
1429 {
1430 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001431 if (force || (statbuf.st_mtime != res->mtime))
1432 {
1433 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001434 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1435 {
1436 last_change = statbuf.st_mtime;
1437 latest = res;
1438 }
1439 }
1440 }
1441
1442 if (latest)
1443 {
1444 static int warned = 0;
1445 if (reload_servers(latest->name))
1446 {
1447 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1448 warned = 0;
1449 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001450 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001451 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001452 }
1453 else
1454 {
1455 latest->mtime = 0;
1456 if (!warned)
1457 {
1458 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1459 warned = 1;
1460 }
1461 }
1462 }
1463}
1464
1465void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001466{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001467 (void)now;
1468
Simon Kelley824af852008-02-12 20:43:05 +00001469 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001470 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001471
Simon Kelley7622fc02009-06-04 20:32:05 +01001472#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001473 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001474 {
Simon Kelley28866e92011-02-14 20:19:14 +00001475 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001476 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001477 reread_dhcp();
Simon Kelley04918052015-01-26 11:23:43 +00001478#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +00001479 set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001480#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001481 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001482 lease_update_from_configs();
1483 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001484 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001485 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001486#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001487 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001488 /* Not doing DHCP, so no lease system, manage
1489 alarms for ra only */
1490 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001491#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001492#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001493}
1494
Simon Kelleyb842bc92015-07-12 21:09:11 +01001495static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001496{
1497 struct serverfd *serverfdp;
1498 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001499 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001500
1501#ifdef HAVE_TFTP
1502 int tftp = 0;
1503 struct tftp_transfer *transfer;
1504 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1505 {
1506 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001507 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001508 }
1509#endif
1510
Simon Kelley16972692006-10-16 20:04:18 +01001511 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001512 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001513 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001514
Simon Kelley3be34542004-09-11 19:12:13 +01001515 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001516 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001517
Simon Kelley1a6bca82008-07-11 11:11:42 +01001518 if (daemon->port != 0 && !daemon->osport)
1519 for (i = 0; i < RANDOM_SOCKS; i++)
1520 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001521 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001522
Simon Kelley3be34542004-09-11 19:12:13 +01001523 for (listener = daemon->listeners; listener; listener = listener->next)
1524 {
Simon Kelley16972692006-10-16 20:04:18 +01001525 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001526 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001527 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001528
Simon Kelley16972692006-10-16 20:04:18 +01001529 /* death of a child goes through the select loop, so
1530 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001531 if (listener->tcpfd != -1)
1532 for (i = 0; i < MAX_PROCS; i++)
1533 if (daemon->tcp_pids[i] == 0)
1534 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001535 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001536 break;
1537 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001538
Simon Kelley832af0b2007-01-21 20:01:28 +00001539#ifdef HAVE_TFTP
1540 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001541 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001542#endif
1543
1544 }
1545
Simon Kelley16972692006-10-16 20:04:18 +01001546 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001547}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001548
Simon Kelleyb842bc92015-07-12 21:09:11 +01001549static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001550{
1551 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001552 struct listener *listener;
1553 int i;
1554
Simon Kelley832af0b2007-01-21 20:01:28 +00001555 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001556 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001557 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1558
1559 if (daemon->port != 0 && !daemon->osport)
1560 for (i = 0; i < RANDOM_SOCKS; i++)
1561 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001562 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001563 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001564
1565 for (listener = daemon->listeners; listener; listener = listener->next)
1566 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001567 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001568 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001569
Simon Kelley832af0b2007-01-21 20:01:28 +00001570#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001571 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001572 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001573#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001574
Simon Kelleyb842bc92015-07-12 21:09:11 +01001575 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001576 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001577 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001578 struct irec *iface = NULL;
1579 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001580 union mysockaddr tcp_addr;
1581 socklen_t tcp_len = sizeof(union mysockaddr);
1582
1583 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001584
Simon Kelley46b06652013-02-04 21:47:59 +00001585 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001586 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001587
Simon Kelley46b06652013-02-04 21:47:59 +00001588 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1589 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001590 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001591 continue;
1592 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001593
1594 /* Make sure that the interface list is up-to-date.
1595
1596 We do this here as we may need the results below, and
1597 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001598
Simon Kelley76dd75d2013-05-23 10:04:25 +01001599 Multiple calls to enumerate_interfaces() per select loop are
1600 inhibited, so calls to it in the child process (which doesn't select())
1601 have no effect. This avoids two processes reading from the same
1602 netlink fd and screwing the pooch entirely.
1603 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001604
Simon Kelley76dd75d2013-05-23 10:04:25 +01001605 enumerate_interfaces(0);
1606
1607 if (option_bool(OPT_NOWILD))
1608 iface = listener->iface; /* May be NULL */
1609 else
1610 {
1611 int if_index;
1612 char intr_name[IF_NAMESIZE];
1613
1614 /* if we can find the arrival interface, check it's one that's allowed */
1615 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1616 indextoname(listener->tcpfd, if_index, intr_name))
1617 {
1618 struct all_addr addr;
1619 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001620#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001621 if (tcp_addr.sa.sa_family == AF_INET6)
1622 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001623#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001624
1625 for (iface = daemon->interfaces; iface; iface = iface->next)
1626 if (iface->index == if_index)
1627 break;
1628
1629 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1630 client_ok = 0;
1631 }
1632
1633 if (option_bool(OPT_CLEVERBIND))
1634 iface = listener->iface; /* May be NULL */
1635 else
1636 {
1637 /* Check for allowed interfaces when binding the wildcard address:
1638 we do this by looking for an interface with the same address as
1639 the local address of the TCP connection, then looking to see if that's
1640 an allowed interface. As a side effect, we get the netmask of the
1641 interface too, for localisation. */
1642
1643 for (iface = daemon->interfaces; iface; iface = iface->next)
1644 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1645 break;
1646
1647 if (!iface)
1648 client_ok = 0;
1649 }
1650 }
1651
Simon Kelley22ce5502013-01-22 13:53:04 +00001652 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001653 {
1654 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001655 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001656 }
1657#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001658 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001659 {
1660 if (p != -1)
1661 {
1662 int i;
1663 for (i = 0; i < MAX_PROCS; i++)
1664 if (daemon->tcp_pids[i] == 0)
1665 {
1666 daemon->tcp_pids[i] = p;
1667 break;
1668 }
1669 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001670 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001671
1672 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1673 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001674 }
1675#endif
1676 else
1677 {
1678 unsigned char *buff;
1679 struct server *s;
1680 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001681 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001682 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001683
1684 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001685 {
1686 netmask = iface->netmask;
1687 auth_dns = iface->dns_auth;
1688 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001689 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001690 {
1691 netmask.s_addr = 0;
1692 auth_dns = 0;
1693 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001694
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001695#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001696 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001697 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001698 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001699 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001700#endif
1701
Simon Kelley832af0b2007-01-21 20:01:28 +00001702 /* start with no upstream connections. */
1703 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001704 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001705
1706 /* The connected socket inherits non-blocking
1707 attribute from the listening socket.
1708 Reset that here. */
1709 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1710 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1711
Simon Kelley4f7b3042012-11-28 21:27:02 +00001712 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001713
Simon Kelley832af0b2007-01-21 20:01:28 +00001714 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001715 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001716
1717 if (buff)
1718 free(buff);
1719
1720 for (s = daemon->servers; s; s = s->next)
1721 if (s->tcpfd != -1)
1722 {
1723 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001724 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001725 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001726#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001727 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001728 {
1729 flush_log();
1730 _exit(0);
1731 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001732#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001733 }
1734 }
1735 }
Simon Kelley3be34542004-09-11 19:12:13 +01001736}
1737
Simon Kelley7622fc02009-06-04 20:32:05 +01001738#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001739int make_icmp_sock(void)
1740{
Simon Kelley7cebd202006-05-06 14:13:33 +01001741 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001742 int zeroopt = 0;
1743
1744 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1745 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001746 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001747 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1748 {
1749 close(fd);
1750 fd = -1;
1751 }
1752 }
1753
1754 return fd;
1755}
1756
Simon Kelley5aabfc72007-08-29 11:24:47 +01001757int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001758{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001759 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001760
Floris Bos503c6092017-04-09 23:07:13 +01001761 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001762 struct sockaddr_in saddr;
1763 struct {
1764 struct ip ip;
1765 struct icmp icmp;
1766 } packet;
1767 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001768 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001769 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001770
Simon Kelley824af852008-02-12 20:43:05 +00001771#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001772 if ((fd = make_icmp_sock()) == -1)
1773 return 0;
1774#else
1775 int opt = 2000;
1776 fd = daemon->dhcp_icmp_fd;
1777 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1778#endif
1779
Simon Kelley3be34542004-09-11 19:12:13 +01001780 saddr.sin_family = AF_INET;
1781 saddr.sin_port = 0;
1782 saddr.sin_addr = addr;
1783#ifdef HAVE_SOCKADDR_SA_LEN
1784 saddr.sin_len = sizeof(struct sockaddr_in);
1785#endif
1786
1787 memset(&packet.icmp, 0, sizeof(packet.icmp));
1788 packet.icmp.icmp_type = ICMP_ECHO;
1789 packet.icmp.icmp_id = id;
1790 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1791 j += ((u16 *)&packet.icmp)[i];
1792 while (j>>16)
1793 j = (j & 0xffff) + (j >> 16);
1794 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1795
Simon Kelleyff841eb2015-03-11 21:36:30 +00001796 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1797 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001798
Floris Bos503c6092017-04-09 23:07:13 +01001799 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1800
1801#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1802 while (retry_send(close(fd)));
1803#else
1804 opt = 1;
1805 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1806#endif
1807
1808 return gotreply;
1809}
1810
1811int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1812{
1813 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1814 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1815 from "addr" with ICMP ID "id" and return 1 */
1816
1817 /* Note that whilst waiting, we check for
1818 (and service) events on the DNS and TFTP sockets, (so doing that
1819 better not use any resources our caller has in use...)
1820 but we remain deaf to signals or further DHCP packets. */
1821
1822 /* There can be a problem using dnsmasq_time() to end the loop, since
1823 it's not monotonic, and can go backwards if the system clock is
1824 tweaked, leading to the code getting stuck in this loop and
1825 ignoring DHCP requests. To fix this, we check to see if select returned
1826 as a result of a timeout rather than a socket becoming available. We
1827 only allow this to happen as many times as it takes to get to the wait time
1828 in quarter-second chunks. This provides a fallback way to end loop. */
1829
1830 int rc, timeout_count;
1831 time_t now;
1832
1833 for (now = dnsmasq_time(), timeout_count = 0;
1834 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001835 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001836 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001837 if (fd != -1)
1838 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001839 set_dns_listeners(now);
1840 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001841
1842#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001843 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001844 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001845#endif
1846
Simon Kelleyb842bc92015-07-12 21:09:11 +01001847 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001848
1849 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001850 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001851 else if (rc == 0)
1852 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001853
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001854 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001855
Simon Kelleyb842bc92015-07-12 21:09:11 +01001856 check_log_writer(0);
1857 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001858
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001859#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001860 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001861 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001862#endif
1863
Simon Kelley832af0b2007-01-21 20:01:28 +00001864#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001865 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001866#endif
1867
Floris Bos503c6092017-04-09 23:07:13 +01001868 if (fd != -1)
1869 {
1870 struct {
1871 struct ip ip;
1872 struct icmp icmp;
1873 } packet;
1874 struct sockaddr_in faddr;
1875 socklen_t len = sizeof(faddr);
1876
1877 if (poll_check(fd, POLLIN) &&
1878 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1879 addr == faddr.sin_addr.s_addr &&
1880 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1881 packet.icmp.icmp_seq == 0 &&
1882 packet.icmp.icmp_id == id)
1883 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001884 }
1885 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001886
Floris Bos503c6092017-04-09 23:07:13 +01001887 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001888}
Simon Kelley7622fc02009-06-04 20:32:05 +01001889#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001890
1891