blob: ff2c7f2da94c0671e06be738a74db38006d6bc12 [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelleyc72daea2012-01-05 21:33:27 +000017/* Declare static char *compiler_opts in config.h */
18#define DNSMASQ_COMPILE_OPTS
19
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020#include "dnsmasq.h"
21
Simon Kelley5aabfc72007-08-29 11:24:47 +010022struct daemon *daemon;
23
Simon Kelley5aabfc72007-08-29 11:24:47 +010024static volatile pid_t pid = 0;
25static volatile int pipewrite;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000026
Simon Kelleyb842bc92015-07-12 21:09:11 +010027static int set_dns_listeners(time_t now);
28static void check_dns_listeners(time_t now);
Simon Kelley3be34542004-09-11 19:12:13 +010029static void sig_handler(int sig);
Simon Kelley5aabfc72007-08-29 11:24:47 +010030static void async_event(int pipe, time_t now);
Simon Kelleyc72daea2012-01-05 21:33:27 +000031static void fatal_event(struct event_desc *ev, char *msg);
32static int read_event(int fd, struct event_desc *evp, char **msg);
Simon Kelley47a95162014-07-08 22:22:02 +010033static void poll_resolv(int force, int do_reload, time_t now);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000034
35int main (int argc, char **argv)
36{
Simon Kelleyde379512004-06-22 20:23:33 +010037 int bind_fallback = 0;
Simon Kelley9009d742008-11-14 20:04:27 +000038 time_t now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000039 struct sigaction sigact;
Simon Kelley26128d22004-11-14 16:43:54 +000040 struct iname *if_tmp;
Simon Kelley1a6bca82008-07-11 11:11:42 +010041 int piperead, pipefd[2], err_pipe[2];
42 struct passwd *ent_pw = NULL;
Simon Kelleyc72daea2012-01-05 21:33:27 +000043#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +010044 uid_t script_uid = 0;
45 gid_t script_gid = 0;
Simon Kelley7622fc02009-06-04 20:32:05 +010046#endif
47 struct group *gp = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +010048 long i, max_fd = sysconf(_SC_OPEN_MAX);
Simon Kelley1a6bca82008-07-11 11:11:42 +010049 char *baduser = NULL;
50 int log_err;
Simon Kelley6b54d692018-02-08 21:23:05 +000051 int chown_warn = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010052#if defined(HAVE_LINUX_NETWORK)
53 cap_user_header_t hdr = NULL;
54 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010055 char *bound_device = NULL;
56 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010057#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010058#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000059 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010060 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010061#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010062#ifdef HAVE_TFTP
63 int tftp_prefix_missing = 0;
64#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010065
Simon Kelley824af852008-02-12 20:43:05 +000066#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000067 setlocale(LC_ALL, "");
68 bindtextdomain("dnsmasq", LOCALEDIR);
69 textdomain("dnsmasq");
70#endif
71
Simon Kelley9e4abcb2004-01-22 19:47:41 +000072 sigact.sa_handler = sig_handler;
73 sigact.sa_flags = 0;
74 sigemptyset(&sigact.sa_mask);
75 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010076 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000077 sigaction(SIGHUP, &sigact, NULL);
78 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000079 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010080 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000081 sigaction(SIGINT, &sigact, NULL);
82
Simon Kelleyfeba5c12004-07-27 20:28:58 +010083 /* ignore SIGPIPE */
84 sigact.sa_handler = SIG_IGN;
85 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000086
Simon Kelley5aabfc72007-08-29 11:24:47 +010087 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010088
89 rand_init(); /* Must precede read_opts() */
90
Simon Kelley5aabfc72007-08-29 11:24:47 +010091 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000092
Simon Kelley3be34542004-09-11 19:12:13 +010093 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000094 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000095
Simon Kelleyd3a8b392015-12-23 12:27:37 +000096 /* Min buffer size: we check after adding each record, so there must be
97 memory for the largest packet, and the largest record so the
98 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
99 This might be increased is EDNS packet size if greater than the minimum. */
100 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000101 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000102
Simon Kelleyc72daea2012-01-05 21:33:27 +0000103 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000104 if (option_bool(OPT_EXTRALOG))
105 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000106
107#ifdef HAVE_DNSSEC
108 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000109 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100110 /* Note that both /000 and '.' are allowed within labels. These get
111 represented in presentation format using NAME_ESCAPE as an escape
112 character when in DNSSEC mode.
113 In theory, if all the characters in a name were /000 or
114 '.' or NAME_ESCAPE then all would have to be escaped, so the
115 presentation format would be twice as long as the spec.
116
117 daemon->namebuff was previously allocated by the option-reading
118 code before we knew if we're in DNSSEC mode, so reallocate here. */
119 free(daemon->namebuff);
120 daemon->namebuff = safe_malloc(MAXDNAME * 2);
121 daemon->keyname = safe_malloc(MAXDNAME * 2);
122 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000123 /* one char flag per possible RR in answer section (may get extended). */
124 daemon->rr_status_sz = 64;
125 daemon->rr_status = safe_malloc(daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000126 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000127#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000128
Simon Kelley7622fc02009-06-04 20:32:05 +0100129#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100130 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000131 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000132 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100133 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000134 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100135#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000136
Simon Kelleya2761752012-01-18 16:07:21 +0000137 /* Close any file descriptors we inherited apart from std{in|out|err}
138
139 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
140 otherwise file descriptors we create can end up being 0, 1, or 2
141 and then get accidentally closed later when we make 0, 1, and 2
142 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
143 but it's not guaranteed. By opening /dev/null three times, we
144 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100145 for (i = 0; i < max_fd; i++)
146 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
147 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000148 else
149 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100150
Simon Kelley801ca9a2012-03-06 19:30:17 +0000151#ifndef HAVE_LINUX_NETWORK
152# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000153 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100154 {
155 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000156 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100157 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000158# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100159
160 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100161 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100162 {
163 bind_fallback = 1;
164 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100165 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100166 }
Simon Kelley04918052015-01-26 11:23:43 +0000167#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000168
Simon Kelley04918052015-01-26 11:23:43 +0000169#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000170 if (daemon->dynamic_dirs)
171 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100172#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100173
Simon Kelley0744ca62014-01-25 16:40:15 +0000174 if (option_bool(OPT_DNSSEC_VALID))
175 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000176#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000177 struct ds_config *ds;
178
179 /* Must have at least a root trust anchor, or the DNSSEC code
180 can loop forever. */
181 for (ds = daemon->ds; ds; ds = ds->next)
182 if (ds->name[0] == 0)
183 break;
184
185 if (!ds)
186 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000187
188 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000189 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000190#else
191 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000192#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000193 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000194
Simon Kelley832af0b2007-01-21 20:01:28 +0000195#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100196 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100197 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000198#endif
199
Simon Kelley7de060b2011-08-26 17:24:52 +0100200#ifdef HAVE_CONNTRACK
201 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000202 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100203#else
204 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000205 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100206#endif
207
Simon Kelley824af852008-02-12 20:43:05 +0000208#ifdef HAVE_SOLARIS_NETWORK
209 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000210 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000211#endif
212
Simon Kelley572b41e2011-02-18 18:11:18 +0000213#ifdef __ANDROID__
214 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000215 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000216#endif
217
Simon Kelley4820dce2012-12-18 18:30:30 +0000218#ifndef HAVE_AUTH
219 if (daemon->authserver)
220 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
221#endif
222
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100223#ifndef HAVE_LOOP
224 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000225 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100226#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000227
Hans Dedecker926332a2016-01-23 10:48:12 +0000228 if (daemon->max_port < daemon->min_port)
229 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
230
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100231 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000232
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000233 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000234 if (daemon->authinterface && daemon->soa_sn == 0)
235#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000236 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000237#else
238 daemon->soa_sn = now;
239#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000240
Simon Kelleyff7eea22013-09-04 18:01:38 +0100241#ifdef HAVE_DHCP6
242 if (daemon->dhcp6)
243 {
244 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000245
Simon Kelleyff7eea22013-09-04 18:01:38 +0100246 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000247 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100248 if (context->flags & CONTEXT_DHCP)
249 daemon->doing_dhcp6 = 1;
250 if (context->flags & CONTEXT_RA)
251 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000252#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100253 if (context->flags & CONTEXT_TEMPLATE)
254 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000255#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000256 }
Simon Kelley1f776932012-12-16 19:46:08 +0000257 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100258#endif
259
260#ifdef HAVE_DHCP
261 /* Note that order matters here, we must call lease_init before
262 creating any file descriptors which shouldn't be leaked
263 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000264 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000265 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000266 conditions below. */
267 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000268 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100269 {
270 dhcp_common_init();
271 if (daemon->dhcp || daemon->doing_dhcp6)
272 lease_init(now);
273 }
274
275 if (daemon->dhcp || daemon->relay4)
276 dhcp_init();
277
278# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100279 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100280 ra_init(now);
281
282 if (daemon->doing_dhcp6 || daemon->relay6)
283 dhcp6_init();
284# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000285
Simon Kelley7622fc02009-06-04 20:32:05 +0100286#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100287
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000288#ifdef HAVE_IPSET
289 if (daemon->ipsets)
290 ipset_init();
291#endif
292
Simon Kelley1ee9be42013-12-09 16:50:19 +0000293#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000294 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000295#elif defined(HAVE_BSD_NETWORK)
296 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000297#endif
298
Simon Kelley1ee9be42013-12-09 16:50:19 +0000299 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
300 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
301
Simon Kelley115ac3e2013-05-20 11:28:32 +0100302 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100303 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000304
Simon Kelley54dd3932012-06-20 11:23:38 +0100305 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100306 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100307 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100308
309 if (!option_bool(OPT_CLEVERBIND))
310 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
311 if (if_tmp->name && !if_tmp->used)
312 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100313
314#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
315 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100316 bound_device = whichdevice();
317
Simon Kelley9380ba72012-04-16 14:41:56 +0100318 if (daemon->dhcp)
319 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100320 if (!daemon->relay4 && bound_device)
321 {
322 bindtodevice(bound_device, daemon->dhcpfd);
323 did_bind = 1;
324 }
325 if (daemon->enable_pxe && bound_device)
326 {
327 bindtodevice(bound_device, daemon->pxefd);
328 did_bind = 1;
329 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100330 }
331#endif
332
333#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100334 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
335 {
336 bindtodevice(bound_device, daemon->dhcp6fd);
337 did_bind = 1;
338 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100339#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100340 }
Simon Kelley28866e92011-02-14 20:19:14 +0000341 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100342 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000343
344#ifdef HAVE_DHCP6
345 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100346 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000347 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000348
349 /* After netlink_init() and before create_helper() */
350 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000351#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100352
Simon Kelley824af852008-02-12 20:43:05 +0000353 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000354 {
355 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000356
Simon Kelley82e3f452014-01-31 21:05:48 +0000357#ifdef HAVE_DNSSEC
358 blockdata_init();
359#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000360 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000361
Simon Kelley04918052015-01-26 11:23:43 +0000362#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000363 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
364 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000365 inotify_dnsmasq_init();
366 else
367 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000368#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100369
370 if (daemon->dump_file)
371#ifdef HAVE_DUMPFILE
372 dump_init();
373 else
374 daemon->dumpfd = -1;
375#else
376 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
377#endif
378
Simon Kelley28866e92011-02-14 20:19:14 +0000379 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100380#ifdef HAVE_DBUS
381 {
382 char *err;
383 daemon->dbus = NULL;
384 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100385 if ((err = dbus_init()))
386 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100387 }
388#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100389 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100390#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100391
Simon Kelley824af852008-02-12 20:43:05 +0000392 if (daemon->port != 0)
393 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100394
Simon Kelleyc72daea2012-01-05 21:33:27 +0000395#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100396 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000397 if ((daemon->dhcp || daemon->dhcp6) &&
398 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000399 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100400 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000401 struct passwd *scr_pw;
402
403 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100404 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000405 script_uid = scr_pw->pw_uid;
406 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100407 }
408 else
409 baduser = daemon->scriptuser;
410 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100411#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000412
Simon Kelley1a6bca82008-07-11 11:11:42 +0100413 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
414 baduser = daemon->username;
415 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
416 baduser = daemon->groupname;
417
418 if (baduser)
419 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000420
Simon Kelley1a6bca82008-07-11 11:11:42 +0100421 /* implement group defaults, "dip" if available, or group associated with uid */
422 if (!daemon->group_set && !gp)
423 {
424 if (!(gp = getgrnam(CHGRP)) && ent_pw)
425 gp = getgrgid(ent_pw->pw_gid);
426
427 /* for error message */
428 if (gp)
429 daemon->groupname = gp->gr_name;
430 }
431
432#if defined(HAVE_LINUX_NETWORK)
433 /* determine capability API version here, while we can still
434 call safe_malloc */
435 if (ent_pw && ent_pw->pw_uid != 0)
436 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100437 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100438 hdr = safe_malloc(sizeof(*hdr));
439
Simon Kelley1a6bca82008-07-11 11:11:42 +0100440 /* find version supported by kernel */
441 memset(hdr, 0, sizeof(*hdr));
442 capget(hdr, NULL);
443
444 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
445 {
446 /* if unknown version, use largest supported version (3) */
447 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
448 hdr->version = LINUX_CAPABILITY_VERSION_3;
449 capsize = 2;
450 }
451
452 data = safe_malloc(sizeof(*data) * capsize);
453 memset(data, 0, sizeof(*data) * capsize);
454 }
455#endif
456
Simon Kelley5aabfc72007-08-29 11:24:47 +0100457 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100458 in a race-free manner and another to carry errors to daemon-invoking process */
459 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100460
461 piperead = pipefd[0];
462 pipewrite = pipefd[1];
463 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000464 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100465
466 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100467
Simon Kelley28866e92011-02-14 20:19:14 +0000468 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000469 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000470 /* The following code "daemonizes" the process.
471 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100472
Simon Kelley9e038942008-05-30 20:06:34 +0100473 if (chdir("/") != 0)
474 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
475
Simon Kelley16972692006-10-16 20:04:18 +0100476#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000477 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100478 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100479 pid_t pid;
480
Simon Kelley1a6bca82008-07-11 11:11:42 +0100481 /* pipe to carry errors back to original process.
482 When startup is complete we close this and the process terminates. */
483 safe_pipe(err_pipe, 0);
484
Simon Kelley7622fc02009-06-04 20:32:05 +0100485 if ((pid = fork()) == -1)
486 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000487 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100488
Simon Kelley5aabfc72007-08-29 11:24:47 +0100489 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100490 {
491 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000492 char *msg;
493
Simon Kelley1a6bca82008-07-11 11:11:42 +0100494 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000495 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100496
497 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000498 if (read_event(err_pipe[0], &ev, &msg))
499 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100500
501 _exit(EC_GOOD);
502 }
503
Simon Kelleyff841eb2015-03-11 21:36:30 +0000504 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100505
506 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100507
508 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100509
510 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000511 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100512
513 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100514 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100515 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000516#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100517
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000518 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100519 if (daemon->runfile)
520 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100521 int fd, err = 0;
522
523 sprintf(daemon->namebuff, "%d\n", (int) getpid());
524
525 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
526 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
527 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
528 extent that an attacker running as the unprivileged user could replace the pidfile with a
529 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
530
Josh Soref730c6742017-02-06 16:14:04 +0000531 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100532 ensuring that the open() fails should there be any existing file (because the unlink() failed,
533 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
534 attack can succeed.
535
536 Any compromise of the non-privileged user still theoretically allows the pid-file to be
537 replaced whilst dnsmasq is running. The worst that could allow is that the usual
538 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
539
540 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
541 failure to write the pid-file.
542 */
543
544 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100545
Simon Kelley79cfefd2012-09-02 13:29:51 +0100546 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 +0100547 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100548 /* only complain if started as root */
549 if (getuid() == 0)
550 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100551 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100552 else
553 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000554 /* We're still running as root here. Change the ownership of the PID file
555 to the user we will be running as. Note that this is not to allow
556 us to delete the file, since that depends on the permissions
557 of the directory containing the file. That directory will
558 need to by owned by the dnsmasq user, and the ownership of the
559 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000560 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
561 chown_warn = errno;
562
563 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100564 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000565 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000566 {
567 while (retry_send(close(fd)));
568 if (errno != 0)
569 err = 1;
570 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100571 }
572
573 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100574 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000575 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100576 _exit(0);
577 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000578 }
Simon Kelley16972692006-10-16 20:04:18 +0100579 }
580
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100581 log_err = log_start(ent_pw, err_pipe[1]);
582
Simon Kelley28866e92011-02-14 20:19:14 +0000583 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100584 {
585 /* open stdout etc to /dev/null */
586 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000587 if (nullfd != -1)
588 {
589 dup2(nullfd, STDOUT_FILENO);
590 dup2(nullfd, STDERR_FILENO);
591 dup2(nullfd, STDIN_FILENO);
592 close(nullfd);
593 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100594 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100595
Simon Kelley1a6bca82008-07-11 11:11:42 +0100596 /* if we are to run scripts, we need to fork a helper before dropping root. */
597 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000598#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000599 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000600 (daemon->lease_change_command || daemon->luascript))
601 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100602#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100603
Simon Kelley28866e92011-02-14 20:19:14 +0000604 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100605 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100606 int bad_capabilities = 0;
607 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100608
Josh Soref730c6742017-02-06 16:14:04 +0000609 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100610 if (gp &&
611 (setgroups(0, &dummy) == -1 ||
612 setgid(gp->gr_gid) == -1))
613 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000614 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100615 _exit(0);
616 }
617
Simon Kelley7cebd202006-05-06 14:13:33 +0100618 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100619 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100620#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100621 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100622 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100623 ports because of DAD, or we're doing it dynamically,
624 we need CAP_NET_BIND_SERVICE too. */
625 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100626 data->effective = data->permitted = data->inheritable =
627 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
628 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
629 else
630 data->effective = data->permitted = data->inheritable =
631 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100632
Simon Kelley16972692006-10-16 20:04:18 +0100633 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000634 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100635 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100636
Simon Kelley7622fc02009-06-04 20:32:05 +0100637#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000638 /* http://developers.sun.com/solaris/articles/program_privileges.html */
639 priv_set_t *priv_set;
640
641 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
642 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
643 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
644 bad_capabilities = errno;
645
646 if (priv_set && bad_capabilities == 0)
647 {
648 priv_inverse(priv_set);
649
650 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
651 bad_capabilities = errno;
652 }
653
654 if (priv_set)
655 priv_freeset(priv_set);
656
Simon Kelley824af852008-02-12 20:43:05 +0000657#endif
658
Simon Kelley1a6bca82008-07-11 11:11:42 +0100659 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100660 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000661 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100662 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100663 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100664
665 /* finally drop root */
666 if (setuid(ent_pw->pw_uid) == -1)
667 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000668 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100669 _exit(0);
670 }
671
672#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100673 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100674 data->effective = data->permitted =
675 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
676 else
677 data->effective = data->permitted =
678 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100679 data->inheritable = 0;
680
Josh Soref730c6742017-02-06 16:14:04 +0000681 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100682 if (capset(hdr, data) == -1)
683 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000684 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100685 _exit(0);
686 }
687#endif
688
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000689 }
Simon Kelley849a8352006-06-09 21:02:31 +0100690 }
Simon Kelley16972692006-10-16 20:04:18 +0100691
Simon Kelley16972692006-10-16 20:04:18 +0100692#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000693 free(hdr);
694 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000695 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000696 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100697#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100698
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100699#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100700 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100701 {
702 DIR *dir;
703 struct tftp_prefix *p;
704
705 if (daemon->tftp_prefix)
706 {
707 if (!((dir = opendir(daemon->tftp_prefix))))
708 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100709 tftp_prefix_missing = 1;
710 if (!option_bool(OPT_TFTP_NO_FAIL))
711 {
712 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
713 _exit(0);
714 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100715 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100716 else
717 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100718 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100719
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100720 for (p = daemon->if_prefix; p; p = p->next)
721 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100722 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100723 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100724 {
725 p->missing = 1;
726 if (!option_bool(OPT_TFTP_NO_FAIL))
727 {
728 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
729 _exit(0);
730 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100731 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100732 else
733 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100734 }
735 }
736#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100737
Simon Kelley824af852008-02-12 20:43:05 +0000738 if (daemon->port == 0)
739 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000740 else
741 {
742 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100743 {
744 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
745 if (daemon->cachesize > 10000)
746 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
747 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000748 else
749 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
750
751 if (option_bool(OPT_LOCAL_SERVICE))
752 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
753 }
Simon Kelley16972692006-10-16 20:04:18 +0100754
Simon Kelleyf2621c72007-04-29 19:47:21 +0100755 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000756
757 if (chown_warn != 0)
758 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100759
Simon Kelley3d8df262005-08-29 12:19:27 +0100760#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000761 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100762 {
763 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100764 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100765 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100766 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100767 }
768#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000769
Simon Kelley1d97ac42014-01-31 11:12:27 +0000770#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000771 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000772 {
Simon Kelley360f2512015-03-07 18:28:06 +0000773 int rc;
774
775 /* Delay creating the timestamp file until here, after we've changed user, so that
776 it has the correct owner to allow updating the mtime later.
777 This means we have to report fatal errors via the pipe. */
778 if ((rc = setup_timestamp()) == -1)
779 {
780 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
781 _exit(0);
782 }
783
Simon Kelleya6918532018-04-15 16:20:52 +0100784 if (option_bool(OPT_DNSSEC_IGN_NS))
785 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
786 else
787 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000788
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100789 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
790 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000791 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000792
793 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000794 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000795 }
Simon Kelleydb737462014-01-31 10:32:45 +0000796#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100797
Simon Kelley1a6bca82008-07-11 11:11:42 +0100798 if (log_err != 0)
799 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
800 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000801
Simon Kelleyde379512004-06-22 20:23:33 +0100802 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100803 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100804
Simon Kelleyf7029f52013-11-21 15:09:09 +0000805 if (option_bool(OPT_NOWILD))
806 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000807 else if (!option_bool(OPT_CLEVERBIND))
808 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000809
810 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100811
Simon Kelley28866e92011-02-14 20:19:14 +0000812 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000813 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
814 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100815 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100816
Simon Kelley28866e92011-02-14 20:19:14 +0000817 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100818 {
819 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100820 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100821 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000822 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100823 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100824 }
825
Simon Kelleyf2621c72007-04-29 19:47:21 +0100826 if (daemon->max_logs != 0)
827 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000828
Simon Kelleyf2621c72007-04-29 19:47:21 +0100829
Simon Kelley7622fc02009-06-04 20:32:05 +0100830#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000831 for (context = daemon->dhcp; context; context = context->next)
832 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100833
Simon Kelleyff7eea22013-09-04 18:01:38 +0100834 for (relay = daemon->relay4; relay; relay = relay->next)
835 log_relay(AF_INET, relay);
836
Simon Kelley1f776932012-12-16 19:46:08 +0000837# ifdef HAVE_DHCP6
838 for (context = daemon->dhcp6; context; context = context->next)
839 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000840
Simon Kelleyff7eea22013-09-04 18:01:38 +0100841 for (relay = daemon->relay6; relay; relay = relay->next)
842 log_relay(AF_INET6, relay);
843
Simon Kelley1f776932012-12-16 19:46:08 +0000844 if (daemon->doing_dhcp6 || daemon->doing_ra)
845 dhcp_construct_contexts(now);
846
847 if (option_bool(OPT_RA))
848 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
849# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000850
Simon Kelley3b3f4412013-10-11 16:33:28 +0100851# ifdef HAVE_LINUX_NETWORK
852 if (did_bind)
853 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
854# endif
855
Josh Soref730c6742017-02-06 16:14:04 +0000856 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000857 if (daemon->dhcp || daemon->doing_dhcp6)
858 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000859#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000860
Simon Kelley832af0b2007-01-21 20:01:28 +0000861#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000862 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100863 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100864 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000865
Simon Kelley7622fc02009-06-04 20:32:05 +0100866 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100867 daemon->tftp_prefix ? _("root is ") : _("enabled"),
868 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000869 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100870
Stefan Tomanek30d08792015-03-31 22:32:11 +0100871 if (tftp_prefix_missing)
872 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100873
Stefan Tomanek30d08792015-03-31 22:32:11 +0100874 for (p = daemon->if_prefix; p; p = p->next)
875 if (p->missing)
876 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
877
Simon Kelley832af0b2007-01-21 20:01:28 +0000878 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100879 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000880 a single file will be sent to may clients (the file only needs
881 one fd). */
882
883 max_fd -= 30; /* use other than TFTP */
884
885 if (max_fd < 0)
886 max_fd = 5;
887 else if (max_fd < 100)
888 max_fd = max_fd/2;
889 else
890 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000891
892 /* if we have to use a limited range of ports,
893 that will limit the number of transfers */
894 if (daemon->start_tftp_port != 0 &&
895 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
896 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000897
898 if (daemon->tftp_max > max_fd)
899 {
900 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100901 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100902 _("restricting maximum simultaneous TFTP transfers to %d"),
903 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000904 }
905 }
906#endif
907
Simon Kelley1a6bca82008-07-11 11:11:42 +0100908 /* finished start-up - release original process */
909 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000910 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000911
Simon Kelley824af852008-02-12 20:43:05 +0000912 if (daemon->port != 0)
913 check_servers();
914
Simon Kelley7cebd202006-05-06 14:13:33 +0100915 pid = getpid();
916
Simon Kelley04918052015-01-26 11:23:43 +0000917#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000918 /* Using inotify, have to select a resolv file at startup */
919 poll_resolv(1, 0, now);
920#endif
921
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100922 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000923 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100924 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000925
Simon Kelleyb842bc92015-07-12 21:09:11 +0100926 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000927
Simon Kelley16972692006-10-16 20:04:18 +0100928 /* if we are out of resources, find how long we have to wait
929 for some to come free, we'll loop around then and restart
930 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100931 if ((t = set_dns_listeners(now)) != 0)
932 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100933
Simon Kelley832af0b2007-01-21 20:01:28 +0000934 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
935 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000936 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100937 timeout = 250;
938
Simon Kelley74c95c22011-10-19 09:33:39 +0100939 /* Wake every second whilst waiting for DAD to complete */
940 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100941 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100942
Simon Kelley832af0b2007-01-21 20:01:28 +0000943#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100944 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100945#endif
946
Simon Kelley7622fc02009-06-04 20:32:05 +0100947#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100948 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100949 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100950 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000951 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100952 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100953 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100954#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100955
Simon Kelley52b92f42012-01-22 16:05:15 +0000956#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100957 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100958 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100959
Simon Kelley1f776932012-12-16 19:46:08 +0000960 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100961 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000962#endif
Simon Kelley04918052015-01-26 11:23:43 +0000963
964#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000965 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100966 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000967#endif
968
969#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100970 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000971#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100972 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100973#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000974
Simon Kelleyb842bc92015-07-12 21:09:11 +0100975 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100976
Simon Kelley33702ab2015-12-28 23:17:15 +0000977#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000978# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000979 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000980# endif
981
Simon Kelley1e505122016-01-25 21:29:23 +0000982 /* Refresh cache */
983 if (option_bool(OPT_SCRIPT_ARP))
984 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +0000985 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +0100986
Simon Kelleya9530962012-03-20 22:07:35 +0000987# ifdef HAVE_TFTP
988 while (helper_buf_empty() && do_tftp_script_run());
989# endif
990
Simon Kelley16972692006-10-16 20:04:18 +0100991 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100992 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +0000993#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100994 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +0000995# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100996 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000997# endif
998
Simon Kelleyb633de92016-01-06 22:51:17 +0000999 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001000
1001# ifdef HAVE_TFTP
1002 while (do_tftp_script_run());
1003# endif
1004
Simon Kelley5aabfc72007-08-29 11:24:47 +01001005#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001006
Simon Kelley7622fc02009-06-04 20:32:05 +01001007
Simon Kelleyf2621c72007-04-29 19:47:21 +01001008 /* must do this just before select(), when we know no
1009 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001010 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001011
Simon Kelleyb842bc92015-07-12 21:09:11 +01001012 if (do_poll(timeout) < 0)
1013 continue;
1014
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001015 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001016
Simon Kelleyb842bc92015-07-12 21:09:11 +01001017 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001018
1019 /* prime. */
1020 enumerate_interfaces(1);
1021
Simon Kelley74c95c22011-10-19 09:33:39 +01001022 /* Check the interfaces to see if any have exited DAD state
1023 and if so, bind the address. */
1024 if (is_dad_listeners())
1025 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001026 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001027 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1028 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001029 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001030 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001031
Simon Kelley1ee9be42013-12-09 16:50:19 +00001032#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001033 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001034 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001035#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001036 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001037 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001038#endif
1039
Simon Kelley04918052015-01-26 11:23:43 +00001040#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001041 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001042 {
1043 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1044 poll_resolv(1, 1, now);
1045 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001046#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001047 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001048 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001049 if (daemon->last_resolv == 0 ||
1050 difftime(now, daemon->last_resolv) > 1.0 ||
1051 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001052 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001053 /* poll_resolv doesn't need to reload first time through, since
1054 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001055
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001056 poll_resolv(0, daemon->last_resolv != 0, now);
1057 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001058 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001059#endif
1060
Simon Kelleyb842bc92015-07-12 21:09:11 +01001061 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001062 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001063
Simon Kelley3d8df262005-08-29 12:19:27 +01001064#ifdef HAVE_DBUS
1065 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001066 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001067 {
1068 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001069 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001070 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001071 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001072 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001073 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001074 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001075#endif
Simon Kelley824af852008-02-12 20:43:05 +00001076
Simon Kelleyb842bc92015-07-12 21:09:11 +01001077 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001078
1079#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001080 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001081#endif
1082
Simon Kelley7622fc02009-06-04 20:32:05 +01001083#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001084 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001085 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001086 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001087 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001088 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001089 dhcp_packet(now, 1);
1090 }
Simon Kelley16972692006-10-16 20:04:18 +01001091
Simon Kelley52b92f42012-01-22 16:05:15 +00001092#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001093 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001094 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001095
Simon Kelleyb842bc92015-07-12 21:09:11 +01001096 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001097 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001098#endif
1099
Simon Kelley1f15b812009-10-13 17:49:32 +01001100# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001101 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001102 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001103# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001104#endif
1105
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001106 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001107}
1108
Simon Kelley3be34542004-09-11 19:12:13 +01001109static void sig_handler(int sig)
1110{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001111 if (pid == 0)
1112 {
Simon Kelley16972692006-10-16 20:04:18 +01001113 /* ignore anything other than TERM during startup
1114 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001115 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001116 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001117 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001118 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001119 {
Simon Kelley16972692006-10-16 20:04:18 +01001120 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001121 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001122 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001123 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001124 else
1125 {
1126 /* master process */
1127 int event, errsave = errno;
1128
1129 if (sig == SIGHUP)
1130 event = EVENT_RELOAD;
1131 else if (sig == SIGCHLD)
1132 event = EVENT_CHILD;
1133 else if (sig == SIGALRM)
1134 event = EVENT_ALARM;
1135 else if (sig == SIGTERM)
1136 event = EVENT_TERM;
1137 else if (sig == SIGUSR1)
1138 event = EVENT_DUMP;
1139 else if (sig == SIGUSR2)
1140 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001141 else if (sig == SIGINT)
1142 {
1143 /* Handle SIGINT normally in debug mode, so
1144 ctrl-c continues to operate. */
1145 if (option_bool(OPT_DEBUG))
1146 exit(EC_MISC);
1147 else
1148 event = EVENT_TIME;
1149 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001150 else
1151 return;
1152
Simon Kelleyc72daea2012-01-05 21:33:27 +00001153 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001154 errno = errsave;
1155 }
Simon Kelley3be34542004-09-11 19:12:13 +01001156}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001157
Simon Kelley353ae4d2012-03-19 20:07:51 +00001158/* now == 0 -> queue immediate callback */
1159void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001160{
Simon Kelley884a6df2012-03-20 16:20:22 +00001161 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001162 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001163 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1164 if ((now == 0 || difftime(event, now) <= 0.0))
1165 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1166 else
1167 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001168 }
Simon Kelley741c2952012-02-25 13:09:18 +00001169}
1170
Simon Kelley47a95162014-07-08 22:22:02 +01001171void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001172{
Simon Kelley47a95162014-07-08 22:22:02 +01001173 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001174}
1175
Simon Kelleyc72daea2012-01-05 21:33:27 +00001176void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001177{
1178 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001179 struct iovec iov[2];
1180
Simon Kelley5aabfc72007-08-29 11:24:47 +01001181 ev.event = event;
1182 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001183 ev.msg_sz = msg ? strlen(msg) : 0;
1184
1185 iov[0].iov_base = &ev;
1186 iov[0].iov_len = sizeof(ev);
1187 iov[1].iov_base = msg;
1188 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001189
1190 /* error pipe, debug mode. */
1191 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001192 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001193 else
1194 /* pipe is non-blocking and struct event_desc is smaller than
1195 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001196 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001197}
Simon Kelley3d8df262005-08-29 12:19:27 +01001198
Simon Kelleyc72daea2012-01-05 21:33:27 +00001199/* NOTE: the memory used to return msg is leaked: use msgs in events only
1200 to describe fatal errors. */
1201static int read_event(int fd, struct event_desc *evp, char **msg)
1202{
1203 char *buf;
1204
1205 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1206 return 0;
1207
1208 *msg = NULL;
1209
1210 if (evp->msg_sz != 0 &&
1211 (buf = malloc(evp->msg_sz + 1)) &&
1212 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1213 {
1214 buf[evp->msg_sz] = 0;
1215 *msg = buf;
1216 }
1217
1218 return 1;
1219}
1220
1221static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001222{
1223 errno = ev->data;
1224
1225 switch (ev->event)
1226 {
1227 case EVENT_DIE:
1228 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001229
1230 case EVENT_FORK_ERR:
1231 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001232
1233 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001234 case EVENT_PIPE_ERR:
1235 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001236
1237 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001238 case EVENT_CAP_ERR:
1239 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1240
Simon Kelleye7a4af82018-02-16 21:27:35 +00001241 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001242 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001243 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001244
Simon Kelleye7a4af82018-02-16 21:27:35 +00001245 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001246 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001247 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001248
1249 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001250 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001251 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001252
Simon Kelleye7a4af82018-02-16 21:27:35 +00001253 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001254 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001255 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001256
1257 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001258 case EVENT_LUA_ERR:
1259 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001260
Simon Kelleye7a4af82018-02-16 21:27:35 +00001261 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001262 case EVENT_TFTP_ERR:
1263 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001264
1265 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001266 case EVENT_TIME_ERR:
1267 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001268 }
1269}
1270
Simon Kelley5aabfc72007-08-29 11:24:47 +01001271static void async_event(int pipe, time_t now)
1272{
1273 pid_t p;
1274 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001275 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001276 char *msg;
1277
1278 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1279 to describe fatal errors. */
1280
1281 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001282 switch (ev.event)
1283 {
1284 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001285 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001286
Simon Kelleye98bd522014-03-28 20:41:23 +00001287 /* fall through */
1288
1289 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001290 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001291
Simon Kelley7b1eae42014-02-20 13:43:28 +00001292 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001293 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001294 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1295 {
1296 reload_servers(daemon->resolv_files->name);
1297 check = 1;
1298 }
1299
1300 if (daemon->servers_file)
1301 {
1302 read_servers_file();
1303 check = 1;
1304 }
1305
1306 if (check)
1307 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001308 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001309
Simon Kelley7622fc02009-06-04 20:32:05 +01001310#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001311 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001312#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001313 break;
1314
1315 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001316 if (daemon->port != 0)
1317 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001318 break;
1319
1320 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001321#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001322 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001323 {
1324 lease_prune(NULL, now);
1325 lease_update_file(now);
1326 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001327#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001328 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001329 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1330 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001331#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001332#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001333 break;
1334
1335 case EVENT_CHILD:
1336 /* See Stevens 5.10 */
1337 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1338 if (p == -1)
1339 {
1340 if (errno != EINTR)
1341 break;
1342 }
1343 else
1344 for (i = 0 ; i < MAX_PROCS; i++)
1345 if (daemon->tcp_pids[i] == p)
1346 daemon->tcp_pids[i] = 0;
1347 break;
1348
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001349#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001350 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001351 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001352 break;
1353
1354 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001355 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001356 break;
1357
1358 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001359 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1360 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001361 break;
1362
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001363 case EVENT_SCRIPT_LOG:
1364 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1365 free(msg);
1366 msg = NULL;
1367 break;
1368
Simon Kelley1a6bca82008-07-11 11:11:42 +01001369 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001370 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001371 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001372 case EVENT_LUA_ERR:
1373 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001374 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001375#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001376
Simon Kelley5aabfc72007-08-29 11:24:47 +01001377 case EVENT_REOPEN:
1378 /* Note: this may leave TCP-handling processes with the old file still open.
1379 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1380 we leave them logging to the old file. */
1381 if (daemon->log_file != NULL)
1382 log_reopen(daemon->log_file);
1383 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001384
1385 case EVENT_NEWADDR:
1386 newaddress(now);
1387 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001388
1389 case EVENT_NEWROUTE:
1390 resend_query();
1391 /* Force re-reading resolv file right now, for luck. */
1392 poll_resolv(0, 1, now);
1393 break;
1394
Simon Kelley3c973ad2018-01-14 21:05:37 +00001395 case EVENT_TIME:
1396#ifdef HAVE_DNSSEC
1397 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1398 {
1399 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1400 daemon->dnssec_no_time_check = 0;
1401 clear_cache_and_reload(now);
1402 }
1403#endif
1404 break;
1405
Simon Kelley5aabfc72007-08-29 11:24:47 +01001406 case EVENT_TERM:
1407 /* Knock all our children on the head. */
1408 for (i = 0; i < MAX_PROCS; i++)
1409 if (daemon->tcp_pids[i] != 0)
1410 kill(daemon->tcp_pids[i], SIGALRM);
1411
Simon Kelley53a91732016-01-06 17:59:13 +00001412#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001413 /* handle pending lease transitions */
1414 if (daemon->helperfd != -1)
1415 {
1416 /* block in writes until all done */
1417 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1418 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1419 do {
1420 helper_write();
1421 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001422 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001423 }
1424#endif
1425
1426 if (daemon->lease_stream)
1427 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001428
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001429#ifdef HAVE_DNSSEC
1430 /* update timestamp file on TERM if time is considered valid */
1431 if (daemon->back_to_the_future)
1432 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001433 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001434 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1435 }
1436#endif
1437
Simon Kelley73a08a22009-02-05 20:28:08 +00001438 if (daemon->runfile)
1439 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001440
1441#ifdef HAVE_DUMPFILE
1442 if (daemon->dumpfd != -1)
1443 close(daemon->dumpfd);
1444#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001445
1446 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1447 flush_log();
1448 exit(EC_GOOD);
1449 }
1450}
1451
Simon Kelley47a95162014-07-08 22:22:02 +01001452static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001453{
1454 struct resolvc *res, *latest;
1455 struct stat statbuf;
1456 time_t last_change = 0;
1457 /* There may be more than one possible file.
1458 Go through and find the one which changed _last_.
1459 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001460
Simon Kelley28866e92011-02-14 20:19:14 +00001461 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001462 return;
1463
Simon Kelley5aabfc72007-08-29 11:24:47 +01001464 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1465 if (stat(res->name, &statbuf) == -1)
1466 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001467 if (force)
1468 {
1469 res->mtime = 0;
1470 continue;
1471 }
1472
Simon Kelley5aabfc72007-08-29 11:24:47 +01001473 if (!res->logged)
1474 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1475 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001476
1477 if (res->mtime != 0)
1478 {
1479 /* existing file evaporated, force selection of the latest
1480 file even if its mtime hasn't changed since we last looked */
1481 poll_resolv(1, do_reload, now);
1482 return;
1483 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001484 }
1485 else
1486 {
1487 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001488 if (force || (statbuf.st_mtime != res->mtime))
1489 {
1490 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001491 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1492 {
1493 last_change = statbuf.st_mtime;
1494 latest = res;
1495 }
1496 }
1497 }
1498
1499 if (latest)
1500 {
1501 static int warned = 0;
1502 if (reload_servers(latest->name))
1503 {
1504 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1505 warned = 0;
1506 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001507 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001508 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001509 }
1510 else
1511 {
1512 latest->mtime = 0;
1513 if (!warned)
1514 {
1515 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1516 warned = 1;
1517 }
1518 }
1519 }
1520}
1521
1522void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001523{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001524 (void)now;
1525
Simon Kelley824af852008-02-12 20:43:05 +00001526 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001527 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001528
Simon Kelley7622fc02009-06-04 20:32:05 +01001529#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001530 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001531 {
Simon Kelley28866e92011-02-14 20:19:14 +00001532 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001533 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001534 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001535 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001536 lease_update_from_configs();
1537 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001538 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001539 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001540#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001541 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001542 /* Not doing DHCP, so no lease system, manage
1543 alarms for ra only */
1544 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001545#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001546#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001547}
1548
Simon Kelleyb842bc92015-07-12 21:09:11 +01001549static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001550{
1551 struct serverfd *serverfdp;
1552 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001553 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001554
1555#ifdef HAVE_TFTP
1556 int tftp = 0;
1557 struct tftp_transfer *transfer;
1558 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1559 {
1560 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001561 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001562 }
1563#endif
1564
Simon Kelley16972692006-10-16 20:04:18 +01001565 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001566 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001567 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001568
Simon Kelley3be34542004-09-11 19:12:13 +01001569 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001570 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001571
Simon Kelley1a6bca82008-07-11 11:11:42 +01001572 if (daemon->port != 0 && !daemon->osport)
1573 for (i = 0; i < RANDOM_SOCKS; i++)
1574 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001575 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001576
Simon Kelley3be34542004-09-11 19:12:13 +01001577 for (listener = daemon->listeners; listener; listener = listener->next)
1578 {
Simon Kelley16972692006-10-16 20:04:18 +01001579 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001580 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001581 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001582
Simon Kelley16972692006-10-16 20:04:18 +01001583 /* death of a child goes through the select loop, so
1584 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001585 if (listener->tcpfd != -1)
1586 for (i = 0; i < MAX_PROCS; i++)
1587 if (daemon->tcp_pids[i] == 0)
1588 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001589 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001590 break;
1591 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001592
Simon Kelley832af0b2007-01-21 20:01:28 +00001593#ifdef HAVE_TFTP
1594 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001595 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001596#endif
1597
1598 }
1599
Simon Kelley16972692006-10-16 20:04:18 +01001600 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001601}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001602
Simon Kelleyb842bc92015-07-12 21:09:11 +01001603static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001604{
1605 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001606 struct listener *listener;
1607 int i;
1608
Simon Kelley832af0b2007-01-21 20:01:28 +00001609 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001610 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001611 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1612
1613 if (daemon->port != 0 && !daemon->osport)
1614 for (i = 0; i < RANDOM_SOCKS; i++)
1615 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001616 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001617 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001618
1619 for (listener = daemon->listeners; listener; listener = listener->next)
1620 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001621 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001622 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001623
Simon Kelley832af0b2007-01-21 20:01:28 +00001624#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001625 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001626 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001627#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001628
Simon Kelleyb842bc92015-07-12 21:09:11 +01001629 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001630 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001631 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001632 struct irec *iface = NULL;
1633 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001634 union mysockaddr tcp_addr;
1635 socklen_t tcp_len = sizeof(union mysockaddr);
1636
1637 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001638
Simon Kelley46b06652013-02-04 21:47:59 +00001639 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001640 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001641
Simon Kelley46b06652013-02-04 21:47:59 +00001642 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1643 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001644 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001645 continue;
1646 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001647
1648 /* Make sure that the interface list is up-to-date.
1649
1650 We do this here as we may need the results below, and
1651 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001652
Simon Kelley76dd75d2013-05-23 10:04:25 +01001653 Multiple calls to enumerate_interfaces() per select loop are
1654 inhibited, so calls to it in the child process (which doesn't select())
1655 have no effect. This avoids two processes reading from the same
1656 netlink fd and screwing the pooch entirely.
1657 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001658
Simon Kelley76dd75d2013-05-23 10:04:25 +01001659 enumerate_interfaces(0);
1660
1661 if (option_bool(OPT_NOWILD))
1662 iface = listener->iface; /* May be NULL */
1663 else
1664 {
1665 int if_index;
1666 char intr_name[IF_NAMESIZE];
1667
1668 /* if we can find the arrival interface, check it's one that's allowed */
1669 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1670 indextoname(listener->tcpfd, if_index, intr_name))
1671 {
1672 struct all_addr addr;
1673 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001674#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001675 if (tcp_addr.sa.sa_family == AF_INET6)
1676 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001677#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001678
1679 for (iface = daemon->interfaces; iface; iface = iface->next)
1680 if (iface->index == if_index)
1681 break;
1682
1683 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1684 client_ok = 0;
1685 }
1686
1687 if (option_bool(OPT_CLEVERBIND))
1688 iface = listener->iface; /* May be NULL */
1689 else
1690 {
1691 /* Check for allowed interfaces when binding the wildcard address:
1692 we do this by looking for an interface with the same address as
1693 the local address of the TCP connection, then looking to see if that's
1694 an allowed interface. As a side effect, we get the netmask of the
1695 interface too, for localisation. */
1696
1697 for (iface = daemon->interfaces; iface; iface = iface->next)
1698 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1699 break;
1700
1701 if (!iface)
1702 client_ok = 0;
1703 }
1704 }
1705
Simon Kelley22ce5502013-01-22 13:53:04 +00001706 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001707 {
1708 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001709 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001710 }
1711#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001712 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001713 {
1714 if (p != -1)
1715 {
1716 int i;
1717 for (i = 0; i < MAX_PROCS; i++)
1718 if (daemon->tcp_pids[i] == 0)
1719 {
1720 daemon->tcp_pids[i] = p;
1721 break;
1722 }
1723 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001724 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001725
1726 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1727 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001728 }
1729#endif
1730 else
1731 {
1732 unsigned char *buff;
1733 struct server *s;
1734 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001735 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001736 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001737
1738 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001739 {
1740 netmask = iface->netmask;
1741 auth_dns = iface->dns_auth;
1742 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001743 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001744 {
1745 netmask.s_addr = 0;
1746 auth_dns = 0;
1747 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001748
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001749#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001750 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001751 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001752 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001753 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001754#endif
1755
Simon Kelley832af0b2007-01-21 20:01:28 +00001756 /* start with no upstream connections. */
1757 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001758 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001759
1760 /* The connected socket inherits non-blocking
1761 attribute from the listening socket.
1762 Reset that here. */
1763 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1764 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1765
Simon Kelley4f7b3042012-11-28 21:27:02 +00001766 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001767
Simon Kelley832af0b2007-01-21 20:01:28 +00001768 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001769 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001770
1771 if (buff)
1772 free(buff);
1773
1774 for (s = daemon->servers; s; s = s->next)
1775 if (s->tcpfd != -1)
1776 {
1777 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001778 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001779 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001780#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001781 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001782 {
1783 flush_log();
1784 _exit(0);
1785 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001786#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001787 }
1788 }
1789 }
Simon Kelley3be34542004-09-11 19:12:13 +01001790}
1791
Simon Kelley7622fc02009-06-04 20:32:05 +01001792#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001793int make_icmp_sock(void)
1794{
Simon Kelley7cebd202006-05-06 14:13:33 +01001795 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001796 int zeroopt = 0;
1797
1798 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1799 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001800 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001801 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1802 {
1803 close(fd);
1804 fd = -1;
1805 }
1806 }
1807
1808 return fd;
1809}
1810
Simon Kelley5aabfc72007-08-29 11:24:47 +01001811int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001812{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001813 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001814
Floris Bos503c6092017-04-09 23:07:13 +01001815 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001816 struct sockaddr_in saddr;
1817 struct {
1818 struct ip ip;
1819 struct icmp icmp;
1820 } packet;
1821 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001822 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001823 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001824
Simon Kelley824af852008-02-12 20:43:05 +00001825#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001826 if ((fd = make_icmp_sock()) == -1)
1827 return 0;
1828#else
1829 int opt = 2000;
1830 fd = daemon->dhcp_icmp_fd;
1831 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1832#endif
1833
Simon Kelley3be34542004-09-11 19:12:13 +01001834 saddr.sin_family = AF_INET;
1835 saddr.sin_port = 0;
1836 saddr.sin_addr = addr;
1837#ifdef HAVE_SOCKADDR_SA_LEN
1838 saddr.sin_len = sizeof(struct sockaddr_in);
1839#endif
1840
1841 memset(&packet.icmp, 0, sizeof(packet.icmp));
1842 packet.icmp.icmp_type = ICMP_ECHO;
1843 packet.icmp.icmp_id = id;
1844 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1845 j += ((u16 *)&packet.icmp)[i];
1846 while (j>>16)
1847 j = (j & 0xffff) + (j >> 16);
1848 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1849
Simon Kelleyff841eb2015-03-11 21:36:30 +00001850 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1851 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001852
Floris Bos503c6092017-04-09 23:07:13 +01001853 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1854
1855#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1856 while (retry_send(close(fd)));
1857#else
1858 opt = 1;
1859 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1860#endif
1861
1862 return gotreply;
1863}
1864
1865int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1866{
1867 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1868 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1869 from "addr" with ICMP ID "id" and return 1 */
1870
1871 /* Note that whilst waiting, we check for
1872 (and service) events on the DNS and TFTP sockets, (so doing that
1873 better not use any resources our caller has in use...)
1874 but we remain deaf to signals or further DHCP packets. */
1875
1876 /* There can be a problem using dnsmasq_time() to end the loop, since
1877 it's not monotonic, and can go backwards if the system clock is
1878 tweaked, leading to the code getting stuck in this loop and
1879 ignoring DHCP requests. To fix this, we check to see if select returned
1880 as a result of a timeout rather than a socket becoming available. We
1881 only allow this to happen as many times as it takes to get to the wait time
1882 in quarter-second chunks. This provides a fallback way to end loop. */
1883
1884 int rc, timeout_count;
1885 time_t now;
1886
1887 for (now = dnsmasq_time(), timeout_count = 0;
1888 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001889 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001890 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001891 if (fd != -1)
1892 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001893 set_dns_listeners(now);
1894 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001895
1896#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001897 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001898 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001899#endif
1900
Simon Kelleyb842bc92015-07-12 21:09:11 +01001901 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001902
1903 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001904 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001905 else if (rc == 0)
1906 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001907
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001908 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001909
Simon Kelleyb842bc92015-07-12 21:09:11 +01001910 check_log_writer(0);
1911 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001912
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001913#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001914 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001915 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001916#endif
1917
Simon Kelley832af0b2007-01-21 20:01:28 +00001918#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001919 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001920#endif
1921
Floris Bos503c6092017-04-09 23:07:13 +01001922 if (fd != -1)
1923 {
1924 struct {
1925 struct ip ip;
1926 struct icmp icmp;
1927 } packet;
1928 struct sockaddr_in faddr;
1929 socklen_t len = sizeof(faddr);
1930
1931 if (poll_check(fd, POLLIN) &&
1932 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1933 addr == faddr.sin_addr.s_addr &&
1934 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1935 packet.icmp.icmp_seq == 0 &&
1936 packet.icmp.icmp_id == id)
1937 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001938 }
1939 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001940
Floris Bos503c6092017-04-09 23:07:13 +01001941 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001942}
Simon Kelley7622fc02009-06-04 20:32:05 +01001943#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001944
1945