blob: ac5d8aa8253ab6ab40a0f02e4f698b72ed1bcb62 [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
Simon Kelley397c0502018-08-04 21:04:59 +0100219 if (daemon->authserver || daemon->auth_zones)
Simon Kelley4820dce2012-12-18 18:30:30 +0000220 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
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100228#ifndef HAVE_UBUS
229 if (option_bool(OPT_UBUS))
230 die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
231#endif
232
Hans Dedecker926332a2016-01-23 10:48:12 +0000233 if (daemon->max_port < daemon->min_port)
234 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
235
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100236 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000237
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000238 /* Create a serial at startup if not configured. */
Simon Kelley397c0502018-08-04 21:04:59 +0100239 if (daemon->auth_zones && daemon->soa_sn == 0)
Simon Kelley4f7b3042012-11-28 21:27:02 +0000240#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000241 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000242#else
243 daemon->soa_sn = now;
244#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000245
Simon Kelleyff7eea22013-09-04 18:01:38 +0100246#ifdef HAVE_DHCP6
247 if (daemon->dhcp6)
248 {
249 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000250
Simon Kelleyff7eea22013-09-04 18:01:38 +0100251 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000252 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100253 if (context->flags & CONTEXT_DHCP)
254 daemon->doing_dhcp6 = 1;
255 if (context->flags & CONTEXT_RA)
256 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000257#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100258 if (context->flags & CONTEXT_TEMPLATE)
259 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000260#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000261 }
Simon Kelley1f776932012-12-16 19:46:08 +0000262 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100263#endif
264
265#ifdef HAVE_DHCP
266 /* Note that order matters here, we must call lease_init before
267 creating any file descriptors which shouldn't be leaked
268 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000269 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000270 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000271 conditions below. */
272 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000273 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100274 {
275 dhcp_common_init();
276 if (daemon->dhcp || daemon->doing_dhcp6)
277 lease_init(now);
278 }
279
280 if (daemon->dhcp || daemon->relay4)
281 dhcp_init();
282
283# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100284 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100285 ra_init(now);
286
287 if (daemon->doing_dhcp6 || daemon->relay6)
288 dhcp6_init();
289# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000290
Simon Kelley7622fc02009-06-04 20:32:05 +0100291#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100292
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000293#ifdef HAVE_IPSET
294 if (daemon->ipsets)
295 ipset_init();
296#endif
297
Simon Kelley1ee9be42013-12-09 16:50:19 +0000298#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000299 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000300#elif defined(HAVE_BSD_NETWORK)
301 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000302#endif
303
Simon Kelley1ee9be42013-12-09 16:50:19 +0000304 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
305 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
306
Simon Kelley115ac3e2013-05-20 11:28:32 +0100307 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100308 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000309
Simon Kelley54dd3932012-06-20 11:23:38 +0100310 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100311 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100312 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100313
314 if (!option_bool(OPT_CLEVERBIND))
315 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
316 if (if_tmp->name && !if_tmp->used)
317 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100318
319#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
320 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100321 bound_device = whichdevice();
322
Simon Kelley9380ba72012-04-16 14:41:56 +0100323 if (daemon->dhcp)
324 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100325 if (!daemon->relay4 && bound_device)
326 {
327 bindtodevice(bound_device, daemon->dhcpfd);
328 did_bind = 1;
329 }
330 if (daemon->enable_pxe && bound_device)
331 {
332 bindtodevice(bound_device, daemon->pxefd);
333 did_bind = 1;
334 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100335 }
336#endif
337
338#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100339 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
340 {
341 bindtodevice(bound_device, daemon->dhcp6fd);
342 did_bind = 1;
343 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100344#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100345 }
Simon Kelley28866e92011-02-14 20:19:14 +0000346 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100347 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000348
349#ifdef HAVE_DHCP6
350 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100351 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000352 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000353
354 /* After netlink_init() and before create_helper() */
355 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000356#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100357
Simon Kelley824af852008-02-12 20:43:05 +0000358 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000359 {
360 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000361
Simon Kelley82e3f452014-01-31 21:05:48 +0000362#ifdef HAVE_DNSSEC
363 blockdata_init();
364#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000365 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000366
Simon Kelley04918052015-01-26 11:23:43 +0000367#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000368 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
369 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000370 inotify_dnsmasq_init();
371 else
372 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000373#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100374
375 if (daemon->dump_file)
376#ifdef HAVE_DUMPFILE
377 dump_init();
378 else
379 daemon->dumpfd = -1;
380#else
381 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
382#endif
383
Simon Kelley28866e92011-02-14 20:19:14 +0000384 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100385#ifdef HAVE_DBUS
386 {
387 char *err;
388 daemon->dbus = NULL;
389 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100390 if ((err = dbus_init()))
391 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100392 }
393#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100394 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100395#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100396
Simon Kelley824af852008-02-12 20:43:05 +0000397 if (daemon->port != 0)
398 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100399
Simon Kelleyc72daea2012-01-05 21:33:27 +0000400#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100401 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000402 if ((daemon->dhcp || daemon->dhcp6) &&
403 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000404 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100405 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000406 struct passwd *scr_pw;
407
408 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100409 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000410 script_uid = scr_pw->pw_uid;
411 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100412 }
413 else
414 baduser = daemon->scriptuser;
415 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100416#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000417
Simon Kelley1a6bca82008-07-11 11:11:42 +0100418 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
419 baduser = daemon->username;
420 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
421 baduser = daemon->groupname;
422
423 if (baduser)
424 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000425
Simon Kelley1a6bca82008-07-11 11:11:42 +0100426 /* implement group defaults, "dip" if available, or group associated with uid */
427 if (!daemon->group_set && !gp)
428 {
429 if (!(gp = getgrnam(CHGRP)) && ent_pw)
430 gp = getgrgid(ent_pw->pw_gid);
431
432 /* for error message */
433 if (gp)
434 daemon->groupname = gp->gr_name;
435 }
436
437#if defined(HAVE_LINUX_NETWORK)
438 /* determine capability API version here, while we can still
439 call safe_malloc */
440 if (ent_pw && ent_pw->pw_uid != 0)
441 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100442 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100443 hdr = safe_malloc(sizeof(*hdr));
444
Simon Kelley1a6bca82008-07-11 11:11:42 +0100445 /* find version supported by kernel */
446 memset(hdr, 0, sizeof(*hdr));
447 capget(hdr, NULL);
448
449 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
450 {
451 /* if unknown version, use largest supported version (3) */
452 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
453 hdr->version = LINUX_CAPABILITY_VERSION_3;
454 capsize = 2;
455 }
456
457 data = safe_malloc(sizeof(*data) * capsize);
458 memset(data, 0, sizeof(*data) * capsize);
459 }
460#endif
461
Simon Kelley5aabfc72007-08-29 11:24:47 +0100462 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100463 in a race-free manner and another to carry errors to daemon-invoking process */
464 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100465
466 piperead = pipefd[0];
467 pipewrite = pipefd[1];
468 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000469 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100470
471 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100472
Simon Kelley28866e92011-02-14 20:19:14 +0000473 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000474 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000475 /* The following code "daemonizes" the process.
476 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100477
Simon Kelley9e038942008-05-30 20:06:34 +0100478 if (chdir("/") != 0)
479 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
480
Simon Kelley16972692006-10-16 20:04:18 +0100481#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000482 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100483 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100484 pid_t pid;
485
Simon Kelley1a6bca82008-07-11 11:11:42 +0100486 /* pipe to carry errors back to original process.
487 When startup is complete we close this and the process terminates. */
488 safe_pipe(err_pipe, 0);
489
Simon Kelley7622fc02009-06-04 20:32:05 +0100490 if ((pid = fork()) == -1)
491 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000492 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100493
Simon Kelley5aabfc72007-08-29 11:24:47 +0100494 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100495 {
496 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000497 char *msg;
498
Simon Kelley1a6bca82008-07-11 11:11:42 +0100499 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000500 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100501
502 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000503 if (read_event(err_pipe[0], &ev, &msg))
504 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100505
506 _exit(EC_GOOD);
507 }
508
Simon Kelleyff841eb2015-03-11 21:36:30 +0000509 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100510
511 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100512
513 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100514
515 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000516 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100517
518 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100519 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100520 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000521#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100522
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000523 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100524 if (daemon->runfile)
525 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100526 int fd, err = 0;
527
528 sprintf(daemon->namebuff, "%d\n", (int) getpid());
529
530 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
531 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
532 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
533 extent that an attacker running as the unprivileged user could replace the pidfile with a
534 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
535
Josh Soref730c6742017-02-06 16:14:04 +0000536 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100537 ensuring that the open() fails should there be any existing file (because the unlink() failed,
538 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
539 attack can succeed.
540
541 Any compromise of the non-privileged user still theoretically allows the pid-file to be
542 replaced whilst dnsmasq is running. The worst that could allow is that the usual
543 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
544
545 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
546 failure to write the pid-file.
547 */
548
549 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100550
Simon Kelley79cfefd2012-09-02 13:29:51 +0100551 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 +0100552 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100553 /* only complain if started as root */
554 if (getuid() == 0)
555 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100556 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100557 else
558 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000559 /* We're still running as root here. Change the ownership of the PID file
560 to the user we will be running as. Note that this is not to allow
561 us to delete the file, since that depends on the permissions
562 of the directory containing the file. That directory will
563 need to by owned by the dnsmasq user, and the ownership of the
564 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000565 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
566 chown_warn = errno;
567
568 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100569 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000570 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000571 {
572 while (retry_send(close(fd)));
573 if (errno != 0)
574 err = 1;
575 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100576 }
577
578 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100579 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000580 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100581 _exit(0);
582 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000583 }
Simon Kelley16972692006-10-16 20:04:18 +0100584 }
585
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100586 log_err = log_start(ent_pw, err_pipe[1]);
587
Simon Kelley28866e92011-02-14 20:19:14 +0000588 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100589 {
590 /* open stdout etc to /dev/null */
591 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000592 if (nullfd != -1)
593 {
594 dup2(nullfd, STDOUT_FILENO);
595 dup2(nullfd, STDERR_FILENO);
596 dup2(nullfd, STDIN_FILENO);
597 close(nullfd);
598 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100599 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100600
Simon Kelley1a6bca82008-07-11 11:11:42 +0100601 /* if we are to run scripts, we need to fork a helper before dropping root. */
602 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000603#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000604 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000605 (daemon->lease_change_command || daemon->luascript))
606 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100607#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100608
Simon Kelley28866e92011-02-14 20:19:14 +0000609 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100610 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100611 int bad_capabilities = 0;
612 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100613
Josh Soref730c6742017-02-06 16:14:04 +0000614 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100615 if (gp &&
616 (setgroups(0, &dummy) == -1 ||
617 setgid(gp->gr_gid) == -1))
618 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000619 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100620 _exit(0);
621 }
622
Simon Kelley7cebd202006-05-06 14:13:33 +0100623 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100624 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100625#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100626 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100627 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100628 ports because of DAD, or we're doing it dynamically,
629 we need CAP_NET_BIND_SERVICE too. */
630 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100631 data->effective = data->permitted = data->inheritable =
632 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
633 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
634 else
635 data->effective = data->permitted = data->inheritable =
636 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100637
Simon Kelley16972692006-10-16 20:04:18 +0100638 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000639 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100640 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100641
Simon Kelley7622fc02009-06-04 20:32:05 +0100642#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000643 /* http://developers.sun.com/solaris/articles/program_privileges.html */
644 priv_set_t *priv_set;
645
646 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
647 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
648 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
649 bad_capabilities = errno;
650
651 if (priv_set && bad_capabilities == 0)
652 {
653 priv_inverse(priv_set);
654
655 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
656 bad_capabilities = errno;
657 }
658
659 if (priv_set)
660 priv_freeset(priv_set);
661
Simon Kelley824af852008-02-12 20:43:05 +0000662#endif
663
Simon Kelley1a6bca82008-07-11 11:11:42 +0100664 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100665 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000666 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100667 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100668 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100669
670 /* finally drop root */
671 if (setuid(ent_pw->pw_uid) == -1)
672 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000673 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100674 _exit(0);
675 }
676
677#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100678 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100679 data->effective = data->permitted =
680 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
681 else
682 data->effective = data->permitted =
683 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100684 data->inheritable = 0;
685
Josh Soref730c6742017-02-06 16:14:04 +0000686 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100687 if (capset(hdr, data) == -1)
688 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000689 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100690 _exit(0);
691 }
692#endif
693
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000694 }
Simon Kelley849a8352006-06-09 21:02:31 +0100695 }
Simon Kelley16972692006-10-16 20:04:18 +0100696
Simon Kelley16972692006-10-16 20:04:18 +0100697#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000698 free(hdr);
699 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000700 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000701 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100702#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100703
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100704#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100705 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100706 {
707 DIR *dir;
708 struct tftp_prefix *p;
709
710 if (daemon->tftp_prefix)
711 {
712 if (!((dir = opendir(daemon->tftp_prefix))))
713 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100714 tftp_prefix_missing = 1;
715 if (!option_bool(OPT_TFTP_NO_FAIL))
716 {
717 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
718 _exit(0);
719 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100720 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100721 else
722 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100723 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100724
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100725 for (p = daemon->if_prefix; p; p = p->next)
726 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100727 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100728 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100729 {
730 p->missing = 1;
731 if (!option_bool(OPT_TFTP_NO_FAIL))
732 {
733 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
734 _exit(0);
735 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100736 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100737 else
738 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100739 }
740 }
741#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100742
Simon Kelley824af852008-02-12 20:43:05 +0000743 if (daemon->port == 0)
744 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000745 else
746 {
747 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100748 {
749 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
750 if (daemon->cachesize > 10000)
751 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
752 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000753 else
754 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
755
756 if (option_bool(OPT_LOCAL_SERVICE))
757 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
758 }
Simon Kelley16972692006-10-16 20:04:18 +0100759
Simon Kelleyf2621c72007-04-29 19:47:21 +0100760 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000761
762 if (chown_warn != 0)
763 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100764
Simon Kelley3d8df262005-08-29 12:19:27 +0100765#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000766 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100767 {
768 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100769 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100770 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100771 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100772 }
773#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000774
Simon Kelley1d97ac42014-01-31 11:12:27 +0000775#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000776 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000777 {
Simon Kelley360f2512015-03-07 18:28:06 +0000778 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100779 struct ds_config *ds;
780
Simon Kelley360f2512015-03-07 18:28:06 +0000781 /* Delay creating the timestamp file until here, after we've changed user, so that
782 it has the correct owner to allow updating the mtime later.
783 This means we have to report fatal errors via the pipe. */
784 if ((rc = setup_timestamp()) == -1)
785 {
786 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
787 _exit(0);
788 }
789
Simon Kelleya6918532018-04-15 16:20:52 +0100790 if (option_bool(OPT_DNSSEC_IGN_NS))
791 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
792 else
793 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000794
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100795 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
796 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000797 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000798
799 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000800 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100801
802 for (ds = daemon->ds; ds; ds = ds->next)
803 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
804 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000805 }
Simon Kelleydb737462014-01-31 10:32:45 +0000806#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100807
Simon Kelley1a6bca82008-07-11 11:11:42 +0100808 if (log_err != 0)
809 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
810 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000811
Simon Kelleyde379512004-06-22 20:23:33 +0100812 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100813 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100814
Simon Kelleyf7029f52013-11-21 15:09:09 +0000815 if (option_bool(OPT_NOWILD))
816 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000817 else if (!option_bool(OPT_CLEVERBIND))
818 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000819
820 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100821
Simon Kelley28866e92011-02-14 20:19:14 +0000822 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000823 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
824 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100825 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100826
Simon Kelley28866e92011-02-14 20:19:14 +0000827 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100828 {
829 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100830 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100831 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000832 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100833 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100834 }
835
Simon Kelleyf2621c72007-04-29 19:47:21 +0100836 if (daemon->max_logs != 0)
837 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000838
Simon Kelleyf2621c72007-04-29 19:47:21 +0100839
Simon Kelley7622fc02009-06-04 20:32:05 +0100840#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000841 for (context = daemon->dhcp; context; context = context->next)
842 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100843
Simon Kelleyff7eea22013-09-04 18:01:38 +0100844 for (relay = daemon->relay4; relay; relay = relay->next)
845 log_relay(AF_INET, relay);
846
Simon Kelley1f776932012-12-16 19:46:08 +0000847# ifdef HAVE_DHCP6
848 for (context = daemon->dhcp6; context; context = context->next)
849 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000850
Simon Kelleyff7eea22013-09-04 18:01:38 +0100851 for (relay = daemon->relay6; relay; relay = relay->next)
852 log_relay(AF_INET6, relay);
853
Simon Kelley1f776932012-12-16 19:46:08 +0000854 if (daemon->doing_dhcp6 || daemon->doing_ra)
855 dhcp_construct_contexts(now);
856
857 if (option_bool(OPT_RA))
858 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
859# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000860
Simon Kelley3b3f4412013-10-11 16:33:28 +0100861# ifdef HAVE_LINUX_NETWORK
862 if (did_bind)
863 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
864# endif
865
Josh Soref730c6742017-02-06 16:14:04 +0000866 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000867 if (daemon->dhcp || daemon->doing_dhcp6)
868 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000869#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000870
Simon Kelley832af0b2007-01-21 20:01:28 +0000871#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000872 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100873 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100874 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000875
Simon Kelley7622fc02009-06-04 20:32:05 +0100876 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100877 daemon->tftp_prefix ? _("root is ") : _("enabled"),
878 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000879 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100880
Stefan Tomanek30d08792015-03-31 22:32:11 +0100881 if (tftp_prefix_missing)
882 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100883
Stefan Tomanek30d08792015-03-31 22:32:11 +0100884 for (p = daemon->if_prefix; p; p = p->next)
885 if (p->missing)
886 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
887
Simon Kelley832af0b2007-01-21 20:01:28 +0000888 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100889 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000890 a single file will be sent to may clients (the file only needs
891 one fd). */
892
893 max_fd -= 30; /* use other than TFTP */
894
895 if (max_fd < 0)
896 max_fd = 5;
897 else if (max_fd < 100)
898 max_fd = max_fd/2;
899 else
900 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000901
902 /* if we have to use a limited range of ports,
903 that will limit the number of transfers */
904 if (daemon->start_tftp_port != 0 &&
905 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
906 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000907
908 if (daemon->tftp_max > max_fd)
909 {
910 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100911 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100912 _("restricting maximum simultaneous TFTP transfers to %d"),
913 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000914 }
915 }
916#endif
917
Simon Kelley1a6bca82008-07-11 11:11:42 +0100918 /* finished start-up - release original process */
919 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000920 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000921
Simon Kelley824af852008-02-12 20:43:05 +0000922 if (daemon->port != 0)
923 check_servers();
924
Simon Kelley7cebd202006-05-06 14:13:33 +0100925 pid = getpid();
926
Simon Kelley04918052015-01-26 11:23:43 +0000927#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000928 /* Using inotify, have to select a resolv file at startup */
929 poll_resolv(1, 0, now);
930#endif
931
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100932 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000933 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100934 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000935
Simon Kelleyb842bc92015-07-12 21:09:11 +0100936 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000937
Simon Kelley16972692006-10-16 20:04:18 +0100938 /* if we are out of resources, find how long we have to wait
939 for some to come free, we'll loop around then and restart
940 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100941 if ((t = set_dns_listeners(now)) != 0)
942 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100943
Simon Kelley832af0b2007-01-21 20:01:28 +0000944 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
945 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000946 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100947 timeout = 250;
948
Simon Kelley74c95c22011-10-19 09:33:39 +0100949 /* Wake every second whilst waiting for DAD to complete */
950 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100951 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100952
Simon Kelley832af0b2007-01-21 20:01:28 +0000953#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100954 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100955#endif
956
957#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +0100958 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100959 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100960#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100961
Simon Kelley7622fc02009-06-04 20:32:05 +0100962#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100963 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100964 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100965 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000966 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100967 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100968 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100969#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100970
Simon Kelley52b92f42012-01-22 16:05:15 +0000971#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100972 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100973 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100974
Simon Kelley1f776932012-12-16 19:46:08 +0000975 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100976 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000977#endif
Simon Kelley04918052015-01-26 11:23:43 +0000978
979#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000980 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100981 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000982#endif
983
984#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100985 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000986#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100987 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100988#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000989
Simon Kelleyb842bc92015-07-12 21:09:11 +0100990 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100991
Simon Kelley33702ab2015-12-28 23:17:15 +0000992#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000993# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000994 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000995# endif
996
Simon Kelley1e505122016-01-25 21:29:23 +0000997 /* Refresh cache */
998 if (option_bool(OPT_SCRIPT_ARP))
999 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001000 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001001
Simon Kelleya9530962012-03-20 22:07:35 +00001002# ifdef HAVE_TFTP
1003 while (helper_buf_empty() && do_tftp_script_run());
1004# endif
1005
Simon Kelley16972692006-10-16 20:04:18 +01001006 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001007 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001008#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001009 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001010# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001011 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001012# endif
1013
Simon Kelleyb633de92016-01-06 22:51:17 +00001014 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001015
1016# ifdef HAVE_TFTP
1017 while (do_tftp_script_run());
1018# endif
1019
Simon Kelley5aabfc72007-08-29 11:24:47 +01001020#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001021
Simon Kelley7622fc02009-06-04 20:32:05 +01001022
Simon Kelleyf2621c72007-04-29 19:47:21 +01001023 /* must do this just before select(), when we know no
1024 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001025 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001026
Simon Kelleyb842bc92015-07-12 21:09:11 +01001027 if (do_poll(timeout) < 0)
1028 continue;
1029
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001030 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001031
Simon Kelleyb842bc92015-07-12 21:09:11 +01001032 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001033
1034 /* prime. */
1035 enumerate_interfaces(1);
1036
Simon Kelley74c95c22011-10-19 09:33:39 +01001037 /* Check the interfaces to see if any have exited DAD state
1038 and if so, bind the address. */
1039 if (is_dad_listeners())
1040 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001041 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001042 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1043 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001044 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001045 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001046
Simon Kelley1ee9be42013-12-09 16:50:19 +00001047#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001048 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001049 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001050#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001051 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001052 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001053#endif
1054
Simon Kelley04918052015-01-26 11:23:43 +00001055#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001056 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001057 {
1058 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1059 poll_resolv(1, 1, now);
1060 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001061#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001062 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001063 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001064 if (daemon->last_resolv == 0 ||
1065 difftime(now, daemon->last_resolv) > 1.0 ||
1066 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001067 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001068 /* poll_resolv doesn't need to reload first time through, since
1069 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001070
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001071 poll_resolv(0, daemon->last_resolv != 0, now);
1072 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001073 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001074#endif
1075
Simon Kelleyb842bc92015-07-12 21:09:11 +01001076 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001077 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001078
Simon Kelley3d8df262005-08-29 12:19:27 +01001079#ifdef HAVE_DBUS
1080 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001081 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001082 {
1083 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001084 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001085 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001086 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001087 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001088 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001089 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001090#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001091
1092#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001093 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001094 check_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001095#endif
1096
Simon Kelleyb842bc92015-07-12 21:09:11 +01001097 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001098
1099#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001100 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001101#endif
1102
Simon Kelley7622fc02009-06-04 20:32:05 +01001103#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001104 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001105 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001106 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001107 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001108 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001109 dhcp_packet(now, 1);
1110 }
Simon Kelley16972692006-10-16 20:04:18 +01001111
Simon Kelley52b92f42012-01-22 16:05:15 +00001112#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001113 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001114 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001115
Simon Kelleyb842bc92015-07-12 21:09:11 +01001116 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001117 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001118#endif
1119
Simon Kelley1f15b812009-10-13 17:49:32 +01001120# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001121 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001122 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001123# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001124#endif
1125
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001126 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001127}
1128
Simon Kelley3be34542004-09-11 19:12:13 +01001129static void sig_handler(int sig)
1130{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001131 if (pid == 0)
1132 {
Simon Kelley16972692006-10-16 20:04:18 +01001133 /* ignore anything other than TERM during startup
1134 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001135 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001136 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001137 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001138 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001139 {
Simon Kelley16972692006-10-16 20:04:18 +01001140 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001141 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001142 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001143 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001144 else
1145 {
1146 /* master process */
1147 int event, errsave = errno;
1148
1149 if (sig == SIGHUP)
1150 event = EVENT_RELOAD;
1151 else if (sig == SIGCHLD)
1152 event = EVENT_CHILD;
1153 else if (sig == SIGALRM)
1154 event = EVENT_ALARM;
1155 else if (sig == SIGTERM)
1156 event = EVENT_TERM;
1157 else if (sig == SIGUSR1)
1158 event = EVENT_DUMP;
1159 else if (sig == SIGUSR2)
1160 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001161 else if (sig == SIGINT)
1162 {
1163 /* Handle SIGINT normally in debug mode, so
1164 ctrl-c continues to operate. */
1165 if (option_bool(OPT_DEBUG))
1166 exit(EC_MISC);
1167 else
1168 event = EVENT_TIME;
1169 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001170 else
1171 return;
1172
Simon Kelleyc72daea2012-01-05 21:33:27 +00001173 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001174 errno = errsave;
1175 }
Simon Kelley3be34542004-09-11 19:12:13 +01001176}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001177
Simon Kelley353ae4d2012-03-19 20:07:51 +00001178/* now == 0 -> queue immediate callback */
1179void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001180{
Simon Kelley884a6df2012-03-20 16:20:22 +00001181 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001182 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001183 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1184 if ((now == 0 || difftime(event, now) <= 0.0))
1185 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1186 else
1187 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001188 }
Simon Kelley741c2952012-02-25 13:09:18 +00001189}
1190
Simon Kelley47a95162014-07-08 22:22:02 +01001191void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001192{
Simon Kelley47a95162014-07-08 22:22:02 +01001193 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001194}
1195
Simon Kelleyc72daea2012-01-05 21:33:27 +00001196void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001197{
1198 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001199 struct iovec iov[2];
1200
Simon Kelley5aabfc72007-08-29 11:24:47 +01001201 ev.event = event;
1202 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001203 ev.msg_sz = msg ? strlen(msg) : 0;
1204
1205 iov[0].iov_base = &ev;
1206 iov[0].iov_len = sizeof(ev);
1207 iov[1].iov_base = msg;
1208 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001209
1210 /* error pipe, debug mode. */
1211 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001212 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001213 else
1214 /* pipe is non-blocking and struct event_desc is smaller than
1215 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001216 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001217}
Simon Kelley3d8df262005-08-29 12:19:27 +01001218
Simon Kelleyc72daea2012-01-05 21:33:27 +00001219/* NOTE: the memory used to return msg is leaked: use msgs in events only
1220 to describe fatal errors. */
1221static int read_event(int fd, struct event_desc *evp, char **msg)
1222{
1223 char *buf;
1224
1225 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1226 return 0;
1227
1228 *msg = NULL;
1229
1230 if (evp->msg_sz != 0 &&
1231 (buf = malloc(evp->msg_sz + 1)) &&
1232 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1233 {
1234 buf[evp->msg_sz] = 0;
1235 *msg = buf;
1236 }
1237
1238 return 1;
1239}
1240
1241static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001242{
1243 errno = ev->data;
1244
1245 switch (ev->event)
1246 {
1247 case EVENT_DIE:
1248 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001249
1250 case EVENT_FORK_ERR:
1251 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001252
1253 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001254 case EVENT_PIPE_ERR:
1255 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001256
1257 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001258 case EVENT_CAP_ERR:
1259 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1260
Simon Kelleye7a4af82018-02-16 21:27:35 +00001261 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001262 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001263 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001264
Simon Kelleye7a4af82018-02-16 21:27:35 +00001265 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001266 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001267 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001268
1269 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001270 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001271 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001272
Simon Kelleye7a4af82018-02-16 21:27:35 +00001273 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001274 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001275 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001276
1277 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001278 case EVENT_LUA_ERR:
1279 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001280
Simon Kelleye7a4af82018-02-16 21:27:35 +00001281 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001282 case EVENT_TFTP_ERR:
1283 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001284
1285 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001286 case EVENT_TIME_ERR:
1287 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001288 }
1289}
1290
Simon Kelley5aabfc72007-08-29 11:24:47 +01001291static void async_event(int pipe, time_t now)
1292{
1293 pid_t p;
1294 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001295 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001296 char *msg;
1297
1298 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1299 to describe fatal errors. */
1300
1301 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001302 switch (ev.event)
1303 {
1304 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001305 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001306
Simon Kelleye98bd522014-03-28 20:41:23 +00001307 /* fall through */
1308
1309 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001310 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001311
Simon Kelley7b1eae42014-02-20 13:43:28 +00001312 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001313 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001314 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1315 {
1316 reload_servers(daemon->resolv_files->name);
1317 check = 1;
1318 }
1319
1320 if (daemon->servers_file)
1321 {
1322 read_servers_file();
1323 check = 1;
1324 }
1325
1326 if (check)
1327 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001328 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001329
Simon Kelley7622fc02009-06-04 20:32:05 +01001330#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001331 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001332#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001333 break;
1334
1335 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001336 if (daemon->port != 0)
1337 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001338 break;
1339
1340 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001341#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001342 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001343 {
1344 lease_prune(NULL, now);
1345 lease_update_file(now);
1346 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001347#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001348 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001349 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1350 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001351#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001352#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001353 break;
1354
1355 case EVENT_CHILD:
1356 /* See Stevens 5.10 */
1357 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1358 if (p == -1)
1359 {
1360 if (errno != EINTR)
1361 break;
1362 }
1363 else
1364 for (i = 0 ; i < MAX_PROCS; i++)
1365 if (daemon->tcp_pids[i] == p)
1366 daemon->tcp_pids[i] = 0;
1367 break;
1368
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001369#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001370 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001371 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001372 break;
1373
1374 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001375 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001376 break;
1377
1378 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001379 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1380 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001381 break;
1382
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001383 case EVENT_SCRIPT_LOG:
1384 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1385 free(msg);
1386 msg = NULL;
1387 break;
1388
Simon Kelley1a6bca82008-07-11 11:11:42 +01001389 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001390 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001391 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001392 case EVENT_LUA_ERR:
1393 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001394 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001395#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001396
Simon Kelley5aabfc72007-08-29 11:24:47 +01001397 case EVENT_REOPEN:
1398 /* Note: this may leave TCP-handling processes with the old file still open.
1399 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1400 we leave them logging to the old file. */
1401 if (daemon->log_file != NULL)
1402 log_reopen(daemon->log_file);
1403 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001404
1405 case EVENT_NEWADDR:
1406 newaddress(now);
1407 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001408
1409 case EVENT_NEWROUTE:
1410 resend_query();
1411 /* Force re-reading resolv file right now, for luck. */
1412 poll_resolv(0, 1, now);
1413 break;
1414
Simon Kelley3c973ad2018-01-14 21:05:37 +00001415 case EVENT_TIME:
1416#ifdef HAVE_DNSSEC
1417 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1418 {
1419 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1420 daemon->dnssec_no_time_check = 0;
1421 clear_cache_and_reload(now);
1422 }
1423#endif
1424 break;
1425
Simon Kelley5aabfc72007-08-29 11:24:47 +01001426 case EVENT_TERM:
1427 /* Knock all our children on the head. */
1428 for (i = 0; i < MAX_PROCS; i++)
1429 if (daemon->tcp_pids[i] != 0)
1430 kill(daemon->tcp_pids[i], SIGALRM);
1431
Simon Kelley53a91732016-01-06 17:59:13 +00001432#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001433 /* handle pending lease transitions */
1434 if (daemon->helperfd != -1)
1435 {
1436 /* block in writes until all done */
1437 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1438 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1439 do {
1440 helper_write();
1441 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001442 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001443 }
1444#endif
1445
1446 if (daemon->lease_stream)
1447 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001448
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001449#ifdef HAVE_DNSSEC
1450 /* update timestamp file on TERM if time is considered valid */
1451 if (daemon->back_to_the_future)
1452 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001453 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001454 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1455 }
1456#endif
1457
Simon Kelley73a08a22009-02-05 20:28:08 +00001458 if (daemon->runfile)
1459 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001460
1461#ifdef HAVE_DUMPFILE
1462 if (daemon->dumpfd != -1)
1463 close(daemon->dumpfd);
1464#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001465
1466 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1467 flush_log();
1468 exit(EC_GOOD);
1469 }
1470}
1471
Simon Kelley47a95162014-07-08 22:22:02 +01001472static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001473{
1474 struct resolvc *res, *latest;
1475 struct stat statbuf;
1476 time_t last_change = 0;
1477 /* There may be more than one possible file.
1478 Go through and find the one which changed _last_.
1479 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001480
Simon Kelley28866e92011-02-14 20:19:14 +00001481 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001482 return;
1483
Simon Kelley5aabfc72007-08-29 11:24:47 +01001484 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1485 if (stat(res->name, &statbuf) == -1)
1486 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001487 if (force)
1488 {
1489 res->mtime = 0;
1490 continue;
1491 }
1492
Simon Kelley5aabfc72007-08-29 11:24:47 +01001493 if (!res->logged)
1494 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1495 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001496
1497 if (res->mtime != 0)
1498 {
1499 /* existing file evaporated, force selection of the latest
1500 file even if its mtime hasn't changed since we last looked */
1501 poll_resolv(1, do_reload, now);
1502 return;
1503 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001504 }
1505 else
1506 {
1507 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001508 if (force || (statbuf.st_mtime != res->mtime))
1509 {
1510 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001511 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1512 {
1513 last_change = statbuf.st_mtime;
1514 latest = res;
1515 }
1516 }
1517 }
1518
1519 if (latest)
1520 {
1521 static int warned = 0;
1522 if (reload_servers(latest->name))
1523 {
1524 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1525 warned = 0;
1526 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001527 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001528 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001529 }
1530 else
1531 {
1532 latest->mtime = 0;
1533 if (!warned)
1534 {
1535 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1536 warned = 1;
1537 }
1538 }
1539 }
1540}
1541
1542void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001543{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001544 (void)now;
1545
Simon Kelley824af852008-02-12 20:43:05 +00001546 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001547 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001548
Simon Kelley7622fc02009-06-04 20:32:05 +01001549#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001550 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001551 {
Simon Kelley28866e92011-02-14 20:19:14 +00001552 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001553 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001554 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001555 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001556 lease_update_from_configs();
1557 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001558 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001559 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001560#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001561 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001562 /* Not doing DHCP, so no lease system, manage
1563 alarms for ra only */
1564 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001565#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001566#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001567}
1568
Simon Kelleyb842bc92015-07-12 21:09:11 +01001569static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001570{
1571 struct serverfd *serverfdp;
1572 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001573 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001574
1575#ifdef HAVE_TFTP
1576 int tftp = 0;
1577 struct tftp_transfer *transfer;
1578 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1579 {
1580 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001581 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001582 }
1583#endif
1584
Simon Kelley16972692006-10-16 20:04:18 +01001585 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001586 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001587 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001588
Simon Kelley3be34542004-09-11 19:12:13 +01001589 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001590 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001591
Simon Kelley1a6bca82008-07-11 11:11:42 +01001592 if (daemon->port != 0 && !daemon->osport)
1593 for (i = 0; i < RANDOM_SOCKS; i++)
1594 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001595 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001596
Simon Kelley3be34542004-09-11 19:12:13 +01001597 for (listener = daemon->listeners; listener; listener = listener->next)
1598 {
Simon Kelley16972692006-10-16 20:04:18 +01001599 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001600 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001601 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001602
Simon Kelley16972692006-10-16 20:04:18 +01001603 /* death of a child goes through the select loop, so
1604 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001605 if (listener->tcpfd != -1)
1606 for (i = 0; i < MAX_PROCS; i++)
1607 if (daemon->tcp_pids[i] == 0)
1608 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001609 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001610 break;
1611 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001612
Simon Kelley832af0b2007-01-21 20:01:28 +00001613#ifdef HAVE_TFTP
1614 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001615 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001616#endif
1617
1618 }
1619
Simon Kelley16972692006-10-16 20:04:18 +01001620 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001621}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001622
Simon Kelleyb842bc92015-07-12 21:09:11 +01001623static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001624{
1625 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001626 struct listener *listener;
1627 int i;
1628
Simon Kelley832af0b2007-01-21 20:01:28 +00001629 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001630 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001631 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1632
1633 if (daemon->port != 0 && !daemon->osport)
1634 for (i = 0; i < RANDOM_SOCKS; i++)
1635 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001636 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001637 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001638
1639 for (listener = daemon->listeners; listener; listener = listener->next)
1640 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001641 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001642 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001643
Simon Kelley832af0b2007-01-21 20:01:28 +00001644#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001645 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001646 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001647#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001648
Simon Kelleyb842bc92015-07-12 21:09:11 +01001649 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001650 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001651 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001652 struct irec *iface = NULL;
1653 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001654 union mysockaddr tcp_addr;
1655 socklen_t tcp_len = sizeof(union mysockaddr);
1656
1657 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001658
Simon Kelley46b06652013-02-04 21:47:59 +00001659 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001660 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001661
Simon Kelley46b06652013-02-04 21:47:59 +00001662 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1663 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001664 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001665 continue;
1666 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001667
1668 /* Make sure that the interface list is up-to-date.
1669
1670 We do this here as we may need the results below, and
1671 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001672
Simon Kelley76dd75d2013-05-23 10:04:25 +01001673 Multiple calls to enumerate_interfaces() per select loop are
1674 inhibited, so calls to it in the child process (which doesn't select())
1675 have no effect. This avoids two processes reading from the same
1676 netlink fd and screwing the pooch entirely.
1677 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001678
Simon Kelley76dd75d2013-05-23 10:04:25 +01001679 enumerate_interfaces(0);
1680
1681 if (option_bool(OPT_NOWILD))
1682 iface = listener->iface; /* May be NULL */
1683 else
1684 {
1685 int if_index;
1686 char intr_name[IF_NAMESIZE];
1687
1688 /* if we can find the arrival interface, check it's one that's allowed */
1689 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1690 indextoname(listener->tcpfd, if_index, intr_name))
1691 {
1692 struct all_addr addr;
1693 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001694#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001695 if (tcp_addr.sa.sa_family == AF_INET6)
1696 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001697#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001698
1699 for (iface = daemon->interfaces; iface; iface = iface->next)
1700 if (iface->index == if_index)
1701 break;
1702
1703 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1704 client_ok = 0;
1705 }
1706
1707 if (option_bool(OPT_CLEVERBIND))
1708 iface = listener->iface; /* May be NULL */
1709 else
1710 {
1711 /* Check for allowed interfaces when binding the wildcard address:
1712 we do this by looking for an interface with the same address as
1713 the local address of the TCP connection, then looking to see if that's
1714 an allowed interface. As a side effect, we get the netmask of the
1715 interface too, for localisation. */
1716
1717 for (iface = daemon->interfaces; iface; iface = iface->next)
1718 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1719 break;
1720
1721 if (!iface)
1722 client_ok = 0;
1723 }
1724 }
1725
Simon Kelley22ce5502013-01-22 13:53:04 +00001726 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001727 {
1728 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001729 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001730 }
1731#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001732 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001733 {
1734 if (p != -1)
1735 {
1736 int i;
1737 for (i = 0; i < MAX_PROCS; i++)
1738 if (daemon->tcp_pids[i] == 0)
1739 {
1740 daemon->tcp_pids[i] = p;
1741 break;
1742 }
1743 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001744 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001745
1746 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1747 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001748 }
1749#endif
1750 else
1751 {
1752 unsigned char *buff;
1753 struct server *s;
1754 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001755 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001756 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001757
1758 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001759 {
1760 netmask = iface->netmask;
1761 auth_dns = iface->dns_auth;
1762 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001763 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001764 {
1765 netmask.s_addr = 0;
1766 auth_dns = 0;
1767 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001768
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001769#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001770 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001771 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001772 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001773 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001774#endif
1775
Simon Kelley832af0b2007-01-21 20:01:28 +00001776 /* start with no upstream connections. */
1777 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001778 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001779
1780 /* The connected socket inherits non-blocking
1781 attribute from the listening socket.
1782 Reset that here. */
1783 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1784 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1785
Simon Kelley4f7b3042012-11-28 21:27:02 +00001786 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001787
Simon Kelley832af0b2007-01-21 20:01:28 +00001788 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001789 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001790
1791 if (buff)
1792 free(buff);
1793
1794 for (s = daemon->servers; s; s = s->next)
1795 if (s->tcpfd != -1)
1796 {
1797 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001798 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001799 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001800#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001801 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001802 {
1803 flush_log();
1804 _exit(0);
1805 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001806#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001807 }
1808 }
1809 }
Simon Kelley3be34542004-09-11 19:12:13 +01001810}
1811
Simon Kelley7622fc02009-06-04 20:32:05 +01001812#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001813int make_icmp_sock(void)
1814{
Simon Kelley7cebd202006-05-06 14:13:33 +01001815 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001816 int zeroopt = 0;
1817
1818 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1819 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001820 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001821 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1822 {
1823 close(fd);
1824 fd = -1;
1825 }
1826 }
1827
1828 return fd;
1829}
1830
Simon Kelley5aabfc72007-08-29 11:24:47 +01001831int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001832{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001833 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001834
Floris Bos503c6092017-04-09 23:07:13 +01001835 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001836 struct sockaddr_in saddr;
1837 struct {
1838 struct ip ip;
1839 struct icmp icmp;
1840 } packet;
1841 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001842 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001843 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001844
Simon Kelley824af852008-02-12 20:43:05 +00001845#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001846 if ((fd = make_icmp_sock()) == -1)
1847 return 0;
1848#else
1849 int opt = 2000;
1850 fd = daemon->dhcp_icmp_fd;
1851 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1852#endif
1853
Simon Kelley3be34542004-09-11 19:12:13 +01001854 saddr.sin_family = AF_INET;
1855 saddr.sin_port = 0;
1856 saddr.sin_addr = addr;
1857#ifdef HAVE_SOCKADDR_SA_LEN
1858 saddr.sin_len = sizeof(struct sockaddr_in);
1859#endif
1860
1861 memset(&packet.icmp, 0, sizeof(packet.icmp));
1862 packet.icmp.icmp_type = ICMP_ECHO;
1863 packet.icmp.icmp_id = id;
1864 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1865 j += ((u16 *)&packet.icmp)[i];
1866 while (j>>16)
1867 j = (j & 0xffff) + (j >> 16);
1868 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1869
Simon Kelleyff841eb2015-03-11 21:36:30 +00001870 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1871 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001872
Floris Bos503c6092017-04-09 23:07:13 +01001873 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1874
1875#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1876 while (retry_send(close(fd)));
1877#else
1878 opt = 1;
1879 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1880#endif
1881
1882 return gotreply;
1883}
1884
1885int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1886{
1887 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1888 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1889 from "addr" with ICMP ID "id" and return 1 */
1890
1891 /* Note that whilst waiting, we check for
1892 (and service) events on the DNS and TFTP sockets, (so doing that
1893 better not use any resources our caller has in use...)
1894 but we remain deaf to signals or further DHCP packets. */
1895
1896 /* There can be a problem using dnsmasq_time() to end the loop, since
1897 it's not monotonic, and can go backwards if the system clock is
1898 tweaked, leading to the code getting stuck in this loop and
1899 ignoring DHCP requests. To fix this, we check to see if select returned
1900 as a result of a timeout rather than a socket becoming available. We
1901 only allow this to happen as many times as it takes to get to the wait time
1902 in quarter-second chunks. This provides a fallback way to end loop. */
1903
1904 int rc, timeout_count;
1905 time_t now;
1906
1907 for (now = dnsmasq_time(), timeout_count = 0;
1908 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001909 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001910 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001911 if (fd != -1)
1912 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001913 set_dns_listeners(now);
1914 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001915
1916#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001917 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001918 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001919#endif
1920
Simon Kelleyb842bc92015-07-12 21:09:11 +01001921 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001922
1923 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001924 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001925 else if (rc == 0)
1926 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001927
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001928 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001929
Simon Kelleyb842bc92015-07-12 21:09:11 +01001930 check_log_writer(0);
1931 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001932
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001933#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001934 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001935 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001936#endif
1937
Simon Kelley832af0b2007-01-21 20:01:28 +00001938#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001939 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001940#endif
1941
Floris Bos503c6092017-04-09 23:07:13 +01001942 if (fd != -1)
1943 {
1944 struct {
1945 struct ip ip;
1946 struct icmp icmp;
1947 } packet;
1948 struct sockaddr_in faddr;
1949 socklen_t len = sizeof(faddr);
1950
1951 if (poll_check(fd, POLLIN) &&
1952 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1953 addr == faddr.sin_addr.s_addr &&
1954 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1955 packet.icmp.icmp_seq == 0 &&
1956 packet.icmp.icmp_id == id)
1957 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001958 }
1959 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001960
Floris Bos503c6092017-04-09 23:07:13 +01001961 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001962}
Simon Kelley7622fc02009-06-04 20:32:05 +01001963#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001964
1965