blob: 573aac069b75b801ad1ddf5305af5010ca1ab88a [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 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 Kelley305ffb52019-03-16 18:17:17 +000055 int need_cap_net_admin = 0;
56 int need_cap_net_raw = 0;
57 int need_cap_net_bind_service = 0;
Simon Kelley3b3f4412013-10-11 16:33:28 +010058 char *bound_device = NULL;
59 int did_bind = 0;
Simon Kelley90d7c6b2019-09-14 21:13:03 +010060 struct server *serv;
Simon Kelley1a6bca82008-07-11 11:11:42 +010061#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010062#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000063 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010064 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010065#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010066#ifdef HAVE_TFTP
67 int tftp_prefix_missing = 0;
68#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010069
Simon Kelley824af852008-02-12 20:43:05 +000070#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000071 setlocale(LC_ALL, "");
72 bindtextdomain("dnsmasq", LOCALEDIR);
73 textdomain("dnsmasq");
74#endif
75
Simon Kelley9e4abcb2004-01-22 19:47:41 +000076 sigact.sa_handler = sig_handler;
77 sigact.sa_flags = 0;
78 sigemptyset(&sigact.sa_mask);
79 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010080 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000081 sigaction(SIGHUP, &sigact, NULL);
82 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000083 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010084 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000085 sigaction(SIGINT, &sigact, NULL);
86
Simon Kelleyfeba5c12004-07-27 20:28:58 +010087 /* ignore SIGPIPE */
88 sigact.sa_handler = SIG_IGN;
89 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000090
Simon Kelley5aabfc72007-08-29 11:24:47 +010091 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010092
93 rand_init(); /* Must precede read_opts() */
94
Simon Kelley5aabfc72007-08-29 11:24:47 +010095 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000096
Simon Kelley3be34542004-09-11 19:12:13 +010097 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000098 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000099
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000100 /* Min buffer size: we check after adding each record, so there must be
101 memory for the largest packet, and the largest record so the
102 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
103 This might be increased is EDNS packet size if greater than the minimum. */
104 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000105 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000106
Simon Kelleyc72daea2012-01-05 21:33:27 +0000107 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000108 if (option_bool(OPT_EXTRALOG))
109 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000110
111#ifdef HAVE_DNSSEC
112 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000113 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100114 /* Note that both /000 and '.' are allowed within labels. These get
115 represented in presentation format using NAME_ESCAPE as an escape
116 character when in DNSSEC mode.
117 In theory, if all the characters in a name were /000 or
118 '.' or NAME_ESCAPE then all would have to be escaped, so the
119 presentation format would be twice as long as the spec.
120
121 daemon->namebuff was previously allocated by the option-reading
122 code before we knew if we're in DNSSEC mode, so reallocate here. */
123 free(daemon->namebuff);
124 daemon->namebuff = safe_malloc(MAXDNAME * 2);
125 daemon->keyname = safe_malloc(MAXDNAME * 2);
126 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000127 /* one char flag per possible RR in answer section (may get extended). */
128 daemon->rr_status_sz = 64;
Simon Kelleyae7a3b92019-09-03 14:40:47 +0100129 daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000130 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000131#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000132
Simon Kelley7622fc02009-06-04 20:32:05 +0100133#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100134 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000135 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000136 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100137 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000138 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100139#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000140
Simon Kelleya2761752012-01-18 16:07:21 +0000141 /* Close any file descriptors we inherited apart from std{in|out|err}
142
143 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
144 otherwise file descriptors we create can end up being 0, 1, or 2
145 and then get accidentally closed later when we make 0, 1, and 2
146 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
147 but it's not guaranteed. By opening /dev/null three times, we
148 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100149 for (i = 0; i < max_fd; i++)
150 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
151 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000152 else
153 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100154
Simon Kelley801ca9a2012-03-06 19:30:17 +0000155#ifndef HAVE_LINUX_NETWORK
156# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000157 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100158 {
159 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000160 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100161 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000162# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100163
164 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100165 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100166 {
167 bind_fallback = 1;
168 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100169 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100170 }
Simon Kelley04918052015-01-26 11:23:43 +0000171#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000172
Simon Kelley04918052015-01-26 11:23:43 +0000173#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000174 if (daemon->dynamic_dirs)
175 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100176#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100177
Simon Kelley0744ca62014-01-25 16:40:15 +0000178 if (option_bool(OPT_DNSSEC_VALID))
179 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000180#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000181 struct ds_config *ds;
182
183 /* Must have at least a root trust anchor, or the DNSSEC code
184 can loop forever. */
185 for (ds = daemon->ds; ds; ds = ds->next)
186 if (ds->name[0] == 0)
187 break;
188
189 if (!ds)
190 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000191
192 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000193 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000194#else
195 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000196#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000197 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000198
Simon Kelley832af0b2007-01-21 20:01:28 +0000199#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100200 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100201 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000202#endif
203
Simon Kelley7de060b2011-08-26 17:24:52 +0100204#ifdef HAVE_CONNTRACK
205 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000206 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100207#else
208 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000209 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100210#endif
211
Simon Kelley824af852008-02-12 20:43:05 +0000212#ifdef HAVE_SOLARIS_NETWORK
213 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000214 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000215#endif
216
Simon Kelley572b41e2011-02-18 18:11:18 +0000217#ifdef __ANDROID__
218 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000219 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000220#endif
221
Simon Kelley4820dce2012-12-18 18:30:30 +0000222#ifndef HAVE_AUTH
Simon Kelley08933472018-10-05 16:34:35 +0100223 if (daemon->auth_zones)
Simon Kelley4820dce2012-12-18 18:30:30 +0000224 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
225#endif
226
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100227#ifndef HAVE_LOOP
228 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000229 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100230#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000231
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100232#ifndef HAVE_UBUS
233 if (option_bool(OPT_UBUS))
234 die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
235#endif
236
Hans Dedecker926332a2016-01-23 10:48:12 +0000237 if (daemon->max_port < daemon->min_port)
238 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
239
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100240 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000241
Simon Kelley08933472018-10-05 16:34:35 +0100242 if (daemon->auth_zones)
243 {
244 if (!daemon->authserver)
245 die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
246
247 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000248#ifdef HAVE_BROKEN_RTC
Martin Schiller53792c92018-10-08 14:55:19 +0200249 if (daemon->soa_sn == 0)
Simon Kelley08933472018-10-05 16:34:35 +0100250 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000251#else
Simon Kelley08933472018-10-05 16:34:35 +0100252 if (daemon->soa_sn == 0)
253 daemon->soa_sn = now;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000254#endif
Simon Kelley08933472018-10-05 16:34:35 +0100255 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000256
Simon Kelleyff7eea22013-09-04 18:01:38 +0100257#ifdef HAVE_DHCP6
258 if (daemon->dhcp6)
259 {
260 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000261
Simon Kelleyff7eea22013-09-04 18:01:38 +0100262 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000263 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100264 if (context->flags & CONTEXT_DHCP)
265 daemon->doing_dhcp6 = 1;
266 if (context->flags & CONTEXT_RA)
267 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000268#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100269 if (context->flags & CONTEXT_TEMPLATE)
270 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000271#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000272 }
Simon Kelley1f776932012-12-16 19:46:08 +0000273 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100274#endif
275
276#ifdef HAVE_DHCP
277 /* Note that order matters here, we must call lease_init before
278 creating any file descriptors which shouldn't be leaked
279 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000280 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000281 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000282 conditions below. */
283 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000284 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100285 {
286 dhcp_common_init();
287 if (daemon->dhcp || daemon->doing_dhcp6)
288 lease_init(now);
289 }
290
291 if (daemon->dhcp || daemon->relay4)
Simon Kelley305ffb52019-03-16 18:17:17 +0000292 {
293 dhcp_init();
294# ifdef HAVE_LINUX_NETWORK
295 if (!option_bool(OPT_NO_PING))
296 need_cap_net_raw = 1;
297 need_cap_net_admin = 1;
298# endif
299 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100300
301# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100302 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelley305ffb52019-03-16 18:17:17 +0000303 {
304 ra_init(now);
305# ifdef HAVE_LINUX_NETWORK
306 need_cap_net_raw = 1;
307 need_cap_net_admin = 1;
308# endif
309 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100310
311 if (daemon->doing_dhcp6 || daemon->relay6)
312 dhcp6_init();
313# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000314
Simon Kelley7622fc02009-06-04 20:32:05 +0100315#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100316
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000317#ifdef HAVE_IPSET
318 if (daemon->ipsets)
Simon Kelley305ffb52019-03-16 18:17:17 +0000319 {
320 ipset_init();
321# ifdef HAVE_LINUX_NETWORK
322 need_cap_net_admin = 1;
323# endif
324 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000325#endif
326
Simon Kelley1ee9be42013-12-09 16:50:19 +0000327#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000328 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000329#elif defined(HAVE_BSD_NETWORK)
330 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000331#endif
332
Simon Kelley1ee9be42013-12-09 16:50:19 +0000333 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
334 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
335
Simon Kelley115ac3e2013-05-20 11:28:32 +0100336 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100337 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000338
Simon Kelley54dd3932012-06-20 11:23:38 +0100339 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100340 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100341 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100342
343 if (!option_bool(OPT_CLEVERBIND))
344 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
345 if (if_tmp->name && !if_tmp->used)
346 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100347
348#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
349 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100350 bound_device = whichdevice();
351
Simon Kelley9380ba72012-04-16 14:41:56 +0100352 if (daemon->dhcp)
353 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100354 if (!daemon->relay4 && bound_device)
355 {
356 bindtodevice(bound_device, daemon->dhcpfd);
357 did_bind = 1;
358 }
359 if (daemon->enable_pxe && bound_device)
360 {
361 bindtodevice(bound_device, daemon->pxefd);
362 did_bind = 1;
363 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100364 }
365#endif
366
367#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100368 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
369 {
370 bindtodevice(bound_device, daemon->dhcp6fd);
371 did_bind = 1;
372 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100373#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100374 }
Simon Kelley28866e92011-02-14 20:19:14 +0000375 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100376 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000377
378#ifdef HAVE_DHCP6
379 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100380 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000381 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000382
383 /* After netlink_init() and before create_helper() */
384 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000385#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100386
Simon Kelley824af852008-02-12 20:43:05 +0000387 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000388 {
389 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000390
Simon Kelley82e3f452014-01-31 21:05:48 +0000391 blockdata_init();
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000392 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000393
Simon Kelley04918052015-01-26 11:23:43 +0000394#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000395 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
396 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000397 inotify_dnsmasq_init();
398 else
399 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000400#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100401
402 if (daemon->dump_file)
403#ifdef HAVE_DUMPFILE
404 dump_init();
405 else
406 daemon->dumpfd = -1;
407#else
408 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
409#endif
410
Simon Kelley28866e92011-02-14 20:19:14 +0000411 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100412#ifdef HAVE_DBUS
413 {
414 char *err;
415 daemon->dbus = NULL;
416 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100417 if ((err = dbus_init()))
418 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100419 }
420#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100421 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100422#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100423
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100424 if (option_bool(OPT_UBUS))
425#ifdef HAVE_UBUS
426 {
427 daemon->ubus = NULL;
428 ubus_init();
429 }
430#else
431 die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
432#endif
433
Simon Kelley824af852008-02-12 20:43:05 +0000434 if (daemon->port != 0)
435 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100436
Simon Kelleyc72daea2012-01-05 21:33:27 +0000437#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100438 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000439 if ((daemon->dhcp || daemon->dhcp6) &&
440 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000441 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100442 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000443 struct passwd *scr_pw;
444
445 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100446 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000447 script_uid = scr_pw->pw_uid;
448 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100449 }
450 else
451 baduser = daemon->scriptuser;
452 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100453#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000454
Simon Kelley1a6bca82008-07-11 11:11:42 +0100455 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
456 baduser = daemon->username;
457 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
458 baduser = daemon->groupname;
459
460 if (baduser)
461 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000462
Simon Kelley1a6bca82008-07-11 11:11:42 +0100463 /* implement group defaults, "dip" if available, or group associated with uid */
464 if (!daemon->group_set && !gp)
465 {
466 if (!(gp = getgrnam(CHGRP)) && ent_pw)
467 gp = getgrgid(ent_pw->pw_gid);
468
469 /* for error message */
470 if (gp)
471 daemon->groupname = gp->gr_name;
472 }
473
474#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000475 /* We keep CAP_NETADMIN (for ARP-injection) and
476 CAP_NET_RAW (for icmp) if we're doing dhcp,
477 if we have yet to bind ports because of DAD,
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100478 or we're doing it dynamically, we need CAP_NET_BIND_SERVICE. */
Simon Kelley305ffb52019-03-16 18:17:17 +0000479 if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
480 (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
481 need_cap_net_bind_service = 1;
482
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100483 /* usptream servers which bind to an interface call SO_BINDTODEVICE
Simon Kelleydefd6b12019-09-16 23:02:12 +0100484 for each TCP connection, so need CAP_NET_RAW */
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100485 for (serv = daemon->servers; serv; serv = serv->next)
486 if (serv->interface[0] != 0)
Simon Kelleydefd6b12019-09-16 23:02:12 +0100487 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100488
489 /* If we're doing Dbus or UBus, the above can be set dynamically,
490 (as can ports) so always (potentially) needed. */
491#ifdef HAVE_DBUS
492 if (option_bool(OPT_DBUS))
493 {
494 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100495 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100496 }
497#endif
498
499#ifdef HAVE_UBUS
500 if (option_bool(OPT_UBUS))
501 {
502 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100503 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100504 }
505#endif
506
Simon Kelley1a6bca82008-07-11 11:11:42 +0100507 /* determine capability API version here, while we can still
508 call safe_malloc */
Simon Kelley305ffb52019-03-16 18:17:17 +0000509 int capsize = 1; /* for header version 1 */
510 char *fail = NULL;
511
512 hdr = safe_malloc(sizeof(*hdr));
513
514 /* find version supported by kernel */
515 memset(hdr, 0, sizeof(*hdr));
516 capget(hdr, NULL);
517
518 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100519 {
Simon Kelley305ffb52019-03-16 18:17:17 +0000520 /* if unknown version, use largest supported version (3) */
521 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
522 hdr->version = LINUX_CAPABILITY_VERSION_3;
523 capsize = 2;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100524 }
Simon Kelley305ffb52019-03-16 18:17:17 +0000525
526 data = safe_malloc(sizeof(*data) * capsize);
527 capget(hdr, data); /* Get current values, for verification */
528
529 if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
530 fail = "NET_ADMIN";
531 else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
532 fail = "NET_RAW";
533 else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
534 fail = "NET_BIND_SERVICE";
535
536 if (fail)
537 die(_("process is missing required capability %s"), fail, EC_MISC);
538
539 /* Now set bitmaps to set caps after daemonising */
540 memset(data, 0, sizeof(*data) * capsize);
541
542 if (need_cap_net_admin)
543 data->effective |= (1 << CAP_NET_ADMIN);
544 if (need_cap_net_raw)
545 data->effective |= (1 << CAP_NET_RAW);
546 if (need_cap_net_bind_service)
547 data->effective |= (1 << CAP_NET_BIND_SERVICE);
548
549 data->permitted = data->effective;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100550#endif
551
Simon Kelley5aabfc72007-08-29 11:24:47 +0100552 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100553 in a race-free manner and another to carry errors to daemon-invoking process */
554 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100555
556 piperead = pipefd[0];
557 pipewrite = pipefd[1];
558 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000559 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100560
561 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100562
Simon Kelley28866e92011-02-14 20:19:14 +0000563 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000564 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000565 /* The following code "daemonizes" the process.
566 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100567
Simon Kelley9e038942008-05-30 20:06:34 +0100568 if (chdir("/") != 0)
569 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
570
Simon Kelley28866e92011-02-14 20:19:14 +0000571 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100572 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100573 pid_t pid;
574
Simon Kelley1a6bca82008-07-11 11:11:42 +0100575 /* pipe to carry errors back to original process.
576 When startup is complete we close this and the process terminates. */
577 safe_pipe(err_pipe, 0);
578
Simon Kelley7622fc02009-06-04 20:32:05 +0100579 if ((pid = fork()) == -1)
580 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000581 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100582
Simon Kelley5aabfc72007-08-29 11:24:47 +0100583 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100584 {
585 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000586 char *msg;
587
Simon Kelley1a6bca82008-07-11 11:11:42 +0100588 /* close our copy of write-end */
Simon Kelley5fc639c2019-03-29 21:29:43 +0000589 close(err_pipe[1]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100590
591 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000592 if (read_event(err_pipe[0], &ev, &msg))
593 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100594
595 _exit(EC_GOOD);
596 }
597
Simon Kelley5fc639c2019-03-29 21:29:43 +0000598 close(err_pipe[0]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100599
600 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100601
602 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100603
604 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000605 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100606
607 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100608 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100609 }
Simon Kelley9e038942008-05-30 20:06:34 +0100610
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000611 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100612 if (daemon->runfile)
613 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100614 int fd, err = 0;
615
616 sprintf(daemon->namebuff, "%d\n", (int) getpid());
617
618 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
619 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
620 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
621 extent that an attacker running as the unprivileged user could replace the pidfile with a
622 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
623
Josh Soref730c6742017-02-06 16:14:04 +0000624 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100625 ensuring that the open() fails should there be any existing file (because the unlink() failed,
626 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
627 attack can succeed.
628
629 Any compromise of the non-privileged user still theoretically allows the pid-file to be
630 replaced whilst dnsmasq is running. The worst that could allow is that the usual
631 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
632
633 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
634 failure to write the pid-file.
635 */
636
637 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100638
Simon Kelley79cfefd2012-09-02 13:29:51 +0100639 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 +0100640 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100641 /* only complain if started as root */
642 if (getuid() == 0)
643 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100644 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100645 else
646 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000647 /* We're still running as root here. Change the ownership of the PID file
648 to the user we will be running as. Note that this is not to allow
649 us to delete the file, since that depends on the permissions
650 of the directory containing the file. That directory will
651 need to by owned by the dnsmasq user, and the ownership of the
652 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000653 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
654 chown_warn = errno;
655
656 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100657 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000658 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000659 {
Simon Kelley5fc639c2019-03-29 21:29:43 +0000660 if (close(fd) == -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000661 err = 1;
662 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100663 }
664
665 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100666 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000667 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100668 _exit(0);
669 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000670 }
Simon Kelley16972692006-10-16 20:04:18 +0100671 }
672
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100673 log_err = log_start(ent_pw, err_pipe[1]);
674
Simon Kelley28866e92011-02-14 20:19:14 +0000675 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100676 {
677 /* open stdout etc to /dev/null */
678 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000679 if (nullfd != -1)
680 {
681 dup2(nullfd, STDOUT_FILENO);
682 dup2(nullfd, STDERR_FILENO);
683 dup2(nullfd, STDIN_FILENO);
684 close(nullfd);
685 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100686 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100687
Simon Kelley1a6bca82008-07-11 11:11:42 +0100688 /* if we are to run scripts, we need to fork a helper before dropping root. */
689 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000690#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000691 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000692 (daemon->lease_change_command || daemon->luascript))
693 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100694#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100695
Simon Kelley28866e92011-02-14 20:19:14 +0000696 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100697 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100698 int bad_capabilities = 0;
699 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100700
Josh Soref730c6742017-02-06 16:14:04 +0000701 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100702 if (gp &&
703 (setgroups(0, &dummy) == -1 ||
704 setgid(gp->gr_gid) == -1))
705 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000706 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100707 _exit(0);
708 }
709
Simon Kelley7cebd202006-05-06 14:13:33 +0100710 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100711 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100712#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000713 /* Need to be able to drop root. */
714 data->effective |= (1 << CAP_SETUID);
715 data->permitted |= (1 << CAP_SETUID);
Simon Kelley16972692006-10-16 20:04:18 +0100716 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000717 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100718 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100719
Simon Kelley7622fc02009-06-04 20:32:05 +0100720#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000721 /* http://developers.sun.com/solaris/articles/program_privileges.html */
722 priv_set_t *priv_set;
723
724 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
725 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
726 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
727 bad_capabilities = errno;
728
729 if (priv_set && bad_capabilities == 0)
730 {
731 priv_inverse(priv_set);
732
733 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
734 bad_capabilities = errno;
735 }
736
737 if (priv_set)
738 priv_freeset(priv_set);
739
Simon Kelley824af852008-02-12 20:43:05 +0000740#endif
741
Simon Kelley1a6bca82008-07-11 11:11:42 +0100742 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100743 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000744 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100745 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100746 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100747
748 /* finally drop root */
749 if (setuid(ent_pw->pw_uid) == -1)
750 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000751 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100752 _exit(0);
753 }
754
755#ifdef HAVE_LINUX_NETWORK
Simon Kelley305ffb52019-03-16 18:17:17 +0000756 data->effective &= ~(1 << CAP_SETUID);
757 data->permitted &= ~(1 << CAP_SETUID);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100758
Simon Kelley305ffb52019-03-16 18:17:17 +0000759 /* lose the setuid capability */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100760 if (capset(hdr, data) == -1)
761 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000762 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100763 _exit(0);
764 }
765#endif
766
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000767 }
Simon Kelley849a8352006-06-09 21:02:31 +0100768 }
Simon Kelley16972692006-10-16 20:04:18 +0100769
Simon Kelley16972692006-10-16 20:04:18 +0100770#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000771 free(hdr);
772 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000773 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000774 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100775#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100776
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100777#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100778 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100779 {
780 DIR *dir;
781 struct tftp_prefix *p;
782
783 if (daemon->tftp_prefix)
784 {
785 if (!((dir = opendir(daemon->tftp_prefix))))
786 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100787 tftp_prefix_missing = 1;
788 if (!option_bool(OPT_TFTP_NO_FAIL))
789 {
790 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
791 _exit(0);
792 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100793 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100794 else
795 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100796 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100797
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100798 for (p = daemon->if_prefix; p; p = p->next)
799 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100800 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100801 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100802 {
803 p->missing = 1;
804 if (!option_bool(OPT_TFTP_NO_FAIL))
805 {
806 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
807 _exit(0);
808 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100809 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100810 else
811 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100812 }
813 }
814#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100815
Simon Kelley824af852008-02-12 20:43:05 +0000816 if (daemon->port == 0)
817 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000818 else
819 {
820 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100821 {
822 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
823 if (daemon->cachesize > 10000)
824 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
825 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000826 else
827 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
828
829 if (option_bool(OPT_LOCAL_SERVICE))
830 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
831 }
Simon Kelley16972692006-10-16 20:04:18 +0100832
Simon Kelleyf2621c72007-04-29 19:47:21 +0100833 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000834
835 if (chown_warn != 0)
836 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100837
Simon Kelley3d8df262005-08-29 12:19:27 +0100838#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000839 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100840 {
841 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100842 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100843 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100844 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100845 }
846#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000847
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100848#ifdef HAVE_UBUS
849 if (option_bool(OPT_UBUS))
850 {
851 if (daemon->ubus)
852 my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
853 else
854 my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
855 }
856#endif
857
Simon Kelley1d97ac42014-01-31 11:12:27 +0000858#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000859 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000860 {
Simon Kelley360f2512015-03-07 18:28:06 +0000861 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100862 struct ds_config *ds;
863
Simon Kelley360f2512015-03-07 18:28:06 +0000864 /* Delay creating the timestamp file until here, after we've changed user, so that
865 it has the correct owner to allow updating the mtime later.
866 This means we have to report fatal errors via the pipe. */
867 if ((rc = setup_timestamp()) == -1)
868 {
869 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
870 _exit(0);
871 }
872
Simon Kelleya6918532018-04-15 16:20:52 +0100873 if (option_bool(OPT_DNSSEC_IGN_NS))
874 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
875 else
876 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000877
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100878 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
879 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000880 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000881
882 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000883 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100884
885 for (ds = daemon->ds; ds; ds = ds->next)
886 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
887 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000888 }
Simon Kelleydb737462014-01-31 10:32:45 +0000889#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100890
Simon Kelley1a6bca82008-07-11 11:11:42 +0100891 if (log_err != 0)
892 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
893 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000894
Simon Kelleyde379512004-06-22 20:23:33 +0100895 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100896 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100897
Simon Kelleyf7029f52013-11-21 15:09:09 +0000898 if (option_bool(OPT_NOWILD))
899 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000900 else if (!option_bool(OPT_CLEVERBIND))
901 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000902
903 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100904
Simon Kelley28866e92011-02-14 20:19:14 +0000905 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000906 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
907 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100908 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100909
Simon Kelley28866e92011-02-14 20:19:14 +0000910 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100911 {
912 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100913 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100914 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000915 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100916 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100917 }
918
Simon Kelleyf2621c72007-04-29 19:47:21 +0100919 if (daemon->max_logs != 0)
920 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000921
Simon Kelleyf2621c72007-04-29 19:47:21 +0100922
Simon Kelley7622fc02009-06-04 20:32:05 +0100923#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000924 for (context = daemon->dhcp; context; context = context->next)
925 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100926
Simon Kelleyff7eea22013-09-04 18:01:38 +0100927 for (relay = daemon->relay4; relay; relay = relay->next)
928 log_relay(AF_INET, relay);
929
Simon Kelley1f776932012-12-16 19:46:08 +0000930# ifdef HAVE_DHCP6
931 for (context = daemon->dhcp6; context; context = context->next)
932 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000933
Simon Kelleyff7eea22013-09-04 18:01:38 +0100934 for (relay = daemon->relay6; relay; relay = relay->next)
935 log_relay(AF_INET6, relay);
936
Simon Kelley1f776932012-12-16 19:46:08 +0000937 if (daemon->doing_dhcp6 || daemon->doing_ra)
938 dhcp_construct_contexts(now);
939
940 if (option_bool(OPT_RA))
941 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
942# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000943
Simon Kelley3b3f4412013-10-11 16:33:28 +0100944# ifdef HAVE_LINUX_NETWORK
945 if (did_bind)
946 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
947# endif
948
Josh Soref730c6742017-02-06 16:14:04 +0000949 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000950 if (daemon->dhcp || daemon->doing_dhcp6)
951 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000952#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000953
Simon Kelley832af0b2007-01-21 20:01:28 +0000954#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000955 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100956 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100957 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000958
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000959 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100960 daemon->tftp_prefix ? _("root is ") : _("enabled"),
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000961 daemon->tftp_prefix ? daemon->tftp_prefix : "",
962 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "",
963 option_bool(OPT_SINGLE_PORT) ? _("single port mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100964
Stefan Tomanek30d08792015-03-31 22:32:11 +0100965 if (tftp_prefix_missing)
966 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100967
Stefan Tomanek30d08792015-03-31 22:32:11 +0100968 for (p = daemon->if_prefix; p; p = p->next)
969 if (p->missing)
970 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
971
Simon Kelley832af0b2007-01-21 20:01:28 +0000972 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100973 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000974 a single file will be sent to may clients (the file only needs
975 one fd). */
976
977 max_fd -= 30; /* use other than TFTP */
978
979 if (max_fd < 0)
980 max_fd = 5;
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000981 else if (max_fd < 100 && !option_bool(OPT_SINGLE_PORT))
Simon Kelley832af0b2007-01-21 20:01:28 +0000982 max_fd = max_fd/2;
983 else
984 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000985
986 /* if we have to use a limited range of ports,
987 that will limit the number of transfers */
988 if (daemon->start_tftp_port != 0 &&
989 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
990 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000991
992 if (daemon->tftp_max > max_fd)
993 {
994 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100995 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100996 _("restricting maximum simultaneous TFTP transfers to %d"),
997 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000998 }
999 }
1000#endif
1001
Simon Kelley1a6bca82008-07-11 11:11:42 +01001002 /* finished start-up - release original process */
1003 if (err_pipe[1] != -1)
Simon Kelley5fc639c2019-03-29 21:29:43 +00001004 close(err_pipe[1]);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001005
Simon Kelley824af852008-02-12 20:43:05 +00001006 if (daemon->port != 0)
1007 check_servers();
1008
Simon Kelley7cebd202006-05-06 14:13:33 +01001009 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +01001010
1011 daemon->pipe_to_parent = -1;
1012 for (i = 0; i < MAX_PROCS; i++)
1013 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +01001014
Simon Kelley04918052015-01-26 11:23:43 +00001015#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +00001016 /* Using inotify, have to select a resolv file at startup */
1017 poll_resolv(1, 0, now);
1018#endif
1019
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001020 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001021 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001022 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001023
Simon Kelleyb842bc92015-07-12 21:09:11 +01001024 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001025
Simon Kelley16972692006-10-16 20:04:18 +01001026 /* if we are out of resources, find how long we have to wait
1027 for some to come free, we'll loop around then and restart
1028 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001029 if ((t = set_dns_listeners(now)) != 0)
1030 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +01001031
Simon Kelley832af0b2007-01-21 20:01:28 +00001032 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
1033 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +00001034 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +01001035 timeout = 250;
1036
Simon Kelley74c95c22011-10-19 09:33:39 +01001037 /* Wake every second whilst waiting for DAD to complete */
1038 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001039 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001040
Simon Kelley832af0b2007-01-21 20:01:28 +00001041#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +01001042 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001043#endif
1044
1045#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001046 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001047 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001048#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001049
Simon Kelley7622fc02009-06-04 20:32:05 +01001050#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001051 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001052 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001053 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +00001054 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001055 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001056 }
Simon Kelley7622fc02009-06-04 20:32:05 +01001057#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001058
Simon Kelley52b92f42012-01-22 16:05:15 +00001059#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +01001060 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001061 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001062
Simon Kelley1f776932012-12-16 19:46:08 +00001063 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001064 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +00001065#endif
Simon Kelley04918052015-01-26 11:23:43 +00001066
1067#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001068 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001069 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +00001070#endif
1071
1072#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001073 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +00001074#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001075 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001076#endif
Simon Kelley193de4a2014-12-10 17:32:16 +00001077
Simon Kelleyb842bc92015-07-12 21:09:11 +01001078 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001079
Simon Kelley33702ab2015-12-28 23:17:15 +00001080#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001081# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001082 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001083# endif
1084
Simon Kelley1e505122016-01-25 21:29:23 +00001085 /* Refresh cache */
1086 if (option_bool(OPT_SCRIPT_ARP))
1087 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001088 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001089
Simon Kelleya9530962012-03-20 22:07:35 +00001090# ifdef HAVE_TFTP
1091 while (helper_buf_empty() && do_tftp_script_run());
1092# endif
1093
Simon Kelley16972692006-10-16 20:04:18 +01001094 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001095 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001096#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001097 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001098# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001099 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001100# endif
1101
Simon Kelleyb633de92016-01-06 22:51:17 +00001102 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001103
1104# ifdef HAVE_TFTP
1105 while (do_tftp_script_run());
1106# endif
1107
Simon Kelley5aabfc72007-08-29 11:24:47 +01001108#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001109
Simon Kelley7622fc02009-06-04 20:32:05 +01001110
Simon Kelley66f62652020-01-05 16:21:24 +00001111 /* must do this just before do_poll(), when we know no
Simon Kelleyf2621c72007-04-29 19:47:21 +01001112 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001113 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001114
Simon Kelleyb842bc92015-07-12 21:09:11 +01001115 if (do_poll(timeout) < 0)
1116 continue;
1117
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001118 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001119
Simon Kelleyb842bc92015-07-12 21:09:11 +01001120 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001121
1122 /* prime. */
1123 enumerate_interfaces(1);
1124
Simon Kelley74c95c22011-10-19 09:33:39 +01001125 /* Check the interfaces to see if any have exited DAD state
1126 and if so, bind the address. */
1127 if (is_dad_listeners())
1128 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001129 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001130 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1131 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001132 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001133 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001134
Simon Kelley1ee9be42013-12-09 16:50:19 +00001135#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001136 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001137 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001138#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001139 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001140 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001141#endif
1142
Simon Kelley04918052015-01-26 11:23:43 +00001143#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001144 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001145 {
1146 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1147 poll_resolv(1, 1, now);
1148 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001149#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001150 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001151 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001152 if (daemon->last_resolv == 0 ||
1153 difftime(now, daemon->last_resolv) > 1.0 ||
1154 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001155 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001156 /* poll_resolv doesn't need to reload first time through, since
1157 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001158
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001159 poll_resolv(0, daemon->last_resolv != 0, now);
1160 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001161 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001162#endif
1163
Simon Kelleyb842bc92015-07-12 21:09:11 +01001164 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001165 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001166
Simon Kelley3d8df262005-08-29 12:19:27 +01001167#ifdef HAVE_DBUS
1168 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001169 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001170 {
1171 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001172 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001173 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001174 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001175 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001176 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001177 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001178#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001179
1180#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001181 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001182 {
1183 /* if we didn't create a UBus connection, retry now. */
1184 if (!daemon->ubus)
1185 {
1186 ubus_init();
1187 }
1188
1189 check_ubus_listeners();
1190 }
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001191#endif
1192
Simon Kelleyb842bc92015-07-12 21:09:11 +01001193 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001194
1195#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001196 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001197#endif
1198
Simon Kelley7622fc02009-06-04 20:32:05 +01001199#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001200 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001201 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001202 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001203 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001204 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001205 dhcp_packet(now, 1);
1206 }
Simon Kelley16972692006-10-16 20:04:18 +01001207
Simon Kelley52b92f42012-01-22 16:05:15 +00001208#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001209 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001210 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001211
Simon Kelleyb842bc92015-07-12 21:09:11 +01001212 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001213 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001214#endif
1215
Simon Kelley1f15b812009-10-13 17:49:32 +01001216# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001217 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001218 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001219# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001220#endif
1221
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001222 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001223}
1224
Simon Kelley3be34542004-09-11 19:12:13 +01001225static void sig_handler(int sig)
1226{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001227 if (pid == 0)
1228 {
Simon Kelley16972692006-10-16 20:04:18 +01001229 /* ignore anything other than TERM during startup
1230 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001231 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001232 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001233 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001234 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001235 {
Simon Kelley16972692006-10-16 20:04:18 +01001236 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001237 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001238 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001239 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001240 else
1241 {
1242 /* master process */
1243 int event, errsave = errno;
1244
1245 if (sig == SIGHUP)
1246 event = EVENT_RELOAD;
1247 else if (sig == SIGCHLD)
1248 event = EVENT_CHILD;
1249 else if (sig == SIGALRM)
1250 event = EVENT_ALARM;
1251 else if (sig == SIGTERM)
1252 event = EVENT_TERM;
1253 else if (sig == SIGUSR1)
1254 event = EVENT_DUMP;
1255 else if (sig == SIGUSR2)
1256 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001257 else if (sig == SIGINT)
1258 {
1259 /* Handle SIGINT normally in debug mode, so
1260 ctrl-c continues to operate. */
1261 if (option_bool(OPT_DEBUG))
1262 exit(EC_MISC);
1263 else
1264 event = EVENT_TIME;
1265 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001266 else
1267 return;
1268
Simon Kelleyc72daea2012-01-05 21:33:27 +00001269 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001270 errno = errsave;
1271 }
Simon Kelley3be34542004-09-11 19:12:13 +01001272}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001273
Simon Kelley353ae4d2012-03-19 20:07:51 +00001274/* now == 0 -> queue immediate callback */
1275void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001276{
Simon Kelley884a6df2012-03-20 16:20:22 +00001277 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001278 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001279 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1280 if ((now == 0 || difftime(event, now) <= 0.0))
1281 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1282 else
1283 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001284 }
Simon Kelley741c2952012-02-25 13:09:18 +00001285}
1286
Simon Kelley47a95162014-07-08 22:22:02 +01001287void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001288{
Simon Kelley47a95162014-07-08 22:22:02 +01001289 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001290}
1291
Simon Kelleyc72daea2012-01-05 21:33:27 +00001292void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001293{
1294 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001295 struct iovec iov[2];
1296
Simon Kelley5aabfc72007-08-29 11:24:47 +01001297 ev.event = event;
1298 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001299 ev.msg_sz = msg ? strlen(msg) : 0;
1300
1301 iov[0].iov_base = &ev;
1302 iov[0].iov_len = sizeof(ev);
1303 iov[1].iov_base = msg;
1304 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001305
1306 /* error pipe, debug mode. */
1307 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001308 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001309 else
1310 /* pipe is non-blocking and struct event_desc is smaller than
1311 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001312 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001313}
Simon Kelley3d8df262005-08-29 12:19:27 +01001314
Simon Kelleyc72daea2012-01-05 21:33:27 +00001315/* NOTE: the memory used to return msg is leaked: use msgs in events only
1316 to describe fatal errors. */
1317static int read_event(int fd, struct event_desc *evp, char **msg)
1318{
1319 char *buf;
1320
1321 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1322 return 0;
1323
1324 *msg = NULL;
1325
1326 if (evp->msg_sz != 0 &&
1327 (buf = malloc(evp->msg_sz + 1)) &&
1328 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1329 {
1330 buf[evp->msg_sz] = 0;
1331 *msg = buf;
1332 }
1333
1334 return 1;
1335}
1336
1337static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001338{
1339 errno = ev->data;
1340
1341 switch (ev->event)
1342 {
1343 case EVENT_DIE:
1344 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001345
1346 case EVENT_FORK_ERR:
1347 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001348
1349 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001350 case EVENT_PIPE_ERR:
1351 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001352
1353 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001354 case EVENT_CAP_ERR:
1355 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1356
Simon Kelleye7a4af82018-02-16 21:27:35 +00001357 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001358 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001359 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001360
Simon Kelleye7a4af82018-02-16 21:27:35 +00001361 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001362 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001363 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001364
1365 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001366 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001367 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001368
Simon Kelleye7a4af82018-02-16 21:27:35 +00001369 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001370 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001371 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001372
1373 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001374 case EVENT_LUA_ERR:
1375 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001376
Simon Kelleye7a4af82018-02-16 21:27:35 +00001377 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001378 case EVENT_TFTP_ERR:
1379 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001380
1381 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001382 case EVENT_TIME_ERR:
1383 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001384 }
1385}
1386
Simon Kelley5aabfc72007-08-29 11:24:47 +01001387static void async_event(int pipe, time_t now)
1388{
1389 pid_t p;
1390 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001391 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001392 char *msg;
1393
1394 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1395 to describe fatal errors. */
1396
1397 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001398 switch (ev.event)
1399 {
1400 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001401 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001402
Simon Kelleye98bd522014-03-28 20:41:23 +00001403 /* fall through */
1404
1405 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001406 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001407
Simon Kelley7b1eae42014-02-20 13:43:28 +00001408 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001409 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001410 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1411 {
1412 reload_servers(daemon->resolv_files->name);
1413 check = 1;
1414 }
1415
1416 if (daemon->servers_file)
1417 {
1418 read_servers_file();
1419 check = 1;
1420 }
1421
1422 if (check)
1423 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001424 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001425
Simon Kelley7622fc02009-06-04 20:32:05 +01001426#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001427 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001428#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001429 break;
1430
1431 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001432 if (daemon->port != 0)
1433 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001434 break;
1435
1436 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001437#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001438 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001439 {
1440 lease_prune(NULL, now);
1441 lease_update_file(now);
1442 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001443#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001444 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001445 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1446 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001447#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001448#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001449 break;
1450
1451 case EVENT_CHILD:
1452 /* See Stevens 5.10 */
1453 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1454 if (p == -1)
1455 {
1456 if (errno != EINTR)
1457 break;
1458 }
1459 else
1460 for (i = 0 ; i < MAX_PROCS; i++)
1461 if (daemon->tcp_pids[i] == p)
1462 daemon->tcp_pids[i] = 0;
1463 break;
1464
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001465#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001466 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001467 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001468 break;
1469
1470 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001471 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001472 break;
1473
1474 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001475 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1476 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001477 break;
1478
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001479 case EVENT_SCRIPT_LOG:
1480 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1481 free(msg);
1482 msg = NULL;
1483 break;
1484
Simon Kelley1a6bca82008-07-11 11:11:42 +01001485 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001486 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001487 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001488 case EVENT_LUA_ERR:
1489 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001490 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001491#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001492
Simon Kelley5aabfc72007-08-29 11:24:47 +01001493 case EVENT_REOPEN:
1494 /* Note: this may leave TCP-handling processes with the old file still open.
1495 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1496 we leave them logging to the old file. */
1497 if (daemon->log_file != NULL)
1498 log_reopen(daemon->log_file);
1499 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001500
1501 case EVENT_NEWADDR:
1502 newaddress(now);
1503 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001504
1505 case EVENT_NEWROUTE:
1506 resend_query();
1507 /* Force re-reading resolv file right now, for luck. */
1508 poll_resolv(0, 1, now);
1509 break;
1510
Simon Kelley3c973ad2018-01-14 21:05:37 +00001511 case EVENT_TIME:
1512#ifdef HAVE_DNSSEC
1513 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1514 {
1515 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1516 daemon->dnssec_no_time_check = 0;
1517 clear_cache_and_reload(now);
1518 }
1519#endif
1520 break;
1521
Simon Kelley5aabfc72007-08-29 11:24:47 +01001522 case EVENT_TERM:
1523 /* Knock all our children on the head. */
1524 for (i = 0; i < MAX_PROCS; i++)
1525 if (daemon->tcp_pids[i] != 0)
1526 kill(daemon->tcp_pids[i], SIGALRM);
1527
Simon Kelley53a91732016-01-06 17:59:13 +00001528#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001529 /* handle pending lease transitions */
1530 if (daemon->helperfd != -1)
1531 {
1532 /* block in writes until all done */
1533 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1534 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1535 do {
1536 helper_write();
1537 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelley5fc639c2019-03-29 21:29:43 +00001538 close(daemon->helperfd);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001539 }
1540#endif
1541
1542 if (daemon->lease_stream)
1543 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001544
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001545#ifdef HAVE_DNSSEC
1546 /* update timestamp file on TERM if time is considered valid */
1547 if (daemon->back_to_the_future)
1548 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001549 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001550 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1551 }
1552#endif
1553
Simon Kelley73a08a22009-02-05 20:28:08 +00001554 if (daemon->runfile)
1555 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001556
1557#ifdef HAVE_DUMPFILE
1558 if (daemon->dumpfd != -1)
1559 close(daemon->dumpfd);
1560#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001561
1562 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1563 flush_log();
1564 exit(EC_GOOD);
1565 }
1566}
1567
Simon Kelley47a95162014-07-08 22:22:02 +01001568static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001569{
1570 struct resolvc *res, *latest;
1571 struct stat statbuf;
1572 time_t last_change = 0;
1573 /* There may be more than one possible file.
1574 Go through and find the one which changed _last_.
1575 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001576
Simon Kelley28866e92011-02-14 20:19:14 +00001577 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001578 return;
1579
Simon Kelley5aabfc72007-08-29 11:24:47 +01001580 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1581 if (stat(res->name, &statbuf) == -1)
1582 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001583 if (force)
1584 {
1585 res->mtime = 0;
1586 continue;
1587 }
1588
Simon Kelley5aabfc72007-08-29 11:24:47 +01001589 if (!res->logged)
1590 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1591 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001592
1593 if (res->mtime != 0)
1594 {
1595 /* existing file evaporated, force selection of the latest
1596 file even if its mtime hasn't changed since we last looked */
1597 poll_resolv(1, do_reload, now);
1598 return;
1599 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001600 }
1601 else
1602 {
1603 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001604 if (force || (statbuf.st_mtime != res->mtime))
1605 {
1606 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001607 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1608 {
1609 last_change = statbuf.st_mtime;
1610 latest = res;
1611 }
1612 }
1613 }
1614
1615 if (latest)
1616 {
1617 static int warned = 0;
1618 if (reload_servers(latest->name))
1619 {
1620 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1621 warned = 0;
1622 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001623 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001624 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001625 }
1626 else
1627 {
1628 latest->mtime = 0;
1629 if (!warned)
1630 {
1631 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1632 warned = 1;
1633 }
1634 }
1635 }
1636}
1637
1638void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001639{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001640 (void)now;
1641
Simon Kelley824af852008-02-12 20:43:05 +00001642 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001643 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001644
Simon Kelley7622fc02009-06-04 20:32:05 +01001645#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001646 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001647 {
Simon Kelley28866e92011-02-14 20:19:14 +00001648 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001649 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001650 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001651 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001652 lease_update_from_configs();
1653 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001654 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001655 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001656#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001657 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001658 /* Not doing DHCP, so no lease system, manage
1659 alarms for ra only */
1660 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001661#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001662#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001663}
1664
Simon Kelleyb842bc92015-07-12 21:09:11 +01001665static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001666{
1667 struct serverfd *serverfdp;
1668 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001669 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001670
1671#ifdef HAVE_TFTP
1672 int tftp = 0;
1673 struct tftp_transfer *transfer;
Simon Kelley66f62652020-01-05 16:21:24 +00001674 if (!option_bool(OPT_SINGLE_PORT))
1675 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1676 {
1677 tftp++;
1678 poll_listen(transfer->sockfd, POLLIN);
1679 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001680#endif
1681
Simon Kelley16972692006-10-16 20:04:18 +01001682 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001683 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001684 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001685
Simon Kelley3be34542004-09-11 19:12:13 +01001686 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001687 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001688
Simon Kelley1a6bca82008-07-11 11:11:42 +01001689 if (daemon->port != 0 && !daemon->osport)
1690 for (i = 0; i < RANDOM_SOCKS; i++)
1691 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001692 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001693
Simon Kelley3be34542004-09-11 19:12:13 +01001694 for (listener = daemon->listeners; listener; listener = listener->next)
1695 {
Simon Kelley16972692006-10-16 20:04:18 +01001696 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001697 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001698 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001699
Simon Kelley16972692006-10-16 20:04:18 +01001700 /* death of a child goes through the select loop, so
1701 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001702 if (listener->tcpfd != -1)
1703 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001704 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001705 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001706 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001707 break;
1708 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001709
Simon Kelley832af0b2007-01-21 20:01:28 +00001710#ifdef HAVE_TFTP
Simon Kelley2ac4cf02020-01-06 23:39:33 +00001711 /* tftp == 0 in single-port mode. */
Simon Kelley832af0b2007-01-21 20:01:28 +00001712 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001713 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001714#endif
1715
1716 }
1717
Simon Kelleya799ca02018-10-18 19:35:29 +01001718 if (!option_bool(OPT_DEBUG))
1719 for (i = 0; i < MAX_PROCS; i++)
1720 if (daemon->tcp_pipes[i] != -1)
1721 poll_listen(daemon->tcp_pipes[i], POLLIN);
Simon Kelleya799ca02018-10-18 19:35:29 +01001722
Simon Kelley16972692006-10-16 20:04:18 +01001723 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001724}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001725
Simon Kelleyb842bc92015-07-12 21:09:11 +01001726static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001727{
1728 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001729 struct listener *listener;
1730 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001731 int pipefd[2];
Simon Kelleya799ca02018-10-18 19:35:29 +01001732
Simon Kelley832af0b2007-01-21 20:01:28 +00001733 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001734 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001735 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1736
1737 if (daemon->port != 0 && !daemon->osport)
1738 for (i = 0; i < RANDOM_SOCKS; i++)
1739 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001740 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001741 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001742
Simon Kelleya799ca02018-10-18 19:35:29 +01001743 /* Races. The child process can die before we read all of the data from the
1744 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1745 process, and tcp_pipes to -1 and close the FD when we read the last
1746 of the data - indicated by cache_recv_insert returning zero.
1747 The order of these events is indeterminate, and both are needed
1748 to free the process slot. Once the child process has gone, poll()
1749 returns POLLHUP, not POLLIN, so have to check for both here. */
1750 if (!option_bool(OPT_DEBUG))
1751 for (i = 0; i < MAX_PROCS; i++)
1752 if (daemon->tcp_pipes[i] != -1 &&
1753 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1754 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1755 {
1756 close(daemon->tcp_pipes[i]);
1757 daemon->tcp_pipes[i] = -1;
1758 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001759
Simon Kelley832af0b2007-01-21 20:01:28 +00001760 for (listener = daemon->listeners; listener; listener = listener->next)
1761 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001762 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001763 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001764
Simon Kelley832af0b2007-01-21 20:01:28 +00001765#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001766 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001767 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001768#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001769
Simon Kelleyb842bc92015-07-12 21:09:11 +01001770 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001771 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001772 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001773 struct irec *iface = NULL;
1774 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001775 union mysockaddr tcp_addr;
1776 socklen_t tcp_len = sizeof(union mysockaddr);
1777
1778 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001779
Simon Kelley46b06652013-02-04 21:47:59 +00001780 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001781 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001782
Simon Kelley46b06652013-02-04 21:47:59 +00001783 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1784 {
Simon Kelley5fc639c2019-03-29 21:29:43 +00001785 close(confd);
Simon Kelley46b06652013-02-04 21:47:59 +00001786 continue;
1787 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001788
1789 /* Make sure that the interface list is up-to-date.
1790
1791 We do this here as we may need the results below, and
1792 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001793
Simon Kelley76dd75d2013-05-23 10:04:25 +01001794 Multiple calls to enumerate_interfaces() per select loop are
1795 inhibited, so calls to it in the child process (which doesn't select())
1796 have no effect. This avoids two processes reading from the same
1797 netlink fd and screwing the pooch entirely.
1798 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001799
Simon Kelley76dd75d2013-05-23 10:04:25 +01001800 enumerate_interfaces(0);
1801
1802 if (option_bool(OPT_NOWILD))
1803 iface = listener->iface; /* May be NULL */
1804 else
1805 {
1806 int if_index;
1807 char intr_name[IF_NAMESIZE];
1808
1809 /* if we can find the arrival interface, check it's one that's allowed */
1810 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1811 indextoname(listener->tcpfd, if_index, intr_name))
1812 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001813 union all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001814
Simon Kelley76dd75d2013-05-23 10:04:25 +01001815 if (tcp_addr.sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001816 addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001817 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001818 addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001819
1820 for (iface = daemon->interfaces; iface; iface = iface->next)
1821 if (iface->index == if_index)
1822 break;
1823
1824 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1825 client_ok = 0;
1826 }
1827
1828 if (option_bool(OPT_CLEVERBIND))
1829 iface = listener->iface; /* May be NULL */
1830 else
1831 {
1832 /* Check for allowed interfaces when binding the wildcard address:
1833 we do this by looking for an interface with the same address as
1834 the local address of the TCP connection, then looking to see if that's
1835 an allowed interface. As a side effect, we get the netmask of the
1836 interface too, for localisation. */
1837
1838 for (iface = daemon->interfaces; iface; iface = iface->next)
1839 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1840 break;
1841
1842 if (!iface)
1843 client_ok = 0;
1844 }
1845 }
1846
Simon Kelley22ce5502013-01-22 13:53:04 +00001847 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001848 {
1849 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001850 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001851 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001852 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001853 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001854 close(pipefd[1]); /* parent needs read pipe end. */
1855 if (p == -1)
1856 close(pipefd[0]);
1857 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001858 {
1859 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001860
Simon Kelley832af0b2007-01-21 20:01:28 +00001861 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001862 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001863 {
Simon Kelley77476582020-02-09 23:19:41 +00001864 char a;
1865
Simon Kelley832af0b2007-01-21 20:01:28 +00001866 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001867 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley77476582020-02-09 23:19:41 +00001868#ifdef HAVE_LINUX_NETWORK
1869 /* The child process inherits the netlink socket,
1870 which it never uses, but when the parent (us)
1871 uses it in the future, the answer may go to the
1872 child, resulting in the parent blocking
1873 forever awaiting the result. To avoid this
1874 the child closes the netlink socket, but there's
1875 a nasty race, since the parent may use netlink
1876 before the child has done the close.
1877
1878 To avoid this, the parent blocks here until a
1879 single byte comes back up the pipe, which
1880 is sent by the child after it has closed the
1881 netlink socket. */
1882 retry_send(read(pipefd[0], &a, 1));
1883#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001884 break;
1885 }
1886 }
Simon Kelley5fc639c2019-03-29 21:29:43 +00001887 close(confd);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001888
1889 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1890 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001891 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001892 else
1893 {
1894 unsigned char *buff;
1895 struct server *s;
1896 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001897 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001898 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001899
Simon Kelley52d4abf2012-03-21 21:39:48 +00001900 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001901 {
1902 netmask = iface->netmask;
1903 auth_dns = iface->dns_auth;
1904 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001905 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001906 {
1907 netmask.s_addr = 0;
1908 auth_dns = 0;
1909 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001910
Josh Soref730c6742017-02-06 16:14:04 +00001911 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001912 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001913 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001914 {
Simon Kelley77476582020-02-09 23:19:41 +00001915 char a = 0;
Simon Kelleya799ca02018-10-18 19:35:29 +01001916 alarm(CHILD_LIFETIME);
1917 close(pipefd[0]); /* close read end in child. */
1918 daemon->pipe_to_parent = pipefd[1];
Simon Kelley77476582020-02-09 23:19:41 +00001919#ifdef HAVE_LINUX_NETWORK
1920 /* See comment above re netlink socket. */
1921 close(daemon->netlinkfd);
1922 retry_send(write(pipefd[1], &a, 1));
1923#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001924 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001925
Simon Kelley832af0b2007-01-21 20:01:28 +00001926 /* start with no upstream connections. */
1927 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001928 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001929
1930 /* The connected socket inherits non-blocking
1931 attribute from the listening socket.
1932 Reset that here. */
1933 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1934 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1935
Simon Kelley4f7b3042012-11-28 21:27:02 +00001936 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001937
Simon Kelley832af0b2007-01-21 20:01:28 +00001938 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001939 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001940
1941 if (buff)
1942 free(buff);
1943
1944 for (s = daemon->servers; s; s = s->next)
1945 if (s->tcpfd != -1)
1946 {
1947 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001948 close(s->tcpfd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001949 }
Simon Kelley28866e92011-02-14 20:19:14 +00001950 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001951 {
1952 flush_log();
1953 _exit(0);
1954 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001955 }
1956 }
1957 }
Simon Kelley3be34542004-09-11 19:12:13 +01001958}
1959
Simon Kelley7622fc02009-06-04 20:32:05 +01001960#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001961int make_icmp_sock(void)
1962{
Simon Kelley7cebd202006-05-06 14:13:33 +01001963 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001964 int zeroopt = 0;
1965
1966 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1967 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001968 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001969 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1970 {
1971 close(fd);
1972 fd = -1;
1973 }
1974 }
1975
1976 return fd;
1977}
1978
Simon Kelley5aabfc72007-08-29 11:24:47 +01001979int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001980{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001981 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001982
Floris Bos503c6092017-04-09 23:07:13 +01001983 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001984 struct sockaddr_in saddr;
1985 struct {
1986 struct ip ip;
1987 struct icmp icmp;
1988 } packet;
1989 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001990 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001991 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001992
Simon Kelley824af852008-02-12 20:43:05 +00001993#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001994 if ((fd = make_icmp_sock()) == -1)
1995 return 0;
1996#else
1997 int opt = 2000;
1998 fd = daemon->dhcp_icmp_fd;
1999 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2000#endif
2001
Simon Kelley3be34542004-09-11 19:12:13 +01002002 saddr.sin_family = AF_INET;
2003 saddr.sin_port = 0;
2004 saddr.sin_addr = addr;
2005#ifdef HAVE_SOCKADDR_SA_LEN
2006 saddr.sin_len = sizeof(struct sockaddr_in);
2007#endif
2008
2009 memset(&packet.icmp, 0, sizeof(packet.icmp));
2010 packet.icmp.icmp_type = ICMP_ECHO;
2011 packet.icmp.icmp_id = id;
2012 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
2013 j += ((u16 *)&packet.icmp)[i];
2014 while (j>>16)
2015 j = (j & 0xffff) + (j >> 16);
2016 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
2017
Simon Kelleyff841eb2015-03-11 21:36:30 +00002018 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
2019 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002020
Floris Bos503c6092017-04-09 23:07:13 +01002021 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
2022
2023#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelley5fc639c2019-03-29 21:29:43 +00002024 close(fd);
Floris Bos503c6092017-04-09 23:07:13 +01002025#else
2026 opt = 1;
2027 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2028#endif
2029
2030 return gotreply;
2031}
2032
2033int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
2034{
2035 /* Delay processing DHCP packets for "sec" seconds counting from "start".
2036 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
2037 from "addr" with ICMP ID "id" and return 1 */
2038
2039 /* Note that whilst waiting, we check for
2040 (and service) events on the DNS and TFTP sockets, (so doing that
2041 better not use any resources our caller has in use...)
2042 but we remain deaf to signals or further DHCP packets. */
2043
2044 /* There can be a problem using dnsmasq_time() to end the loop, since
2045 it's not monotonic, and can go backwards if the system clock is
2046 tweaked, leading to the code getting stuck in this loop and
2047 ignoring DHCP requests. To fix this, we check to see if select returned
2048 as a result of a timeout rather than a socket becoming available. We
2049 only allow this to happen as many times as it takes to get to the wait time
2050 in quarter-second chunks. This provides a fallback way to end loop. */
2051
2052 int rc, timeout_count;
2053 time_t now;
2054
2055 for (now = dnsmasq_time(), timeout_count = 0;
2056 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002057 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01002058 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01002059 if (fd != -1)
2060 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01002061 set_dns_listeners(now);
2062 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002063
2064#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00002065 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002066 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002067#endif
2068
Simon Kelleyb842bc92015-07-12 21:09:11 +01002069 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01002070
2071 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002072 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01002073 else if (rc == 0)
2074 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01002075
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002076 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01002077
Simon Kelleyb842bc92015-07-12 21:09:11 +01002078 check_log_writer(0);
2079 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01002080
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002081#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01002082 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00002083 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002084#endif
2085
Simon Kelley832af0b2007-01-21 20:01:28 +00002086#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01002087 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00002088#endif
2089
Floris Bos503c6092017-04-09 23:07:13 +01002090 if (fd != -1)
2091 {
2092 struct {
2093 struct ip ip;
2094 struct icmp icmp;
2095 } packet;
2096 struct sockaddr_in faddr;
2097 socklen_t len = sizeof(faddr);
2098
2099 if (poll_check(fd, POLLIN) &&
2100 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
2101 addr == faddr.sin_addr.s_addr &&
2102 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
2103 packet.icmp.icmp_seq == 0 &&
2104 packet.icmp.icmp_id == id)
2105 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002106 }
2107 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002108
Floris Bos503c6092017-04-09 23:07:13 +01002109 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01002110}
Simon Kelley7622fc02009-06-04 20:32:05 +01002111#endif
Simon Kelley0a852542005-03-23 20:28:59 +00002112
2113