blob: ca27e8289df951b7f0e6d09248df7cd89171b0f3 [file] [log] [blame]
Simon Kelleyc8e8f5c2021-01-24 21:59:37 +00001/* dnsmasq is Copyright (c) 2000-2021 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 Kelley913fa152020-04-19 23:16:52 +010061 char *netlink_warn;
Simon Kelley1a6bca82008-07-11 11:11:42 +010062#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010063#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000064 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010065 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010066#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010067#ifdef HAVE_TFTP
68 int tftp_prefix_missing = 0;
69#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010070
Simon Kelley824af852008-02-12 20:43:05 +000071#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000072 setlocale(LC_ALL, "");
73 bindtextdomain("dnsmasq", LOCALEDIR);
74 textdomain("dnsmasq");
75#endif
76
Simon Kelley9e4abcb2004-01-22 19:47:41 +000077 sigact.sa_handler = sig_handler;
78 sigact.sa_flags = 0;
79 sigemptyset(&sigact.sa_mask);
80 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010081 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000082 sigaction(SIGHUP, &sigact, NULL);
83 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000084 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010085 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000086 sigaction(SIGINT, &sigact, NULL);
87
Simon Kelleyfeba5c12004-07-27 20:28:58 +010088 /* ignore SIGPIPE */
89 sigact.sa_handler = SIG_IGN;
90 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000091
Simon Kelley5aabfc72007-08-29 11:24:47 +010092 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelley0506a5e2020-03-19 21:56:45 +000093
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010094 rand_init(); /* Must precede read_opts() */
95
Simon Kelley5aabfc72007-08-29 11:24:47 +010096 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000097
Simon Kelley0506a5e2020-03-19 21:56:45 +000098#ifdef HAVE_LINUX_NETWORK
99 daemon->kernel_version = kernel_version();
100#endif
101
Simon Kelley3be34542004-09-11 19:12:13 +0100102 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +0000103 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +0000104
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000105 /* Min buffer size: we check after adding each record, so there must be
106 memory for the largest packet, and the largest record so the
107 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
108 This might be increased is EDNS packet size if greater than the minimum. */
109 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000110 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000111
Simon Kelleyc72daea2012-01-05 21:33:27 +0000112 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000113 if (option_bool(OPT_EXTRALOG))
114 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000115
116#ifdef HAVE_DNSSEC
117 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000118 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100119 /* Note that both /000 and '.' are allowed within labels. These get
120 represented in presentation format using NAME_ESCAPE as an escape
121 character when in DNSSEC mode.
122 In theory, if all the characters in a name were /000 or
123 '.' or NAME_ESCAPE then all would have to be escaped, so the
124 presentation format would be twice as long as the spec.
125
126 daemon->namebuff was previously allocated by the option-reading
127 code before we knew if we're in DNSSEC mode, so reallocate here. */
128 free(daemon->namebuff);
129 daemon->namebuff = safe_malloc(MAXDNAME * 2);
130 daemon->keyname = safe_malloc(MAXDNAME * 2);
131 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000132 /* one char flag per possible RR in answer section (may get extended). */
133 daemon->rr_status_sz = 64;
Simon Kelleyae7a3b92019-09-03 14:40:47 +0100134 daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000135 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000136#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000137
Simon Kelley7622fc02009-06-04 20:32:05 +0100138#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100139 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000140 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000141 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100142 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000143 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100144#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000145
Simon Kelley0541a1a2020-03-02 17:10:25 +0000146 /* Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
Simon Kelleya2761752012-01-18 16:07:21 +0000147 otherwise file descriptors we create can end up being 0, 1, or 2
148 and then get accidentally closed later when we make 0, 1, and 2
149 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
150 but it's not guaranteed. By opening /dev/null three times, we
151 ensure that we're not using those fds for real stuff. */
Simon Kelley0541a1a2020-03-02 17:10:25 +0000152 for (i = 0; i < 3; i++)
153 open("/dev/null", O_RDWR);
154
155 /* Close any file descriptors we inherited apart from std{in|out|err} */
156 close_fds(max_fd, -1, -1, -1);
157
Simon Kelley801ca9a2012-03-06 19:30:17 +0000158#ifndef HAVE_LINUX_NETWORK
159# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000160 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100161 {
162 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000163 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100164 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000165# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100166
167 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100168 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100169 {
170 bind_fallback = 1;
171 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100172 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100173 }
Simon Kelley04918052015-01-26 11:23:43 +0000174#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000175
Simon Kelley04918052015-01-26 11:23:43 +0000176#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000177 if (daemon->dynamic_dirs)
178 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100179#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100180
Simon Kelley0744ca62014-01-25 16:40:15 +0000181 if (option_bool(OPT_DNSSEC_VALID))
182 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000183#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000184 struct ds_config *ds;
185
186 /* Must have at least a root trust anchor, or the DNSSEC code
187 can loop forever. */
188 for (ds = daemon->ds; ds; ds = ds->next)
189 if (ds->name[0] == 0)
190 break;
191
192 if (!ds)
193 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000194
195 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000196 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000197#else
198 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000199#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000200 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000201
Simon Kelley832af0b2007-01-21 20:01:28 +0000202#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100203 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100204 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000205#endif
206
Simon Kelley7de060b2011-08-26 17:24:52 +0100207#ifdef HAVE_CONNTRACK
208 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000209 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100210#else
211 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000212 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100213#endif
214
Simon Kelley824af852008-02-12 20:43:05 +0000215#ifdef HAVE_SOLARIS_NETWORK
216 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000217 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000218#endif
219
Simon Kelley572b41e2011-02-18 18:11:18 +0000220#ifdef __ANDROID__
221 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000222 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000223#endif
224
Simon Kelley4820dce2012-12-18 18:30:30 +0000225#ifndef HAVE_AUTH
Simon Kelley08933472018-10-05 16:34:35 +0100226 if (daemon->auth_zones)
Simon Kelley4820dce2012-12-18 18:30:30 +0000227 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
228#endif
229
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100230#ifndef HAVE_LOOP
231 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000232 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100233#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000234
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100235#ifndef HAVE_UBUS
236 if (option_bool(OPT_UBUS))
237 die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
238#endif
239
Simon Kelley4a8c0982021-03-26 21:19:39 +0000240 /* Handle only one of min_port/max_port being set. */
241 if (daemon->min_port != 0 && daemon->max_port == 0)
242 daemon->max_port = MAX_PORT;
243
244 if (daemon->max_port != 0 && daemon->min_port == 0)
245 daemon->min_port = MIN_PORT;
246
Hans Dedecker926332a2016-01-23 10:48:12 +0000247 if (daemon->max_port < daemon->min_port)
248 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
Simon Kelley4a8c0982021-03-26 21:19:39 +0000249
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100250 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000251
Simon Kelley08933472018-10-05 16:34:35 +0100252 if (daemon->auth_zones)
253 {
254 if (!daemon->authserver)
255 die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
256
257 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000258#ifdef HAVE_BROKEN_RTC
Martin Schiller53792c92018-10-08 14:55:19 +0200259 if (daemon->soa_sn == 0)
Simon Kelley08933472018-10-05 16:34:35 +0100260 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000261#else
Simon Kelley08933472018-10-05 16:34:35 +0100262 if (daemon->soa_sn == 0)
263 daemon->soa_sn = now;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000264#endif
Simon Kelley08933472018-10-05 16:34:35 +0100265 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000266
Simon Kelleyff7eea22013-09-04 18:01:38 +0100267#ifdef HAVE_DHCP6
268 if (daemon->dhcp6)
269 {
270 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000271
Simon Kelleyff7eea22013-09-04 18:01:38 +0100272 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000273 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100274 if (context->flags & CONTEXT_DHCP)
275 daemon->doing_dhcp6 = 1;
276 if (context->flags & CONTEXT_RA)
277 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000278#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100279 if (context->flags & CONTEXT_TEMPLATE)
280 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000281#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000282 }
Simon Kelley1f776932012-12-16 19:46:08 +0000283 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100284#endif
285
286#ifdef HAVE_DHCP
287 /* Note that order matters here, we must call lease_init before
288 creating any file descriptors which shouldn't be leaked
289 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000290 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000291 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000292 conditions below. */
293 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000294 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100295 {
296 dhcp_common_init();
297 if (daemon->dhcp || daemon->doing_dhcp6)
298 lease_init(now);
299 }
300
301 if (daemon->dhcp || daemon->relay4)
Simon Kelley305ffb52019-03-16 18:17:17 +0000302 {
303 dhcp_init();
304# ifdef HAVE_LINUX_NETWORK
305 if (!option_bool(OPT_NO_PING))
306 need_cap_net_raw = 1;
307 need_cap_net_admin = 1;
308# endif
309 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100310
311# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100312 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelley305ffb52019-03-16 18:17:17 +0000313 {
314 ra_init(now);
315# ifdef HAVE_LINUX_NETWORK
316 need_cap_net_raw = 1;
317 need_cap_net_admin = 1;
318# endif
319 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100320
321 if (daemon->doing_dhcp6 || daemon->relay6)
322 dhcp6_init();
323# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000324
Simon Kelley7622fc02009-06-04 20:32:05 +0100325#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100326
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000327#ifdef HAVE_IPSET
Simon Kelley305ffb52019-03-16 18:17:17 +0000328 ipset_init();
329# ifdef HAVE_LINUX_NETWORK
330 need_cap_net_admin = 1;
331# endif
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000332#endif
333
Simon Kelley1ee9be42013-12-09 16:50:19 +0000334#if defined(HAVE_LINUX_NETWORK)
Simon Kelley913fa152020-04-19 23:16:52 +0100335 netlink_warn = netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000336#elif defined(HAVE_BSD_NETWORK)
337 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000338#endif
339
Simon Kelley1ee9be42013-12-09 16:50:19 +0000340 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
341 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
342
Simon Kelley115ac3e2013-05-20 11:28:32 +0100343 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100344 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000345
Simon Kelley54dd3932012-06-20 11:23:38 +0100346 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100347 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100348 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100349
350 if (!option_bool(OPT_CLEVERBIND))
351 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
352 if (if_tmp->name && !if_tmp->used)
353 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100354
355#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
356 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100357 bound_device = whichdevice();
358
Simon Kelley9380ba72012-04-16 14:41:56 +0100359 if (daemon->dhcp)
360 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100361 if (!daemon->relay4 && bound_device)
362 {
363 bindtodevice(bound_device, daemon->dhcpfd);
364 did_bind = 1;
365 }
366 if (daemon->enable_pxe && bound_device)
367 {
368 bindtodevice(bound_device, daemon->pxefd);
369 did_bind = 1;
370 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100371 }
372#endif
373
374#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100375 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
376 {
377 bindtodevice(bound_device, daemon->dhcp6fd);
378 did_bind = 1;
379 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100380#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100381 }
Simon Kelley28866e92011-02-14 20:19:14 +0000382 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100383 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000384
385#ifdef HAVE_DHCP6
386 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100387 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000388 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000389
390 /* After netlink_init() and before create_helper() */
391 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000392#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100393
Simon Kelley824af852008-02-12 20:43:05 +0000394 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000395 {
396 cache_init();
Simon Kelley82e3f452014-01-31 21:05:48 +0000397 blockdata_init();
Simon Kelleye75069f2021-01-22 22:50:25 +0000398 hash_questions_init();
Simon Kelleyea28d0e2021-03-26 22:02:04 +0000399
400 /* Scale random socket pool by ftabsize, but
401 limit it based on available fds. */
402 daemon->numrrand = daemon->ftabsize/2;
403 if (daemon->numrrand > max_fd/3)
404 daemon->numrrand = max_fd/3;
405 /* safe_malloc returns zero'd memory */
406 daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000407 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000408
Simon Kelley04918052015-01-26 11:23:43 +0000409#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000410 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
411 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000412 inotify_dnsmasq_init();
413 else
414 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000415#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100416
417 if (daemon->dump_file)
418#ifdef HAVE_DUMPFILE
419 dump_init();
420 else
421 daemon->dumpfd = -1;
422#else
423 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
424#endif
425
Simon Kelley28866e92011-02-14 20:19:14 +0000426 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100427#ifdef HAVE_DBUS
428 {
429 char *err;
430 daemon->dbus = NULL;
431 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100432 if ((err = dbus_init()))
433 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100434 }
435#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100436 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100437#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100438
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100439 if (option_bool(OPT_UBUS))
440#ifdef HAVE_UBUS
441 {
442 daemon->ubus = NULL;
443 ubus_init();
444 }
445#else
446 die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
447#endif
448
Simon Kelley824af852008-02-12 20:43:05 +0000449 if (daemon->port != 0)
450 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100451
Simon Kelleyc72daea2012-01-05 21:33:27 +0000452#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100453 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000454 if ((daemon->dhcp || daemon->dhcp6) &&
455 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000456 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100457 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000458 struct passwd *scr_pw;
459
460 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100461 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000462 script_uid = scr_pw->pw_uid;
463 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100464 }
465 else
466 baduser = daemon->scriptuser;
467 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100468#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000469
Simon Kelley1a6bca82008-07-11 11:11:42 +0100470 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
471 baduser = daemon->username;
472 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
473 baduser = daemon->groupname;
474
475 if (baduser)
476 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000477
Simon Kelley1a6bca82008-07-11 11:11:42 +0100478 /* implement group defaults, "dip" if available, or group associated with uid */
479 if (!daemon->group_set && !gp)
480 {
481 if (!(gp = getgrnam(CHGRP)) && ent_pw)
482 gp = getgrgid(ent_pw->pw_gid);
483
484 /* for error message */
485 if (gp)
486 daemon->groupname = gp->gr_name;
487 }
488
489#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000490 /* We keep CAP_NETADMIN (for ARP-injection) and
491 CAP_NET_RAW (for icmp) if we're doing dhcp,
492 if we have yet to bind ports because of DAD,
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100493 or we're doing it dynamically, we need CAP_NET_BIND_SERVICE. */
Simon Kelley305ffb52019-03-16 18:17:17 +0000494 if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
495 (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
496 need_cap_net_bind_service = 1;
497
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100498 /* usptream servers which bind to an interface call SO_BINDTODEVICE
Simon Kelleydefd6b12019-09-16 23:02:12 +0100499 for each TCP connection, so need CAP_NET_RAW */
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100500 for (serv = daemon->servers; serv; serv = serv->next)
501 if (serv->interface[0] != 0)
Simon Kelleydefd6b12019-09-16 23:02:12 +0100502 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100503
504 /* If we're doing Dbus or UBus, the above can be set dynamically,
505 (as can ports) so always (potentially) needed. */
506#ifdef HAVE_DBUS
507 if (option_bool(OPT_DBUS))
508 {
509 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100510 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100511 }
512#endif
513
514#ifdef HAVE_UBUS
515 if (option_bool(OPT_UBUS))
516 {
517 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100518 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100519 }
520#endif
521
Simon Kelley1a6bca82008-07-11 11:11:42 +0100522 /* determine capability API version here, while we can still
523 call safe_malloc */
Simon Kelley305ffb52019-03-16 18:17:17 +0000524 int capsize = 1; /* for header version 1 */
525 char *fail = NULL;
526
527 hdr = safe_malloc(sizeof(*hdr));
528
529 /* find version supported by kernel */
530 memset(hdr, 0, sizeof(*hdr));
531 capget(hdr, NULL);
532
533 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100534 {
Simon Kelley305ffb52019-03-16 18:17:17 +0000535 /* if unknown version, use largest supported version (3) */
536 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
537 hdr->version = LINUX_CAPABILITY_VERSION_3;
538 capsize = 2;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100539 }
Simon Kelley305ffb52019-03-16 18:17:17 +0000540
541 data = safe_malloc(sizeof(*data) * capsize);
542 capget(hdr, data); /* Get current values, for verification */
543
544 if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
545 fail = "NET_ADMIN";
546 else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
547 fail = "NET_RAW";
548 else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
549 fail = "NET_BIND_SERVICE";
550
551 if (fail)
552 die(_("process is missing required capability %s"), fail, EC_MISC);
553
554 /* Now set bitmaps to set caps after daemonising */
555 memset(data, 0, sizeof(*data) * capsize);
556
557 if (need_cap_net_admin)
558 data->effective |= (1 << CAP_NET_ADMIN);
559 if (need_cap_net_raw)
560 data->effective |= (1 << CAP_NET_RAW);
561 if (need_cap_net_bind_service)
562 data->effective |= (1 << CAP_NET_BIND_SERVICE);
563
564 data->permitted = data->effective;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100565#endif
566
Simon Kelley5aabfc72007-08-29 11:24:47 +0100567 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100568 in a race-free manner and another to carry errors to daemon-invoking process */
569 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100570
571 piperead = pipefd[0];
572 pipewrite = pipefd[1];
573 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000574 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100575
576 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100577
Simon Kelley28866e92011-02-14 20:19:14 +0000578 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000579 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000580 /* The following code "daemonizes" the process.
581 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100582
Simon Kelley9e038942008-05-30 20:06:34 +0100583 if (chdir("/") != 0)
584 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
585
Simon Kelley28866e92011-02-14 20:19:14 +0000586 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100587 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100588 pid_t pid;
589
Simon Kelley1a6bca82008-07-11 11:11:42 +0100590 /* pipe to carry errors back to original process.
591 When startup is complete we close this and the process terminates. */
592 safe_pipe(err_pipe, 0);
593
Simon Kelley7622fc02009-06-04 20:32:05 +0100594 if ((pid = fork()) == -1)
595 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000596 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100597
Simon Kelley5aabfc72007-08-29 11:24:47 +0100598 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100599 {
600 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000601 char *msg;
602
Simon Kelley1a6bca82008-07-11 11:11:42 +0100603 /* close our copy of write-end */
Simon Kelley5fc639c2019-03-29 21:29:43 +0000604 close(err_pipe[1]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100605
606 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000607 if (read_event(err_pipe[0], &ev, &msg))
608 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100609
610 _exit(EC_GOOD);
611 }
612
Simon Kelley5fc639c2019-03-29 21:29:43 +0000613 close(err_pipe[0]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100614
615 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100616
617 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100618
619 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000620 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100621
622 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100623 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100624 }
Simon Kelley9e038942008-05-30 20:06:34 +0100625
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000626 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100627 if (daemon->runfile)
628 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100629 int fd, err = 0;
630
631 sprintf(daemon->namebuff, "%d\n", (int) getpid());
632
633 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
634 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
635 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
636 extent that an attacker running as the unprivileged user could replace the pidfile with a
637 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
638
Josh Soref730c6742017-02-06 16:14:04 +0000639 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100640 ensuring that the open() fails should there be any existing file (because the unlink() failed,
641 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
642 attack can succeed.
643
644 Any compromise of the non-privileged user still theoretically allows the pid-file to be
645 replaced whilst dnsmasq is running. The worst that could allow is that the usual
646 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
647
648 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
649 failure to write the pid-file.
650 */
651
652 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100653
Simon Kelley79cfefd2012-09-02 13:29:51 +0100654 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 +0100655 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100656 /* only complain if started as root */
657 if (getuid() == 0)
658 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100659 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100660 else
661 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000662 /* We're still running as root here. Change the ownership of the PID file
663 to the user we will be running as. Note that this is not to allow
664 us to delete the file, since that depends on the permissions
665 of the directory containing the file. That directory will
666 need to by owned by the dnsmasq user, and the ownership of the
667 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000668 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
669 chown_warn = errno;
670
671 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100672 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000673 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000674 {
Simon Kelley5fc639c2019-03-29 21:29:43 +0000675 if (close(fd) == -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000676 err = 1;
677 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100678 }
679
680 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100681 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000682 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100683 _exit(0);
684 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000685 }
Simon Kelley16972692006-10-16 20:04:18 +0100686 }
687
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100688 log_err = log_start(ent_pw, err_pipe[1]);
689
Simon Kelley28866e92011-02-14 20:19:14 +0000690 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100691 {
692 /* open stdout etc to /dev/null */
693 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000694 if (nullfd != -1)
695 {
696 dup2(nullfd, STDOUT_FILENO);
697 dup2(nullfd, STDERR_FILENO);
698 dup2(nullfd, STDIN_FILENO);
699 close(nullfd);
700 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100701 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100702
Simon Kelley1a6bca82008-07-11 11:11:42 +0100703 /* if we are to run scripts, we need to fork a helper before dropping root. */
704 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000705#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000706 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000707 (daemon->lease_change_command || daemon->luascript))
708 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100709#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100710
Simon Kelley28866e92011-02-14 20:19:14 +0000711 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100712 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100713 int bad_capabilities = 0;
714 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100715
Josh Soref730c6742017-02-06 16:14:04 +0000716 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100717 if (gp &&
718 (setgroups(0, &dummy) == -1 ||
719 setgid(gp->gr_gid) == -1))
720 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000721 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100722 _exit(0);
723 }
724
Simon Kelley7cebd202006-05-06 14:13:33 +0100725 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100726 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100727#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000728 /* Need to be able to drop root. */
729 data->effective |= (1 << CAP_SETUID);
730 data->permitted |= (1 << CAP_SETUID);
Simon Kelley16972692006-10-16 20:04:18 +0100731 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000732 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100733 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100734
Simon Kelley7622fc02009-06-04 20:32:05 +0100735#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000736 /* http://developers.sun.com/solaris/articles/program_privileges.html */
737 priv_set_t *priv_set;
738
739 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
740 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
741 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
742 bad_capabilities = errno;
743
744 if (priv_set && bad_capabilities == 0)
745 {
746 priv_inverse(priv_set);
747
748 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
749 bad_capabilities = errno;
750 }
751
752 if (priv_set)
753 priv_freeset(priv_set);
754
Simon Kelley824af852008-02-12 20:43:05 +0000755#endif
756
Simon Kelley1a6bca82008-07-11 11:11:42 +0100757 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100758 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000759 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100760 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100761 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100762
763 /* finally drop root */
764 if (setuid(ent_pw->pw_uid) == -1)
765 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000766 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100767 _exit(0);
768 }
769
770#ifdef HAVE_LINUX_NETWORK
Simon Kelley305ffb52019-03-16 18:17:17 +0000771 data->effective &= ~(1 << CAP_SETUID);
772 data->permitted &= ~(1 << CAP_SETUID);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100773
Simon Kelley305ffb52019-03-16 18:17:17 +0000774 /* lose the setuid capability */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100775 if (capset(hdr, data) == -1)
776 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000777 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100778 _exit(0);
779 }
780#endif
781
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000782 }
Simon Kelley849a8352006-06-09 21:02:31 +0100783 }
Simon Kelley16972692006-10-16 20:04:18 +0100784
Simon Kelley16972692006-10-16 20:04:18 +0100785#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000786 free(hdr);
787 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000788 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000789 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100790#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100791
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100792#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100793 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100794 {
795 DIR *dir;
796 struct tftp_prefix *p;
797
798 if (daemon->tftp_prefix)
799 {
800 if (!((dir = opendir(daemon->tftp_prefix))))
801 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100802 tftp_prefix_missing = 1;
803 if (!option_bool(OPT_TFTP_NO_FAIL))
804 {
805 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
806 _exit(0);
807 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100808 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100809 else
810 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100811 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100812
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100813 for (p = daemon->if_prefix; p; p = p->next)
814 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100815 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100816 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100817 {
818 p->missing = 1;
819 if (!option_bool(OPT_TFTP_NO_FAIL))
820 {
821 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
822 _exit(0);
823 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100824 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100825 else
826 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100827 }
828 }
829#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100830
Simon Kelley824af852008-02-12 20:43:05 +0000831 if (daemon->port == 0)
832 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000833 else
834 {
835 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100836 {
837 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
838 if (daemon->cachesize > 10000)
839 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
840 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000841 else
842 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
843
844 if (option_bool(OPT_LOCAL_SERVICE))
845 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
846 }
Simon Kelley16972692006-10-16 20:04:18 +0100847
Simon Kelleyf2621c72007-04-29 19:47:21 +0100848 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000849
850 if (chown_warn != 0)
851 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100852
Simon Kelley3d8df262005-08-29 12:19:27 +0100853#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000854 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100855 {
856 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100857 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100858 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100859 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100860 }
861#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000862
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100863#ifdef HAVE_UBUS
864 if (option_bool(OPT_UBUS))
865 {
866 if (daemon->ubus)
867 my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
868 else
869 my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
870 }
871#endif
872
Simon Kelley1d97ac42014-01-31 11:12:27 +0000873#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000874 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000875 {
Simon Kelley360f2512015-03-07 18:28:06 +0000876 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100877 struct ds_config *ds;
878
Simon Kelley360f2512015-03-07 18:28:06 +0000879 /* Delay creating the timestamp file until here, after we've changed user, so that
880 it has the correct owner to allow updating the mtime later.
881 This means we have to report fatal errors via the pipe. */
882 if ((rc = setup_timestamp()) == -1)
883 {
884 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
885 _exit(0);
886 }
887
Simon Kelleya6918532018-04-15 16:20:52 +0100888 if (option_bool(OPT_DNSSEC_IGN_NS))
889 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
890 else
891 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000892
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100893 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
894 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000895 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000896
897 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000898 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100899
900 for (ds = daemon->ds; ds; ds = ds->next)
901 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
902 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000903 }
Simon Kelleydb737462014-01-31 10:32:45 +0000904#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100905
Simon Kelley1a6bca82008-07-11 11:11:42 +0100906 if (log_err != 0)
907 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
908 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000909
Simon Kelleyde379512004-06-22 20:23:33 +0100910 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100911 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100912
Simon Kelleyf7029f52013-11-21 15:09:09 +0000913 if (option_bool(OPT_NOWILD))
914 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000915 else if (!option_bool(OPT_CLEVERBIND))
916 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000917
918 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100919
Simon Kelley28866e92011-02-14 20:19:14 +0000920 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000921 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
922 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100923 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100924
Simon Kelley28866e92011-02-14 20:19:14 +0000925 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100926 {
927 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100928 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100929 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000930 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100931 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100932 }
933
Simon Kelleyf2621c72007-04-29 19:47:21 +0100934 if (daemon->max_logs != 0)
935 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000936
Simon Kelleyf2621c72007-04-29 19:47:21 +0100937
Simon Kelley7622fc02009-06-04 20:32:05 +0100938#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000939 for (context = daemon->dhcp; context; context = context->next)
940 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100941
Simon Kelleyff7eea22013-09-04 18:01:38 +0100942 for (relay = daemon->relay4; relay; relay = relay->next)
943 log_relay(AF_INET, relay);
944
Simon Kelley1f776932012-12-16 19:46:08 +0000945# ifdef HAVE_DHCP6
946 for (context = daemon->dhcp6; context; context = context->next)
947 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000948
Simon Kelleyff7eea22013-09-04 18:01:38 +0100949 for (relay = daemon->relay6; relay; relay = relay->next)
950 log_relay(AF_INET6, relay);
951
Simon Kelley1f776932012-12-16 19:46:08 +0000952 if (daemon->doing_dhcp6 || daemon->doing_ra)
953 dhcp_construct_contexts(now);
954
955 if (option_bool(OPT_RA))
956 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
957# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000958
Simon Kelley3b3f4412013-10-11 16:33:28 +0100959# ifdef HAVE_LINUX_NETWORK
960 if (did_bind)
961 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
Simon Kelley913fa152020-04-19 23:16:52 +0100962
963 if (netlink_warn)
964 my_syslog(LOG_WARNING, netlink_warn);
Simon Kelley3b3f4412013-10-11 16:33:28 +0100965# endif
966
Josh Soref730c6742017-02-06 16:14:04 +0000967 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000968 if (daemon->dhcp || daemon->doing_dhcp6)
969 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000970#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000971
Simon Kelley832af0b2007-01-21 20:01:28 +0000972#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000973 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100974 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100975 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000976
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000977 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100978 daemon->tftp_prefix ? _("root is ") : _("enabled"),
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000979 daemon->tftp_prefix ? daemon->tftp_prefix : "",
980 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "",
981 option_bool(OPT_SINGLE_PORT) ? _("single port mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100982
Stefan Tomanek30d08792015-03-31 22:32:11 +0100983 if (tftp_prefix_missing)
984 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100985
Stefan Tomanek30d08792015-03-31 22:32:11 +0100986 for (p = daemon->if_prefix; p; p = p->next)
987 if (p->missing)
988 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
989
Simon Kelley832af0b2007-01-21 20:01:28 +0000990 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100991 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000992 a single file will be sent to may clients (the file only needs
993 one fd). */
994
Simon Kelleyea28d0e2021-03-26 22:02:04 +0000995 max_fd -= 30 + daemon->numrrand; /* use other than TFTP */
Simon Kelley832af0b2007-01-21 20:01:28 +0000996
997 if (max_fd < 0)
998 max_fd = 5;
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000999 else if (max_fd < 100 && !option_bool(OPT_SINGLE_PORT))
Simon Kelley832af0b2007-01-21 20:01:28 +00001000 max_fd = max_fd/2;
1001 else
1002 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +00001003
1004 /* if we have to use a limited range of ports,
1005 that will limit the number of transfers */
1006 if (daemon->start_tftp_port != 0 &&
1007 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
1008 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001009
1010 if (daemon->tftp_max > max_fd)
1011 {
1012 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +01001013 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +01001014 _("restricting maximum simultaneous TFTP transfers to %d"),
1015 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +00001016 }
1017 }
1018#endif
1019
Simon Kelley1a6bca82008-07-11 11:11:42 +01001020 /* finished start-up - release original process */
1021 if (err_pipe[1] != -1)
Simon Kelley5fc639c2019-03-29 21:29:43 +00001022 close(err_pipe[1]);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001023
Simon Kelley824af852008-02-12 20:43:05 +00001024 if (daemon->port != 0)
1025 check_servers();
1026
Simon Kelley7cebd202006-05-06 14:13:33 +01001027 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +01001028
1029 daemon->pipe_to_parent = -1;
1030 for (i = 0; i < MAX_PROCS; i++)
1031 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +01001032
Simon Kelley04918052015-01-26 11:23:43 +00001033#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +00001034 /* Using inotify, have to select a resolv file at startup */
1035 poll_resolv(1, 0, now);
1036#endif
1037
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001038 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001039 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001040 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001041
Simon Kelleyb842bc92015-07-12 21:09:11 +01001042 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001043
Simon Kelley16972692006-10-16 20:04:18 +01001044 /* if we are out of resources, find how long we have to wait
1045 for some to come free, we'll loop around then and restart
1046 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001047 if ((t = set_dns_listeners(now)) != 0)
1048 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +01001049
Simon Kelley832af0b2007-01-21 20:01:28 +00001050 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
1051 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +00001052 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +01001053 timeout = 250;
1054
Simon Kelley74c95c22011-10-19 09:33:39 +01001055 /* Wake every second whilst waiting for DAD to complete */
1056 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001057 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001058
Simon Kelley832af0b2007-01-21 20:01:28 +00001059#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +01001060 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001061#endif
1062
1063#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001064 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001065 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001066#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001067
Simon Kelley7622fc02009-06-04 20:32:05 +01001068#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001069 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001070 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001071 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +00001072 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001073 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001074 }
Simon Kelley7622fc02009-06-04 20:32:05 +01001075#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001076
Simon Kelley52b92f42012-01-22 16:05:15 +00001077#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +01001078 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001079 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001080
Simon Kelley1f776932012-12-16 19:46:08 +00001081 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001082 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +00001083#endif
Simon Kelley04918052015-01-26 11:23:43 +00001084
1085#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001086 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001087 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +00001088#endif
1089
1090#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001091 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +00001092#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001093 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001094#endif
Simon Kelley193de4a2014-12-10 17:32:16 +00001095
Simon Kelleyb842bc92015-07-12 21:09:11 +01001096 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001097
Simon Kelley33702ab2015-12-28 23:17:15 +00001098#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001099# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001100 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001101# endif
1102
Simon Kelley1e505122016-01-25 21:29:23 +00001103 /* Refresh cache */
1104 if (option_bool(OPT_SCRIPT_ARP))
1105 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001106 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001107
Simon Kelleya9530962012-03-20 22:07:35 +00001108# ifdef HAVE_TFTP
1109 while (helper_buf_empty() && do_tftp_script_run());
1110# endif
1111
Simon Kelley16972692006-10-16 20:04:18 +01001112 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001113 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001114#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001115 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001116# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001117 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001118# endif
1119
Simon Kelleyb633de92016-01-06 22:51:17 +00001120 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001121
1122# ifdef HAVE_TFTP
1123 while (do_tftp_script_run());
1124# endif
1125
Simon Kelley5aabfc72007-08-29 11:24:47 +01001126#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001127
Simon Kelley7622fc02009-06-04 20:32:05 +01001128
Simon Kelley66f62652020-01-05 16:21:24 +00001129 /* must do this just before do_poll(), when we know no
Simon Kelleyf2621c72007-04-29 19:47:21 +01001130 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001131 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001132
Simon Kelleyb842bc92015-07-12 21:09:11 +01001133 if (do_poll(timeout) < 0)
1134 continue;
1135
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001136 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001137
Simon Kelleyb842bc92015-07-12 21:09:11 +01001138 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001139
1140 /* prime. */
1141 enumerate_interfaces(1);
1142
Simon Kelley74c95c22011-10-19 09:33:39 +01001143 /* Check the interfaces to see if any have exited DAD state
1144 and if so, bind the address. */
1145 if (is_dad_listeners())
1146 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001147 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001148 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1149 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001150 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001151 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001152
Simon Kelley1ee9be42013-12-09 16:50:19 +00001153#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001154 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001155 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001156#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001157 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001158 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001159#endif
1160
Simon Kelley04918052015-01-26 11:23:43 +00001161#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001162 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001163 {
1164 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1165 poll_resolv(1, 1, now);
1166 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001167#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001168 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001169 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001170 if (daemon->last_resolv == 0 ||
1171 difftime(now, daemon->last_resolv) > 1.0 ||
1172 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001173 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001174 /* poll_resolv doesn't need to reload first time through, since
1175 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001176
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001177 poll_resolv(0, daemon->last_resolv != 0, now);
1178 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001179 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001180#endif
1181
Simon Kelleyb842bc92015-07-12 21:09:11 +01001182 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001183 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001184
Simon Kelley3d8df262005-08-29 12:19:27 +01001185#ifdef HAVE_DBUS
1186 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001187 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001188 {
1189 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001190 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001191 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001192 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001193 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001194 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001195 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001196#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001197
1198#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001199 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001200 {
1201 /* if we didn't create a UBus connection, retry now. */
1202 if (!daemon->ubus)
1203 {
1204 ubus_init();
1205 }
1206
1207 check_ubus_listeners();
1208 }
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001209#endif
1210
Simon Kelleyb842bc92015-07-12 21:09:11 +01001211 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001212
1213#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001214 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001215#endif
1216
Simon Kelley7622fc02009-06-04 20:32:05 +01001217#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001218 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001219 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001220 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001221 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001222 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001223 dhcp_packet(now, 1);
1224 }
Simon Kelley16972692006-10-16 20:04:18 +01001225
Simon Kelley52b92f42012-01-22 16:05:15 +00001226#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001227 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001228 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001229
Simon Kelleyb842bc92015-07-12 21:09:11 +01001230 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001231 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001232#endif
1233
Simon Kelley1f15b812009-10-13 17:49:32 +01001234# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001235 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001236 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001237# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001238#endif
1239
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001240 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001241}
1242
Simon Kelley3be34542004-09-11 19:12:13 +01001243static void sig_handler(int sig)
1244{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001245 if (pid == 0)
1246 {
Simon Kelley16972692006-10-16 20:04:18 +01001247 /* ignore anything other than TERM during startup
1248 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001249 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001250 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001251 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001252 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001253 {
Simon Kelley16972692006-10-16 20:04:18 +01001254 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001255 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001256 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001257 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001258 else
1259 {
1260 /* master process */
1261 int event, errsave = errno;
1262
1263 if (sig == SIGHUP)
1264 event = EVENT_RELOAD;
1265 else if (sig == SIGCHLD)
1266 event = EVENT_CHILD;
1267 else if (sig == SIGALRM)
1268 event = EVENT_ALARM;
1269 else if (sig == SIGTERM)
1270 event = EVENT_TERM;
1271 else if (sig == SIGUSR1)
1272 event = EVENT_DUMP;
1273 else if (sig == SIGUSR2)
1274 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001275 else if (sig == SIGINT)
1276 {
1277 /* Handle SIGINT normally in debug mode, so
1278 ctrl-c continues to operate. */
1279 if (option_bool(OPT_DEBUG))
1280 exit(EC_MISC);
1281 else
1282 event = EVENT_TIME;
1283 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001284 else
1285 return;
1286
Simon Kelleyc72daea2012-01-05 21:33:27 +00001287 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001288 errno = errsave;
1289 }
Simon Kelley3be34542004-09-11 19:12:13 +01001290}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001291
Simon Kelley353ae4d2012-03-19 20:07:51 +00001292/* now == 0 -> queue immediate callback */
1293void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001294{
Simon Kelley884a6df2012-03-20 16:20:22 +00001295 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001296 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001297 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1298 if ((now == 0 || difftime(event, now) <= 0.0))
1299 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1300 else
1301 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001302 }
Simon Kelley741c2952012-02-25 13:09:18 +00001303}
1304
Simon Kelley47a95162014-07-08 22:22:02 +01001305void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001306{
Simon Kelley47a95162014-07-08 22:22:02 +01001307 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001308}
1309
Simon Kelleyc72daea2012-01-05 21:33:27 +00001310void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001311{
1312 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001313 struct iovec iov[2];
1314
Simon Kelley5aabfc72007-08-29 11:24:47 +01001315 ev.event = event;
1316 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001317 ev.msg_sz = msg ? strlen(msg) : 0;
1318
1319 iov[0].iov_base = &ev;
1320 iov[0].iov_len = sizeof(ev);
1321 iov[1].iov_base = msg;
1322 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001323
1324 /* error pipe, debug mode. */
1325 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001326 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001327 else
1328 /* pipe is non-blocking and struct event_desc is smaller than
1329 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001330 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001331}
Simon Kelley3d8df262005-08-29 12:19:27 +01001332
Simon Kelleyc72daea2012-01-05 21:33:27 +00001333/* NOTE: the memory used to return msg is leaked: use msgs in events only
1334 to describe fatal errors. */
1335static int read_event(int fd, struct event_desc *evp, char **msg)
1336{
1337 char *buf;
1338
1339 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1340 return 0;
1341
1342 *msg = NULL;
1343
1344 if (evp->msg_sz != 0 &&
1345 (buf = malloc(evp->msg_sz + 1)) &&
1346 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1347 {
1348 buf[evp->msg_sz] = 0;
1349 *msg = buf;
1350 }
1351
1352 return 1;
1353}
1354
1355static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001356{
1357 errno = ev->data;
1358
1359 switch (ev->event)
1360 {
1361 case EVENT_DIE:
1362 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001363
1364 case EVENT_FORK_ERR:
1365 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001366
1367 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001368 case EVENT_PIPE_ERR:
1369 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001370
1371 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001372 case EVENT_CAP_ERR:
1373 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1374
Simon Kelleye7a4af82018-02-16 21:27:35 +00001375 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001376 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001377 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001378
Simon Kelleye7a4af82018-02-16 21:27:35 +00001379 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001380 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001381 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001382
1383 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001384 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001385 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001386
Simon Kelleye7a4af82018-02-16 21:27:35 +00001387 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001388 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001389 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001390
1391 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001392 case EVENT_LUA_ERR:
1393 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001394
Simon Kelleye7a4af82018-02-16 21:27:35 +00001395 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001396 case EVENT_TFTP_ERR:
1397 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001398
1399 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001400 case EVENT_TIME_ERR:
1401 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001402 }
1403}
1404
Simon Kelley5aabfc72007-08-29 11:24:47 +01001405static void async_event(int pipe, time_t now)
1406{
1407 pid_t p;
1408 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001409 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001410 char *msg;
1411
1412 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1413 to describe fatal errors. */
1414
1415 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001416 switch (ev.event)
1417 {
1418 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001419 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001420
Simon Kelleye98bd522014-03-28 20:41:23 +00001421 /* fall through */
1422
1423 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001424 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001425
Simon Kelley7b1eae42014-02-20 13:43:28 +00001426 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001427 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001428 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1429 {
1430 reload_servers(daemon->resolv_files->name);
1431 check = 1;
1432 }
1433
1434 if (daemon->servers_file)
1435 {
1436 read_servers_file();
1437 check = 1;
1438 }
1439
1440 if (check)
1441 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001442 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001443
Simon Kelley7622fc02009-06-04 20:32:05 +01001444#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001445 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001446#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001447 break;
1448
1449 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001450 if (daemon->port != 0)
Kyle Swenson545712c2021-11-17 12:25:04 -07001451/* CRADLEPOINT */
1452 dump_cache_json(now);
1453/* CRADLEPOINT */
1454
Simon Kelley5aabfc72007-08-29 11:24:47 +01001455 break;
1456
1457 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001458#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001459 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001460 {
1461 lease_prune(NULL, now);
1462 lease_update_file(now);
1463 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001464#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001465 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001466 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1467 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001468#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001469#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001470 break;
1471
1472 case EVENT_CHILD:
1473 /* See Stevens 5.10 */
1474 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1475 if (p == -1)
1476 {
1477 if (errno != EINTR)
1478 break;
1479 }
1480 else
1481 for (i = 0 ; i < MAX_PROCS; i++)
1482 if (daemon->tcp_pids[i] == p)
1483 daemon->tcp_pids[i] = 0;
1484 break;
1485
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001486#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001487 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001488 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001489 break;
1490
1491 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001492 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001493 break;
1494
1495 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001496 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1497 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001498 break;
1499
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001500 case EVENT_SCRIPT_LOG:
1501 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1502 free(msg);
1503 msg = NULL;
1504 break;
1505
Simon Kelley1a6bca82008-07-11 11:11:42 +01001506 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001507 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001508 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001509 case EVENT_LUA_ERR:
1510 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001511 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001512#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001513
Simon Kelley5aabfc72007-08-29 11:24:47 +01001514 case EVENT_REOPEN:
1515 /* Note: this may leave TCP-handling processes with the old file still open.
1516 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1517 we leave them logging to the old file. */
1518 if (daemon->log_file != NULL)
1519 log_reopen(daemon->log_file);
1520 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001521
1522 case EVENT_NEWADDR:
1523 newaddress(now);
1524 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001525
1526 case EVENT_NEWROUTE:
1527 resend_query();
1528 /* Force re-reading resolv file right now, for luck. */
1529 poll_resolv(0, 1, now);
1530 break;
1531
Simon Kelley3c973ad2018-01-14 21:05:37 +00001532 case EVENT_TIME:
1533#ifdef HAVE_DNSSEC
1534 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1535 {
1536 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1537 daemon->dnssec_no_time_check = 0;
1538 clear_cache_and_reload(now);
1539 }
1540#endif
1541 break;
1542
Simon Kelley5aabfc72007-08-29 11:24:47 +01001543 case EVENT_TERM:
1544 /* Knock all our children on the head. */
1545 for (i = 0; i < MAX_PROCS; i++)
1546 if (daemon->tcp_pids[i] != 0)
1547 kill(daemon->tcp_pids[i], SIGALRM);
1548
Simon Kelley53a91732016-01-06 17:59:13 +00001549#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001550 /* handle pending lease transitions */
1551 if (daemon->helperfd != -1)
1552 {
1553 /* block in writes until all done */
1554 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1555 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1556 do {
1557 helper_write();
1558 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelley5fc639c2019-03-29 21:29:43 +00001559 close(daemon->helperfd);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001560 }
1561#endif
1562
1563 if (daemon->lease_stream)
1564 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001565
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001566#ifdef HAVE_DNSSEC
1567 /* update timestamp file on TERM if time is considered valid */
1568 if (daemon->back_to_the_future)
1569 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001570 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001571 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1572 }
1573#endif
1574
Simon Kelley73a08a22009-02-05 20:28:08 +00001575 if (daemon->runfile)
1576 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001577
1578#ifdef HAVE_DUMPFILE
1579 if (daemon->dumpfd != -1)
1580 close(daemon->dumpfd);
1581#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001582
1583 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1584 flush_log();
1585 exit(EC_GOOD);
1586 }
1587}
1588
Simon Kelley47a95162014-07-08 22:22:02 +01001589static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001590{
1591 struct resolvc *res, *latest;
1592 struct stat statbuf;
1593 time_t last_change = 0;
1594 /* There may be more than one possible file.
1595 Go through and find the one which changed _last_.
1596 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001597
Simon Kelley28866e92011-02-14 20:19:14 +00001598 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001599 return;
1600
Simon Kelley5aabfc72007-08-29 11:24:47 +01001601 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1602 if (stat(res->name, &statbuf) == -1)
1603 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001604 if (force)
1605 {
1606 res->mtime = 0;
1607 continue;
1608 }
1609
Simon Kelley5aabfc72007-08-29 11:24:47 +01001610 if (!res->logged)
1611 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1612 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001613
1614 if (res->mtime != 0)
1615 {
1616 /* existing file evaporated, force selection of the latest
1617 file even if its mtime hasn't changed since we last looked */
1618 poll_resolv(1, do_reload, now);
1619 return;
1620 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001621 }
1622 else
1623 {
1624 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001625 if (force || (statbuf.st_mtime != res->mtime))
1626 {
1627 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001628 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1629 {
1630 last_change = statbuf.st_mtime;
1631 latest = res;
1632 }
1633 }
1634 }
1635
1636 if (latest)
1637 {
1638 static int warned = 0;
1639 if (reload_servers(latest->name))
1640 {
1641 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1642 warned = 0;
1643 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001644 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001645 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001646 }
1647 else
1648 {
1649 latest->mtime = 0;
1650 if (!warned)
1651 {
1652 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1653 warned = 1;
1654 }
1655 }
1656 }
1657}
1658
1659void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001660{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001661 (void)now;
1662
Simon Kelley824af852008-02-12 20:43:05 +00001663 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001664 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001665
Simon Kelley7622fc02009-06-04 20:32:05 +01001666#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001667 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001668 {
Simon Kelley28866e92011-02-14 20:19:14 +00001669 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001670 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001671 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001672 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001673 lease_update_from_configs();
1674 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001675 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001676 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001677#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001678 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001679 /* Not doing DHCP, so no lease system, manage
1680 alarms for ra only */
1681 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001682#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001683#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001684}
1685
Simon Kelleyb842bc92015-07-12 21:09:11 +01001686static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001687{
1688 struct serverfd *serverfdp;
1689 struct listener *listener;
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001690 struct randfd_list *rfl;
Simon Kelley824af852008-02-12 20:43:05 +00001691 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001692
1693#ifdef HAVE_TFTP
1694 int tftp = 0;
1695 struct tftp_transfer *transfer;
Simon Kelley66f62652020-01-05 16:21:24 +00001696 if (!option_bool(OPT_SINGLE_PORT))
1697 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1698 {
1699 tftp++;
1700 poll_listen(transfer->sockfd, POLLIN);
1701 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001702#endif
1703
Simon Kelley16972692006-10-16 20:04:18 +01001704 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001705 if (daemon->port != 0)
Simon Kelley8caf3d72020-04-04 17:00:32 +01001706 get_new_frec(now, &wait, NULL);
Simon Kelley16972692006-10-16 20:04:18 +01001707
Simon Kelley3be34542004-09-11 19:12:13 +01001708 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001709 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001710
Simon Kelleyea28d0e2021-03-26 22:02:04 +00001711 for (i = 0; i < daemon->numrrand; i++)
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001712 if (daemon->randomsocks[i].refcount != 0)
1713 poll_listen(daemon->randomsocks[i].fd, POLLIN);
1714
1715 /* Check overflow random sockets too. */
1716 for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
1717 poll_listen(rfl->rfd->fd, POLLIN);
1718
Simon Kelley3be34542004-09-11 19:12:13 +01001719 for (listener = daemon->listeners; listener; listener = listener->next)
1720 {
Simon Kelley16972692006-10-16 20:04:18 +01001721 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001722 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001723 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001724
Simon Kelley16972692006-10-16 20:04:18 +01001725 /* death of a child goes through the select loop, so
1726 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001727 if (listener->tcpfd != -1)
1728 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001729 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001730 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001731 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001732 break;
1733 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001734
Simon Kelley832af0b2007-01-21 20:01:28 +00001735#ifdef HAVE_TFTP
Simon Kelley2ac4cf02020-01-06 23:39:33 +00001736 /* tftp == 0 in single-port mode. */
Simon Kelley832af0b2007-01-21 20:01:28 +00001737 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001738 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001739#endif
1740
1741 }
1742
Simon Kelleya799ca02018-10-18 19:35:29 +01001743 if (!option_bool(OPT_DEBUG))
1744 for (i = 0; i < MAX_PROCS; i++)
1745 if (daemon->tcp_pipes[i] != -1)
1746 poll_listen(daemon->tcp_pipes[i], POLLIN);
Simon Kelleya799ca02018-10-18 19:35:29 +01001747
Simon Kelley16972692006-10-16 20:04:18 +01001748 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001749}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001750
Simon Kelleyb842bc92015-07-12 21:09:11 +01001751static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001752{
1753 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001754 struct listener *listener;
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001755 struct randfd_list *rfl;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001756 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001757 int pipefd[2];
Simon Kelleya799ca02018-10-18 19:35:29 +01001758
Simon Kelley832af0b2007-01-21 20:01:28 +00001759 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001760 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001761 reply_query(serverfdp->fd, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001762
Simon Kelleyea28d0e2021-03-26 22:02:04 +00001763 for (i = 0; i < daemon->numrrand; i++)
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001764 if (daemon->randomsocks[i].refcount != 0 &&
1765 poll_check(daemon->randomsocks[i].fd, POLLIN))
1766 reply_query(daemon->randomsocks[i].fd, now);
1767
1768 /* Check overflow random sockets too. */
1769 for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
1770 if (poll_check(rfl->rfd->fd, POLLIN))
1771 reply_query(rfl->rfd->fd, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001772
Simon Kelleya799ca02018-10-18 19:35:29 +01001773 /* Races. The child process can die before we read all of the data from the
1774 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1775 process, and tcp_pipes to -1 and close the FD when we read the last
1776 of the data - indicated by cache_recv_insert returning zero.
1777 The order of these events is indeterminate, and both are needed
1778 to free the process slot. Once the child process has gone, poll()
1779 returns POLLHUP, not POLLIN, so have to check for both here. */
1780 if (!option_bool(OPT_DEBUG))
1781 for (i = 0; i < MAX_PROCS; i++)
1782 if (daemon->tcp_pipes[i] != -1 &&
1783 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1784 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1785 {
1786 close(daemon->tcp_pipes[i]);
1787 daemon->tcp_pipes[i] = -1;
1788 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001789
Simon Kelley832af0b2007-01-21 20:01:28 +00001790 for (listener = daemon->listeners; listener; listener = listener->next)
1791 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001792 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001793 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001794
Simon Kelley832af0b2007-01-21 20:01:28 +00001795#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001796 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001797 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001798#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001799
Simon Kelleyb842bc92015-07-12 21:09:11 +01001800 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001801 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001802 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001803 struct irec *iface = NULL;
1804 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001805 union mysockaddr tcp_addr;
1806 socklen_t tcp_len = sizeof(union mysockaddr);
1807
1808 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001809
Simon Kelley46b06652013-02-04 21:47:59 +00001810 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001811 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001812
Simon Kelley46b06652013-02-04 21:47:59 +00001813 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1814 {
Simon Kelley5fc639c2019-03-29 21:29:43 +00001815 close(confd);
Simon Kelley46b06652013-02-04 21:47:59 +00001816 continue;
1817 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001818
1819 /* Make sure that the interface list is up-to-date.
1820
1821 We do this here as we may need the results below, and
1822 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001823
Simon Kelley76dd75d2013-05-23 10:04:25 +01001824 Multiple calls to enumerate_interfaces() per select loop are
1825 inhibited, so calls to it in the child process (which doesn't select())
1826 have no effect. This avoids two processes reading from the same
1827 netlink fd and screwing the pooch entirely.
1828 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001829
Simon Kelley76dd75d2013-05-23 10:04:25 +01001830 enumerate_interfaces(0);
1831
1832 if (option_bool(OPT_NOWILD))
1833 iface = listener->iface; /* May be NULL */
1834 else
1835 {
1836 int if_index;
1837 char intr_name[IF_NAMESIZE];
1838
1839 /* if we can find the arrival interface, check it's one that's allowed */
1840 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1841 indextoname(listener->tcpfd, if_index, intr_name))
1842 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001843 union all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001844
Simon Kelley76dd75d2013-05-23 10:04:25 +01001845 if (tcp_addr.sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001846 addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001847 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001848 addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001849
1850 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Mensik951a2212019-07-03 17:02:16 +02001851 if (iface->index == if_index &&
1852 iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
Simon Kelley76dd75d2013-05-23 10:04:25 +01001853 break;
1854
1855 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1856 client_ok = 0;
1857 }
1858
1859 if (option_bool(OPT_CLEVERBIND))
1860 iface = listener->iface; /* May be NULL */
1861 else
1862 {
1863 /* Check for allowed interfaces when binding the wildcard address:
1864 we do this by looking for an interface with the same address as
1865 the local address of the TCP connection, then looking to see if that's
1866 an allowed interface. As a side effect, we get the netmask of the
1867 interface too, for localisation. */
1868
1869 for (iface = daemon->interfaces; iface; iface = iface->next)
1870 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1871 break;
1872
1873 if (!iface)
1874 client_ok = 0;
1875 }
1876 }
1877
Simon Kelley22ce5502013-01-22 13:53:04 +00001878 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001879 {
1880 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001881 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001882 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001883 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001884 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001885 close(pipefd[1]); /* parent needs read pipe end. */
1886 if (p == -1)
1887 close(pipefd[0]);
1888 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001889 {
1890 int i;
Simon Kelleye2cb6552020-06-20 22:30:12 +01001891#ifdef HAVE_LINUX_NETWORK
1892 /* The child process inherits the netlink socket,
1893 which it never uses, but when the parent (us)
1894 uses it in the future, the answer may go to the
1895 child, resulting in the parent blocking
1896 forever awaiting the result. To avoid this
1897 the child closes the netlink socket, but there's
1898 a nasty race, since the parent may use netlink
1899 before the child has done the close.
1900
1901 To avoid this, the parent blocks here until a
1902 single byte comes back up the pipe, which
1903 is sent by the child after it has closed the
1904 netlink socket. */
1905
1906 unsigned char a;
1907 read_write(pipefd[0], &a, 1, 1);
1908#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001909
Simon Kelley832af0b2007-01-21 20:01:28 +00001910 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001911 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001912 {
1913 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001914 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley832af0b2007-01-21 20:01:28 +00001915 break;
1916 }
1917 }
Simon Kelley5fc639c2019-03-29 21:29:43 +00001918 close(confd);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001919
1920 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1921 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001922 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001923 else
1924 {
1925 unsigned char *buff;
1926 struct server *s;
1927 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001928 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001930
Simon Kelley52d4abf2012-03-21 21:39:48 +00001931 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001932 {
1933 netmask = iface->netmask;
1934 auth_dns = iface->dns_auth;
1935 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001936 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001937 {
1938 netmask.s_addr = 0;
1939 auth_dns = 0;
1940 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001941
Josh Soref730c6742017-02-06 16:14:04 +00001942 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001943 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001944 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001945 {
Simon Kelleye2cb6552020-06-20 22:30:12 +01001946#ifdef HAVE_LINUX_NETWORK
1947 /* See comment above re: netlink socket. */
1948 unsigned char a = 0;
1949
1950 close(daemon->netlinkfd);
1951 read_write(pipefd[1], &a, 1, 0);
1952#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001953 alarm(CHILD_LIFETIME);
1954 close(pipefd[0]); /* close read end in child. */
1955 daemon->pipe_to_parent = pipefd[1];
1956 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001957
Simon Kelley832af0b2007-01-21 20:01:28 +00001958 /* start with no upstream connections. */
1959 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001960 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001961
1962 /* The connected socket inherits non-blocking
1963 attribute from the listening socket.
1964 Reset that here. */
1965 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1966 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1967
Simon Kelley4f7b3042012-11-28 21:27:02 +00001968 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001969
Simon Kelley832af0b2007-01-21 20:01:28 +00001970 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001971 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001972
1973 if (buff)
1974 free(buff);
1975
1976 for (s = daemon->servers; s; s = s->next)
1977 if (s->tcpfd != -1)
1978 {
1979 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001980 close(s->tcpfd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001981 }
Simon Kelleye2cb6552020-06-20 22:30:12 +01001982
Simon Kelley28866e92011-02-14 20:19:14 +00001983 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001984 {
Simon Kelleye2cb6552020-06-20 22:30:12 +01001985 close(daemon->pipe_to_parent);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001986 flush_log();
1987 _exit(0);
1988 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001989 }
1990 }
1991 }
Simon Kelley3be34542004-09-11 19:12:13 +01001992}
1993
Simon Kelley7622fc02009-06-04 20:32:05 +01001994#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001995int make_icmp_sock(void)
1996{
Simon Kelley7cebd202006-05-06 14:13:33 +01001997 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001998 int zeroopt = 0;
1999
2000 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
2001 {
Simon Kelley7cebd202006-05-06 14:13:33 +01002002 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002003 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
2004 {
2005 close(fd);
2006 fd = -1;
2007 }
2008 }
2009
2010 return fd;
2011}
2012
Simon Kelley5aabfc72007-08-29 11:24:47 +01002013int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01002014{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002015 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01002016
Floris Bos503c6092017-04-09 23:07:13 +01002017 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01002018 struct sockaddr_in saddr;
2019 struct {
2020 struct ip ip;
2021 struct icmp icmp;
2022 } packet;
2023 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01002024 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002025 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002026
Simon Kelley824af852008-02-12 20:43:05 +00002027#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002028 if ((fd = make_icmp_sock()) == -1)
2029 return 0;
2030#else
2031 int opt = 2000;
2032 fd = daemon->dhcp_icmp_fd;
2033 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2034#endif
2035
Simon Kelley3be34542004-09-11 19:12:13 +01002036 saddr.sin_family = AF_INET;
2037 saddr.sin_port = 0;
2038 saddr.sin_addr = addr;
2039#ifdef HAVE_SOCKADDR_SA_LEN
2040 saddr.sin_len = sizeof(struct sockaddr_in);
2041#endif
2042
2043 memset(&packet.icmp, 0, sizeof(packet.icmp));
2044 packet.icmp.icmp_type = ICMP_ECHO;
2045 packet.icmp.icmp_id = id;
2046 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
2047 j += ((u16 *)&packet.icmp)[i];
2048 while (j>>16)
2049 j = (j & 0xffff) + (j >> 16);
2050 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
2051
Simon Kelleyff841eb2015-03-11 21:36:30 +00002052 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
2053 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002054
Floris Bos503c6092017-04-09 23:07:13 +01002055 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
2056
2057#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelley5fc639c2019-03-29 21:29:43 +00002058 close(fd);
Floris Bos503c6092017-04-09 23:07:13 +01002059#else
2060 opt = 1;
2061 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2062#endif
2063
2064 return gotreply;
2065}
2066
2067int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
2068{
2069 /* Delay processing DHCP packets for "sec" seconds counting from "start".
2070 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
2071 from "addr" with ICMP ID "id" and return 1 */
2072
2073 /* Note that whilst waiting, we check for
2074 (and service) events on the DNS and TFTP sockets, (so doing that
2075 better not use any resources our caller has in use...)
2076 but we remain deaf to signals or further DHCP packets. */
2077
2078 /* There can be a problem using dnsmasq_time() to end the loop, since
2079 it's not monotonic, and can go backwards if the system clock is
2080 tweaked, leading to the code getting stuck in this loop and
2081 ignoring DHCP requests. To fix this, we check to see if select returned
2082 as a result of a timeout rather than a socket becoming available. We
2083 only allow this to happen as many times as it takes to get to the wait time
2084 in quarter-second chunks. This provides a fallback way to end loop. */
2085
2086 int rc, timeout_count;
2087 time_t now;
2088
2089 for (now = dnsmasq_time(), timeout_count = 0;
2090 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002091 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01002092 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01002093 if (fd != -1)
2094 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01002095 set_dns_listeners(now);
2096 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002097
2098#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00002099 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002100 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002101#endif
2102
Simon Kelleyb842bc92015-07-12 21:09:11 +01002103 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01002104
2105 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002106 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01002107 else if (rc == 0)
2108 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01002109
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002110 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01002111
Simon Kelleyb842bc92015-07-12 21:09:11 +01002112 check_log_writer(0);
2113 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01002114
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002115#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01002116 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00002117 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002118#endif
2119
Simon Kelley832af0b2007-01-21 20:01:28 +00002120#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01002121 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00002122#endif
2123
Floris Bos503c6092017-04-09 23:07:13 +01002124 if (fd != -1)
2125 {
2126 struct {
2127 struct ip ip;
2128 struct icmp icmp;
2129 } packet;
2130 struct sockaddr_in faddr;
2131 socklen_t len = sizeof(faddr);
2132
2133 if (poll_check(fd, POLLIN) &&
2134 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
2135 addr == faddr.sin_addr.s_addr &&
2136 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
2137 packet.icmp.icmp_seq == 0 &&
2138 packet.icmp.icmp_id == id)
2139 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002140 }
2141 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002142
Floris Bos503c6092017-04-09 23:07:13 +01002143 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01002144}
Geert Stappersba26d342020-04-06 15:42:39 +01002145#endif /* HAVE_DHCP */