blob: fa9ae15ac0aaa7915b653d2219d988822aff6165 [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
328 if (daemon->ipsets)
Simon Kelley305ffb52019-03-16 18:17:17 +0000329 {
330 ipset_init();
331# ifdef HAVE_LINUX_NETWORK
332 need_cap_net_admin = 1;
333# endif
334 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000335#endif
336
Simon Kelley1ee9be42013-12-09 16:50:19 +0000337#if defined(HAVE_LINUX_NETWORK)
Simon Kelley913fa152020-04-19 23:16:52 +0100338 netlink_warn = netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000339#elif defined(HAVE_BSD_NETWORK)
340 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000341#endif
342
Simon Kelley1ee9be42013-12-09 16:50:19 +0000343 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
344 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
345
Simon Kelley115ac3e2013-05-20 11:28:32 +0100346 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100347 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000348
Simon Kelley54dd3932012-06-20 11:23:38 +0100349 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100350 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100351 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100352
353 if (!option_bool(OPT_CLEVERBIND))
354 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
355 if (if_tmp->name && !if_tmp->used)
356 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100357
358#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
359 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100360 bound_device = whichdevice();
361
Simon Kelley9380ba72012-04-16 14:41:56 +0100362 if (daemon->dhcp)
363 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100364 if (!daemon->relay4 && bound_device)
365 {
366 bindtodevice(bound_device, daemon->dhcpfd);
367 did_bind = 1;
368 }
369 if (daemon->enable_pxe && bound_device)
370 {
371 bindtodevice(bound_device, daemon->pxefd);
372 did_bind = 1;
373 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100374 }
375#endif
376
377#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100378 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
379 {
380 bindtodevice(bound_device, daemon->dhcp6fd);
381 did_bind = 1;
382 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100383#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100384 }
Simon Kelley28866e92011-02-14 20:19:14 +0000385 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100386 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000387
388#ifdef HAVE_DHCP6
389 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100390 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000391 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000392
393 /* After netlink_init() and before create_helper() */
394 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000395#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100396
Simon Kelley824af852008-02-12 20:43:05 +0000397 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000398 {
399 cache_init();
Simon Kelley82e3f452014-01-31 21:05:48 +0000400 blockdata_init();
Simon Kelleye75069f2021-01-22 22:50:25 +0000401 hash_questions_init();
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000402 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000403
Simon Kelley04918052015-01-26 11:23:43 +0000404#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000405 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
406 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000407 inotify_dnsmasq_init();
408 else
409 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000410#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100411
412 if (daemon->dump_file)
413#ifdef HAVE_DUMPFILE
414 dump_init();
415 else
416 daemon->dumpfd = -1;
417#else
418 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
419#endif
420
Simon Kelley28866e92011-02-14 20:19:14 +0000421 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100422#ifdef HAVE_DBUS
423 {
424 char *err;
425 daemon->dbus = NULL;
426 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100427 if ((err = dbus_init()))
428 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100429 }
430#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100431 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100432#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100433
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100434 if (option_bool(OPT_UBUS))
435#ifdef HAVE_UBUS
436 {
437 daemon->ubus = NULL;
438 ubus_init();
439 }
440#else
441 die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
442#endif
443
Simon Kelley824af852008-02-12 20:43:05 +0000444 if (daemon->port != 0)
445 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100446
Simon Kelleyc72daea2012-01-05 21:33:27 +0000447#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100448 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000449 if ((daemon->dhcp || daemon->dhcp6) &&
450 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000451 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100452 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000453 struct passwd *scr_pw;
454
455 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100456 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000457 script_uid = scr_pw->pw_uid;
458 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100459 }
460 else
461 baduser = daemon->scriptuser;
462 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100463#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000464
Simon Kelley1a6bca82008-07-11 11:11:42 +0100465 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
466 baduser = daemon->username;
467 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
468 baduser = daemon->groupname;
469
470 if (baduser)
471 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000472
Simon Kelley1a6bca82008-07-11 11:11:42 +0100473 /* implement group defaults, "dip" if available, or group associated with uid */
474 if (!daemon->group_set && !gp)
475 {
476 if (!(gp = getgrnam(CHGRP)) && ent_pw)
477 gp = getgrgid(ent_pw->pw_gid);
478
479 /* for error message */
480 if (gp)
481 daemon->groupname = gp->gr_name;
482 }
483
484#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000485 /* We keep CAP_NETADMIN (for ARP-injection) and
486 CAP_NET_RAW (for icmp) if we're doing dhcp,
487 if we have yet to bind ports because of DAD,
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100488 or we're doing it dynamically, we need CAP_NET_BIND_SERVICE. */
Simon Kelley305ffb52019-03-16 18:17:17 +0000489 if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
490 (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
491 need_cap_net_bind_service = 1;
492
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100493 /* usptream servers which bind to an interface call SO_BINDTODEVICE
Simon Kelleydefd6b12019-09-16 23:02:12 +0100494 for each TCP connection, so need CAP_NET_RAW */
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100495 for (serv = daemon->servers; serv; serv = serv->next)
496 if (serv->interface[0] != 0)
Simon Kelleydefd6b12019-09-16 23:02:12 +0100497 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100498
499 /* If we're doing Dbus or UBus, the above can be set dynamically,
500 (as can ports) so always (potentially) needed. */
501#ifdef HAVE_DBUS
502 if (option_bool(OPT_DBUS))
503 {
504 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100505 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100506 }
507#endif
508
509#ifdef HAVE_UBUS
510 if (option_bool(OPT_UBUS))
511 {
512 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100513 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100514 }
515#endif
516
Simon Kelley1a6bca82008-07-11 11:11:42 +0100517 /* determine capability API version here, while we can still
518 call safe_malloc */
Simon Kelley305ffb52019-03-16 18:17:17 +0000519 int capsize = 1; /* for header version 1 */
520 char *fail = NULL;
521
522 hdr = safe_malloc(sizeof(*hdr));
523
524 /* find version supported by kernel */
525 memset(hdr, 0, sizeof(*hdr));
526 capget(hdr, NULL);
527
528 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100529 {
Simon Kelley305ffb52019-03-16 18:17:17 +0000530 /* if unknown version, use largest supported version (3) */
531 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
532 hdr->version = LINUX_CAPABILITY_VERSION_3;
533 capsize = 2;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100534 }
Simon Kelley305ffb52019-03-16 18:17:17 +0000535
536 data = safe_malloc(sizeof(*data) * capsize);
537 capget(hdr, data); /* Get current values, for verification */
538
539 if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
540 fail = "NET_ADMIN";
541 else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
542 fail = "NET_RAW";
543 else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
544 fail = "NET_BIND_SERVICE";
545
546 if (fail)
547 die(_("process is missing required capability %s"), fail, EC_MISC);
548
549 /* Now set bitmaps to set caps after daemonising */
550 memset(data, 0, sizeof(*data) * capsize);
551
552 if (need_cap_net_admin)
553 data->effective |= (1 << CAP_NET_ADMIN);
554 if (need_cap_net_raw)
555 data->effective |= (1 << CAP_NET_RAW);
556 if (need_cap_net_bind_service)
557 data->effective |= (1 << CAP_NET_BIND_SERVICE);
558
559 data->permitted = data->effective;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100560#endif
561
Simon Kelley5aabfc72007-08-29 11:24:47 +0100562 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100563 in a race-free manner and another to carry errors to daemon-invoking process */
564 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100565
566 piperead = pipefd[0];
567 pipewrite = pipefd[1];
568 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000569 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100570
571 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100572
Simon Kelley28866e92011-02-14 20:19:14 +0000573 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000574 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000575 /* The following code "daemonizes" the process.
576 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100577
Simon Kelley9e038942008-05-30 20:06:34 +0100578 if (chdir("/") != 0)
579 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
580
Simon Kelley28866e92011-02-14 20:19:14 +0000581 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100582 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100583 pid_t pid;
584
Simon Kelley1a6bca82008-07-11 11:11:42 +0100585 /* pipe to carry errors back to original process.
586 When startup is complete we close this and the process terminates. */
587 safe_pipe(err_pipe, 0);
588
Simon Kelley7622fc02009-06-04 20:32:05 +0100589 if ((pid = fork()) == -1)
590 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000591 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100592
Simon Kelley5aabfc72007-08-29 11:24:47 +0100593 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100594 {
595 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000596 char *msg;
597
Simon Kelley1a6bca82008-07-11 11:11:42 +0100598 /* close our copy of write-end */
Simon Kelley5fc639c2019-03-29 21:29:43 +0000599 close(err_pipe[1]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100600
601 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000602 if (read_event(err_pipe[0], &ev, &msg))
603 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100604
605 _exit(EC_GOOD);
606 }
607
Simon Kelley5fc639c2019-03-29 21:29:43 +0000608 close(err_pipe[0]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100609
610 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100611
612 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100613
614 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000615 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100616
617 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100618 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100619 }
Simon Kelley9e038942008-05-30 20:06:34 +0100620
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000621 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100622 if (daemon->runfile)
623 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100624 int fd, err = 0;
625
626 sprintf(daemon->namebuff, "%d\n", (int) getpid());
627
628 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
629 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
630 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
631 extent that an attacker running as the unprivileged user could replace the pidfile with a
632 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
633
Josh Soref730c6742017-02-06 16:14:04 +0000634 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100635 ensuring that the open() fails should there be any existing file (because the unlink() failed,
636 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
637 attack can succeed.
638
639 Any compromise of the non-privileged user still theoretically allows the pid-file to be
640 replaced whilst dnsmasq is running. The worst that could allow is that the usual
641 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
642
643 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
644 failure to write the pid-file.
645 */
646
647 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100648
Simon Kelley79cfefd2012-09-02 13:29:51 +0100649 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 +0100650 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100651 /* only complain if started as root */
652 if (getuid() == 0)
653 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100654 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100655 else
656 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000657 /* We're still running as root here. Change the ownership of the PID file
658 to the user we will be running as. Note that this is not to allow
659 us to delete the file, since that depends on the permissions
660 of the directory containing the file. That directory will
661 need to by owned by the dnsmasq user, and the ownership of the
662 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000663 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
664 chown_warn = errno;
665
666 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100667 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000668 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000669 {
Simon Kelley5fc639c2019-03-29 21:29:43 +0000670 if (close(fd) == -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000671 err = 1;
672 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100673 }
674
675 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100676 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000677 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100678 _exit(0);
679 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000680 }
Simon Kelley16972692006-10-16 20:04:18 +0100681 }
682
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100683 log_err = log_start(ent_pw, err_pipe[1]);
684
Simon Kelley28866e92011-02-14 20:19:14 +0000685 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100686 {
687 /* open stdout etc to /dev/null */
688 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000689 if (nullfd != -1)
690 {
691 dup2(nullfd, STDOUT_FILENO);
692 dup2(nullfd, STDERR_FILENO);
693 dup2(nullfd, STDIN_FILENO);
694 close(nullfd);
695 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100696 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100697
Simon Kelley1a6bca82008-07-11 11:11:42 +0100698 /* if we are to run scripts, we need to fork a helper before dropping root. */
699 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000700#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000701 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000702 (daemon->lease_change_command || daemon->luascript))
703 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100704#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100705
Simon Kelley28866e92011-02-14 20:19:14 +0000706 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100707 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100708 int bad_capabilities = 0;
709 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100710
Josh Soref730c6742017-02-06 16:14:04 +0000711 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100712 if (gp &&
713 (setgroups(0, &dummy) == -1 ||
714 setgid(gp->gr_gid) == -1))
715 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000716 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100717 _exit(0);
718 }
719
Simon Kelley7cebd202006-05-06 14:13:33 +0100720 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100721 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100722#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000723 /* Need to be able to drop root. */
724 data->effective |= (1 << CAP_SETUID);
725 data->permitted |= (1 << CAP_SETUID);
Simon Kelley16972692006-10-16 20:04:18 +0100726 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000727 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100728 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100729
Simon Kelley7622fc02009-06-04 20:32:05 +0100730#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000731 /* http://developers.sun.com/solaris/articles/program_privileges.html */
732 priv_set_t *priv_set;
733
734 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
735 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
736 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
737 bad_capabilities = errno;
738
739 if (priv_set && bad_capabilities == 0)
740 {
741 priv_inverse(priv_set);
742
743 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
744 bad_capabilities = errno;
745 }
746
747 if (priv_set)
748 priv_freeset(priv_set);
749
Simon Kelley824af852008-02-12 20:43:05 +0000750#endif
751
Simon Kelley1a6bca82008-07-11 11:11:42 +0100752 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100753 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000754 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100755 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100756 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100757
758 /* finally drop root */
759 if (setuid(ent_pw->pw_uid) == -1)
760 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000761 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100762 _exit(0);
763 }
764
765#ifdef HAVE_LINUX_NETWORK
Simon Kelley305ffb52019-03-16 18:17:17 +0000766 data->effective &= ~(1 << CAP_SETUID);
767 data->permitted &= ~(1 << CAP_SETUID);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100768
Simon Kelley305ffb52019-03-16 18:17:17 +0000769 /* lose the setuid capability */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100770 if (capset(hdr, data) == -1)
771 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000772 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100773 _exit(0);
774 }
775#endif
776
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000777 }
Simon Kelley849a8352006-06-09 21:02:31 +0100778 }
Simon Kelley16972692006-10-16 20:04:18 +0100779
Simon Kelley16972692006-10-16 20:04:18 +0100780#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000781 free(hdr);
782 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000783 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000784 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100785#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100786
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100787#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100788 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100789 {
790 DIR *dir;
791 struct tftp_prefix *p;
792
793 if (daemon->tftp_prefix)
794 {
795 if (!((dir = opendir(daemon->tftp_prefix))))
796 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100797 tftp_prefix_missing = 1;
798 if (!option_bool(OPT_TFTP_NO_FAIL))
799 {
800 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
801 _exit(0);
802 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100803 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100804 else
805 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100806 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100807
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100808 for (p = daemon->if_prefix; p; p = p->next)
809 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100810 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100811 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100812 {
813 p->missing = 1;
814 if (!option_bool(OPT_TFTP_NO_FAIL))
815 {
816 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
817 _exit(0);
818 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100819 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100820 else
821 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100822 }
823 }
824#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100825
Simon Kelley824af852008-02-12 20:43:05 +0000826 if (daemon->port == 0)
827 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000828 else
829 {
830 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100831 {
832 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
833 if (daemon->cachesize > 10000)
834 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
835 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000836 else
837 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
838
839 if (option_bool(OPT_LOCAL_SERVICE))
840 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
841 }
Simon Kelley16972692006-10-16 20:04:18 +0100842
Simon Kelleyf2621c72007-04-29 19:47:21 +0100843 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000844
845 if (chown_warn != 0)
846 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100847
Simon Kelley3d8df262005-08-29 12:19:27 +0100848#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000849 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100850 {
851 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100852 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100853 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100854 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100855 }
856#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000857
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100858#ifdef HAVE_UBUS
859 if (option_bool(OPT_UBUS))
860 {
861 if (daemon->ubus)
862 my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
863 else
864 my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
865 }
866#endif
867
Simon Kelley1d97ac42014-01-31 11:12:27 +0000868#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000869 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000870 {
Simon Kelley360f2512015-03-07 18:28:06 +0000871 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100872 struct ds_config *ds;
873
Simon Kelley360f2512015-03-07 18:28:06 +0000874 /* Delay creating the timestamp file until here, after we've changed user, so that
875 it has the correct owner to allow updating the mtime later.
876 This means we have to report fatal errors via the pipe. */
877 if ((rc = setup_timestamp()) == -1)
878 {
879 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
880 _exit(0);
881 }
882
Simon Kelleya6918532018-04-15 16:20:52 +0100883 if (option_bool(OPT_DNSSEC_IGN_NS))
884 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
885 else
886 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000887
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100888 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
889 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000890 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000891
892 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000893 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100894
895 for (ds = daemon->ds; ds; ds = ds->next)
896 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
897 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000898 }
Simon Kelleydb737462014-01-31 10:32:45 +0000899#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100900
Simon Kelley1a6bca82008-07-11 11:11:42 +0100901 if (log_err != 0)
902 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
903 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000904
Simon Kelleyde379512004-06-22 20:23:33 +0100905 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100906 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100907
Simon Kelleyf7029f52013-11-21 15:09:09 +0000908 if (option_bool(OPT_NOWILD))
909 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000910 else if (!option_bool(OPT_CLEVERBIND))
911 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000912
913 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100914
Simon Kelley28866e92011-02-14 20:19:14 +0000915 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000916 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
917 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100918 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100919
Simon Kelley28866e92011-02-14 20:19:14 +0000920 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100921 {
922 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100923 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100924 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000925 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100926 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100927 }
928
Simon Kelleyf2621c72007-04-29 19:47:21 +0100929 if (daemon->max_logs != 0)
930 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000931
Simon Kelleyf2621c72007-04-29 19:47:21 +0100932
Simon Kelley7622fc02009-06-04 20:32:05 +0100933#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000934 for (context = daemon->dhcp; context; context = context->next)
935 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100936
Simon Kelleyff7eea22013-09-04 18:01:38 +0100937 for (relay = daemon->relay4; relay; relay = relay->next)
938 log_relay(AF_INET, relay);
939
Simon Kelley1f776932012-12-16 19:46:08 +0000940# ifdef HAVE_DHCP6
941 for (context = daemon->dhcp6; context; context = context->next)
942 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000943
Simon Kelleyff7eea22013-09-04 18:01:38 +0100944 for (relay = daemon->relay6; relay; relay = relay->next)
945 log_relay(AF_INET6, relay);
946
Simon Kelley1f776932012-12-16 19:46:08 +0000947 if (daemon->doing_dhcp6 || daemon->doing_ra)
948 dhcp_construct_contexts(now);
949
950 if (option_bool(OPT_RA))
951 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
952# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000953
Simon Kelley3b3f4412013-10-11 16:33:28 +0100954# ifdef HAVE_LINUX_NETWORK
955 if (did_bind)
956 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
Simon Kelley913fa152020-04-19 23:16:52 +0100957
958 if (netlink_warn)
959 my_syslog(LOG_WARNING, netlink_warn);
Simon Kelley3b3f4412013-10-11 16:33:28 +0100960# endif
961
Josh Soref730c6742017-02-06 16:14:04 +0000962 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000963 if (daemon->dhcp || daemon->doing_dhcp6)
964 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000965#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000966
Simon Kelley832af0b2007-01-21 20:01:28 +0000967#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000968 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100969 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100970 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000971
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000972 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100973 daemon->tftp_prefix ? _("root is ") : _("enabled"),
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000974 daemon->tftp_prefix ? daemon->tftp_prefix : "",
975 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "",
976 option_bool(OPT_SINGLE_PORT) ? _("single port mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100977
Stefan Tomanek30d08792015-03-31 22:32:11 +0100978 if (tftp_prefix_missing)
979 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100980
Stefan Tomanek30d08792015-03-31 22:32:11 +0100981 for (p = daemon->if_prefix; p; p = p->next)
982 if (p->missing)
983 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
984
Simon Kelley832af0b2007-01-21 20:01:28 +0000985 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100986 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000987 a single file will be sent to may clients (the file only needs
988 one fd). */
989
990 max_fd -= 30; /* use other than TFTP */
991
992 if (max_fd < 0)
993 max_fd = 5;
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000994 else if (max_fd < 100 && !option_bool(OPT_SINGLE_PORT))
Simon Kelley832af0b2007-01-21 20:01:28 +0000995 max_fd = max_fd/2;
996 else
997 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000998
999 /* if we have to use a limited range of ports,
1000 that will limit the number of transfers */
1001 if (daemon->start_tftp_port != 0 &&
1002 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
1003 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001004
1005 if (daemon->tftp_max > max_fd)
1006 {
1007 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +01001008 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +01001009 _("restricting maximum simultaneous TFTP transfers to %d"),
1010 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +00001011 }
1012 }
1013#endif
1014
Simon Kelley1a6bca82008-07-11 11:11:42 +01001015 /* finished start-up - release original process */
1016 if (err_pipe[1] != -1)
Simon Kelley5fc639c2019-03-29 21:29:43 +00001017 close(err_pipe[1]);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001018
Simon Kelley824af852008-02-12 20:43:05 +00001019 if (daemon->port != 0)
1020 check_servers();
1021
Simon Kelley7cebd202006-05-06 14:13:33 +01001022 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +01001023
1024 daemon->pipe_to_parent = -1;
1025 for (i = 0; i < MAX_PROCS; i++)
1026 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +01001027
Simon Kelley04918052015-01-26 11:23:43 +00001028#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +00001029 /* Using inotify, have to select a resolv file at startup */
1030 poll_resolv(1, 0, now);
1031#endif
1032
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001033 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001034 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001035 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001036
Simon Kelleyb842bc92015-07-12 21:09:11 +01001037 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001038
Simon Kelley16972692006-10-16 20:04:18 +01001039 /* if we are out of resources, find how long we have to wait
1040 for some to come free, we'll loop around then and restart
1041 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001042 if ((t = set_dns_listeners(now)) != 0)
1043 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +01001044
Simon Kelley832af0b2007-01-21 20:01:28 +00001045 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
1046 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +00001047 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +01001048 timeout = 250;
1049
Simon Kelley74c95c22011-10-19 09:33:39 +01001050 /* Wake every second whilst waiting for DAD to complete */
1051 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001052 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001053
Simon Kelley832af0b2007-01-21 20:01:28 +00001054#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +01001055 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001056#endif
1057
1058#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001059 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001060 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001061#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001062
Simon Kelley7622fc02009-06-04 20:32:05 +01001063#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001064 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001065 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001066 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +00001067 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001068 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001069 }
Simon Kelley7622fc02009-06-04 20:32:05 +01001070#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001071
Simon Kelley52b92f42012-01-22 16:05:15 +00001072#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +01001073 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001074 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001075
Simon Kelley1f776932012-12-16 19:46:08 +00001076 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001077 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +00001078#endif
Simon Kelley04918052015-01-26 11:23:43 +00001079
1080#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001081 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001082 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +00001083#endif
1084
1085#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001086 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +00001087#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001088 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001089#endif
Simon Kelley193de4a2014-12-10 17:32:16 +00001090
Simon Kelleyb842bc92015-07-12 21:09:11 +01001091 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001092
Simon Kelley33702ab2015-12-28 23:17:15 +00001093#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001094# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001095 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001096# endif
1097
Simon Kelley1e505122016-01-25 21:29:23 +00001098 /* Refresh cache */
1099 if (option_bool(OPT_SCRIPT_ARP))
1100 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001101 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001102
Simon Kelleya9530962012-03-20 22:07:35 +00001103# ifdef HAVE_TFTP
1104 while (helper_buf_empty() && do_tftp_script_run());
1105# endif
1106
Simon Kelley16972692006-10-16 20:04:18 +01001107 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001108 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001109#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001110 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001111# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001112 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001113# endif
1114
Simon Kelleyb633de92016-01-06 22:51:17 +00001115 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001116
1117# ifdef HAVE_TFTP
1118 while (do_tftp_script_run());
1119# endif
1120
Simon Kelley5aabfc72007-08-29 11:24:47 +01001121#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001122
Simon Kelley7622fc02009-06-04 20:32:05 +01001123
Simon Kelley66f62652020-01-05 16:21:24 +00001124 /* must do this just before do_poll(), when we know no
Simon Kelleyf2621c72007-04-29 19:47:21 +01001125 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001126 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001127
Simon Kelleyb842bc92015-07-12 21:09:11 +01001128 if (do_poll(timeout) < 0)
1129 continue;
1130
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001131 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001132
Simon Kelleyb842bc92015-07-12 21:09:11 +01001133 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001134
1135 /* prime. */
1136 enumerate_interfaces(1);
1137
Simon Kelley74c95c22011-10-19 09:33:39 +01001138 /* Check the interfaces to see if any have exited DAD state
1139 and if so, bind the address. */
1140 if (is_dad_listeners())
1141 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001142 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001143 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1144 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001145 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001146 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001147
Simon Kelley1ee9be42013-12-09 16:50:19 +00001148#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001149 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001150 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001151#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001152 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001153 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001154#endif
1155
Simon Kelley04918052015-01-26 11:23:43 +00001156#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001157 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001158 {
1159 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1160 poll_resolv(1, 1, now);
1161 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001162#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001163 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001164 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001165 if (daemon->last_resolv == 0 ||
1166 difftime(now, daemon->last_resolv) > 1.0 ||
1167 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001168 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001169 /* poll_resolv doesn't need to reload first time through, since
1170 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001171
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001172 poll_resolv(0, daemon->last_resolv != 0, now);
1173 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001174 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001175#endif
1176
Simon Kelleyb842bc92015-07-12 21:09:11 +01001177 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001178 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001179
Simon Kelley3d8df262005-08-29 12:19:27 +01001180#ifdef HAVE_DBUS
1181 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001182 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001183 {
1184 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001185 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001186 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001187 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001188 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001189 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001190 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001191#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001192
1193#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001194 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001195 {
1196 /* if we didn't create a UBus connection, retry now. */
1197 if (!daemon->ubus)
1198 {
1199 ubus_init();
1200 }
1201
1202 check_ubus_listeners();
1203 }
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001204#endif
1205
Simon Kelleyb842bc92015-07-12 21:09:11 +01001206 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001207
1208#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001209 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001210#endif
1211
Simon Kelley7622fc02009-06-04 20:32:05 +01001212#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001213 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001214 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001215 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001216 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001217 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001218 dhcp_packet(now, 1);
1219 }
Simon Kelley16972692006-10-16 20:04:18 +01001220
Simon Kelley52b92f42012-01-22 16:05:15 +00001221#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001222 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001223 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001224
Simon Kelleyb842bc92015-07-12 21:09:11 +01001225 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001226 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001227#endif
1228
Simon Kelley1f15b812009-10-13 17:49:32 +01001229# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001230 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001231 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001232# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001233#endif
1234
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001235 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001236}
1237
Simon Kelley3be34542004-09-11 19:12:13 +01001238static void sig_handler(int sig)
1239{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001240 if (pid == 0)
1241 {
Simon Kelley16972692006-10-16 20:04:18 +01001242 /* ignore anything other than TERM during startup
1243 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001244 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001245 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001246 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001247 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001248 {
Simon Kelley16972692006-10-16 20:04:18 +01001249 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001250 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001251 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001252 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001253 else
1254 {
1255 /* master process */
1256 int event, errsave = errno;
1257
1258 if (sig == SIGHUP)
1259 event = EVENT_RELOAD;
1260 else if (sig == SIGCHLD)
1261 event = EVENT_CHILD;
1262 else if (sig == SIGALRM)
1263 event = EVENT_ALARM;
1264 else if (sig == SIGTERM)
1265 event = EVENT_TERM;
1266 else if (sig == SIGUSR1)
1267 event = EVENT_DUMP;
1268 else if (sig == SIGUSR2)
1269 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001270 else if (sig == SIGINT)
1271 {
1272 /* Handle SIGINT normally in debug mode, so
1273 ctrl-c continues to operate. */
1274 if (option_bool(OPT_DEBUG))
1275 exit(EC_MISC);
1276 else
1277 event = EVENT_TIME;
1278 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001279 else
1280 return;
1281
Simon Kelleyc72daea2012-01-05 21:33:27 +00001282 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001283 errno = errsave;
1284 }
Simon Kelley3be34542004-09-11 19:12:13 +01001285}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001286
Simon Kelley353ae4d2012-03-19 20:07:51 +00001287/* now == 0 -> queue immediate callback */
1288void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001289{
Simon Kelley884a6df2012-03-20 16:20:22 +00001290 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001291 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001292 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1293 if ((now == 0 || difftime(event, now) <= 0.0))
1294 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1295 else
1296 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001297 }
Simon Kelley741c2952012-02-25 13:09:18 +00001298}
1299
Simon Kelley47a95162014-07-08 22:22:02 +01001300void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001301{
Simon Kelley47a95162014-07-08 22:22:02 +01001302 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001303}
1304
Simon Kelleyc72daea2012-01-05 21:33:27 +00001305void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001306{
1307 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001308 struct iovec iov[2];
1309
Simon Kelley5aabfc72007-08-29 11:24:47 +01001310 ev.event = event;
1311 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001312 ev.msg_sz = msg ? strlen(msg) : 0;
1313
1314 iov[0].iov_base = &ev;
1315 iov[0].iov_len = sizeof(ev);
1316 iov[1].iov_base = msg;
1317 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001318
1319 /* error pipe, debug mode. */
1320 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001321 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001322 else
1323 /* pipe is non-blocking and struct event_desc is smaller than
1324 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001325 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001326}
Simon Kelley3d8df262005-08-29 12:19:27 +01001327
Simon Kelleyc72daea2012-01-05 21:33:27 +00001328/* NOTE: the memory used to return msg is leaked: use msgs in events only
1329 to describe fatal errors. */
1330static int read_event(int fd, struct event_desc *evp, char **msg)
1331{
1332 char *buf;
1333
1334 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1335 return 0;
1336
1337 *msg = NULL;
1338
1339 if (evp->msg_sz != 0 &&
1340 (buf = malloc(evp->msg_sz + 1)) &&
1341 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1342 {
1343 buf[evp->msg_sz] = 0;
1344 *msg = buf;
1345 }
1346
1347 return 1;
1348}
1349
1350static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001351{
1352 errno = ev->data;
1353
1354 switch (ev->event)
1355 {
1356 case EVENT_DIE:
1357 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001358
1359 case EVENT_FORK_ERR:
1360 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001361
1362 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001363 case EVENT_PIPE_ERR:
1364 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001365
1366 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001367 case EVENT_CAP_ERR:
1368 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1369
Simon Kelleye7a4af82018-02-16 21:27:35 +00001370 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001371 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001372 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001373
Simon Kelleye7a4af82018-02-16 21:27:35 +00001374 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001375 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001376 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001377
1378 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001379 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001380 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001381
Simon Kelleye7a4af82018-02-16 21:27:35 +00001382 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001383 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001384 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001385
1386 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001387 case EVENT_LUA_ERR:
1388 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001389
Simon Kelleye7a4af82018-02-16 21:27:35 +00001390 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001391 case EVENT_TFTP_ERR:
1392 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001393
1394 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001395 case EVENT_TIME_ERR:
1396 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001397 }
1398}
1399
Simon Kelley5aabfc72007-08-29 11:24:47 +01001400static void async_event(int pipe, time_t now)
1401{
1402 pid_t p;
1403 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001404 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001405 char *msg;
1406
1407 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1408 to describe fatal errors. */
1409
1410 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001411 switch (ev.event)
1412 {
1413 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001414 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001415
Simon Kelleye98bd522014-03-28 20:41:23 +00001416 /* fall through */
1417
1418 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001419 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001420
Simon Kelley7b1eae42014-02-20 13:43:28 +00001421 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001422 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001423 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1424 {
1425 reload_servers(daemon->resolv_files->name);
1426 check = 1;
1427 }
1428
1429 if (daemon->servers_file)
1430 {
1431 read_servers_file();
1432 check = 1;
1433 }
1434
1435 if (check)
1436 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001437 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001438
Simon Kelley7622fc02009-06-04 20:32:05 +01001439#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001440 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001441#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001442 break;
1443
1444 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001445 if (daemon->port != 0)
1446 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001447 break;
1448
1449 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001450#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001451 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001452 {
1453 lease_prune(NULL, now);
1454 lease_update_file(now);
1455 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001456#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001457 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001458 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1459 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001460#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001461#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001462 break;
1463
1464 case EVENT_CHILD:
1465 /* See Stevens 5.10 */
1466 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1467 if (p == -1)
1468 {
1469 if (errno != EINTR)
1470 break;
1471 }
1472 else
1473 for (i = 0 ; i < MAX_PROCS; i++)
1474 if (daemon->tcp_pids[i] == p)
1475 daemon->tcp_pids[i] = 0;
1476 break;
1477
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001478#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001479 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001480 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001481 break;
1482
1483 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001484 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001485 break;
1486
1487 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001488 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1489 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001490 break;
1491
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001492 case EVENT_SCRIPT_LOG:
1493 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1494 free(msg);
1495 msg = NULL;
1496 break;
1497
Simon Kelley1a6bca82008-07-11 11:11:42 +01001498 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001499 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001500 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001501 case EVENT_LUA_ERR:
1502 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001503 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001504#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001505
Simon Kelley5aabfc72007-08-29 11:24:47 +01001506 case EVENT_REOPEN:
1507 /* Note: this may leave TCP-handling processes with the old file still open.
1508 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1509 we leave them logging to the old file. */
1510 if (daemon->log_file != NULL)
1511 log_reopen(daemon->log_file);
1512 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001513
1514 case EVENT_NEWADDR:
1515 newaddress(now);
1516 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001517
1518 case EVENT_NEWROUTE:
1519 resend_query();
1520 /* Force re-reading resolv file right now, for luck. */
1521 poll_resolv(0, 1, now);
1522 break;
1523
Simon Kelley3c973ad2018-01-14 21:05:37 +00001524 case EVENT_TIME:
1525#ifdef HAVE_DNSSEC
1526 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1527 {
1528 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1529 daemon->dnssec_no_time_check = 0;
1530 clear_cache_and_reload(now);
1531 }
1532#endif
1533 break;
1534
Simon Kelley5aabfc72007-08-29 11:24:47 +01001535 case EVENT_TERM:
1536 /* Knock all our children on the head. */
1537 for (i = 0; i < MAX_PROCS; i++)
1538 if (daemon->tcp_pids[i] != 0)
1539 kill(daemon->tcp_pids[i], SIGALRM);
1540
Simon Kelley53a91732016-01-06 17:59:13 +00001541#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001542 /* handle pending lease transitions */
1543 if (daemon->helperfd != -1)
1544 {
1545 /* block in writes until all done */
1546 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1547 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1548 do {
1549 helper_write();
1550 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelley5fc639c2019-03-29 21:29:43 +00001551 close(daemon->helperfd);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001552 }
1553#endif
1554
1555 if (daemon->lease_stream)
1556 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001557
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001558#ifdef HAVE_DNSSEC
1559 /* update timestamp file on TERM if time is considered valid */
1560 if (daemon->back_to_the_future)
1561 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001562 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001563 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1564 }
1565#endif
1566
Simon Kelley73a08a22009-02-05 20:28:08 +00001567 if (daemon->runfile)
1568 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001569
1570#ifdef HAVE_DUMPFILE
1571 if (daemon->dumpfd != -1)
1572 close(daemon->dumpfd);
1573#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001574
1575 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1576 flush_log();
1577 exit(EC_GOOD);
1578 }
1579}
1580
Simon Kelley47a95162014-07-08 22:22:02 +01001581static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001582{
1583 struct resolvc *res, *latest;
1584 struct stat statbuf;
1585 time_t last_change = 0;
1586 /* There may be more than one possible file.
1587 Go through and find the one which changed _last_.
1588 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001589
Simon Kelley28866e92011-02-14 20:19:14 +00001590 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001591 return;
1592
Simon Kelley5aabfc72007-08-29 11:24:47 +01001593 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1594 if (stat(res->name, &statbuf) == -1)
1595 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001596 if (force)
1597 {
1598 res->mtime = 0;
1599 continue;
1600 }
1601
Simon Kelley5aabfc72007-08-29 11:24:47 +01001602 if (!res->logged)
1603 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1604 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001605
1606 if (res->mtime != 0)
1607 {
1608 /* existing file evaporated, force selection of the latest
1609 file even if its mtime hasn't changed since we last looked */
1610 poll_resolv(1, do_reload, now);
1611 return;
1612 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001613 }
1614 else
1615 {
1616 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001617 if (force || (statbuf.st_mtime != res->mtime))
1618 {
1619 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001620 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1621 {
1622 last_change = statbuf.st_mtime;
1623 latest = res;
1624 }
1625 }
1626 }
1627
1628 if (latest)
1629 {
1630 static int warned = 0;
1631 if (reload_servers(latest->name))
1632 {
1633 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1634 warned = 0;
1635 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001636 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001637 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001638 }
1639 else
1640 {
1641 latest->mtime = 0;
1642 if (!warned)
1643 {
1644 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1645 warned = 1;
1646 }
1647 }
1648 }
1649}
1650
1651void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001652{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001653 (void)now;
1654
Simon Kelley824af852008-02-12 20:43:05 +00001655 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001656 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001657
Simon Kelley7622fc02009-06-04 20:32:05 +01001658#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001659 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001660 {
Simon Kelley28866e92011-02-14 20:19:14 +00001661 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001662 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001663 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001664 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001665 lease_update_from_configs();
1666 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001667 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001668 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001669#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001670 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001671 /* Not doing DHCP, so no lease system, manage
1672 alarms for ra only */
1673 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001674#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001675#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001676}
1677
Simon Kelleyb842bc92015-07-12 21:09:11 +01001678static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001679{
1680 struct serverfd *serverfdp;
1681 struct listener *listener;
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001682 struct randfd_list *rfl;
Simon Kelley824af852008-02-12 20:43:05 +00001683 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001684
1685#ifdef HAVE_TFTP
1686 int tftp = 0;
1687 struct tftp_transfer *transfer;
Simon Kelley66f62652020-01-05 16:21:24 +00001688 if (!option_bool(OPT_SINGLE_PORT))
1689 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1690 {
1691 tftp++;
1692 poll_listen(transfer->sockfd, POLLIN);
1693 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001694#endif
1695
Simon Kelley16972692006-10-16 20:04:18 +01001696 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001697 if (daemon->port != 0)
Simon Kelley8caf3d72020-04-04 17:00:32 +01001698 get_new_frec(now, &wait, NULL);
Simon Kelley16972692006-10-16 20:04:18 +01001699
Simon Kelley3be34542004-09-11 19:12:13 +01001700 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001701 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001702
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001703 for (i = 0; i < RANDOM_SOCKS; i++)
1704 if (daemon->randomsocks[i].refcount != 0)
1705 poll_listen(daemon->randomsocks[i].fd, POLLIN);
1706
1707 /* Check overflow random sockets too. */
1708 for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
1709 poll_listen(rfl->rfd->fd, POLLIN);
1710
Simon Kelley3be34542004-09-11 19:12:13 +01001711 for (listener = daemon->listeners; listener; listener = listener->next)
1712 {
Simon Kelley16972692006-10-16 20:04:18 +01001713 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001714 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001715 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001716
Simon Kelley16972692006-10-16 20:04:18 +01001717 /* death of a child goes through the select loop, so
1718 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001719 if (listener->tcpfd != -1)
1720 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001721 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001722 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001723 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001724 break;
1725 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001726
Simon Kelley832af0b2007-01-21 20:01:28 +00001727#ifdef HAVE_TFTP
Simon Kelley2ac4cf02020-01-06 23:39:33 +00001728 /* tftp == 0 in single-port mode. */
Simon Kelley832af0b2007-01-21 20:01:28 +00001729 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001730 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001731#endif
1732
1733 }
1734
Simon Kelleya799ca02018-10-18 19:35:29 +01001735 if (!option_bool(OPT_DEBUG))
1736 for (i = 0; i < MAX_PROCS; i++)
1737 if (daemon->tcp_pipes[i] != -1)
1738 poll_listen(daemon->tcp_pipes[i], POLLIN);
Simon Kelleya799ca02018-10-18 19:35:29 +01001739
Simon Kelley16972692006-10-16 20:04:18 +01001740 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001741}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001742
Simon Kelleyb842bc92015-07-12 21:09:11 +01001743static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001744{
1745 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001746 struct listener *listener;
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001747 struct randfd_list *rfl;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001748 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001749 int pipefd[2];
Simon Kelleya799ca02018-10-18 19:35:29 +01001750
Simon Kelley832af0b2007-01-21 20:01:28 +00001751 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001752 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001753 reply_query(serverfdp->fd, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001754
Simon Kelley74d4fcd2021-03-15 21:59:51 +00001755 for (i = 0; i < RANDOM_SOCKS; i++)
1756 if (daemon->randomsocks[i].refcount != 0 &&
1757 poll_check(daemon->randomsocks[i].fd, POLLIN))
1758 reply_query(daemon->randomsocks[i].fd, now);
1759
1760 /* Check overflow random sockets too. */
1761 for (rfl = daemon->rfl_poll; rfl; rfl = rfl->next)
1762 if (poll_check(rfl->rfd->fd, POLLIN))
1763 reply_query(rfl->rfd->fd, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001764
Simon Kelleya799ca02018-10-18 19:35:29 +01001765 /* Races. The child process can die before we read all of the data from the
1766 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1767 process, and tcp_pipes to -1 and close the FD when we read the last
1768 of the data - indicated by cache_recv_insert returning zero.
1769 The order of these events is indeterminate, and both are needed
1770 to free the process slot. Once the child process has gone, poll()
1771 returns POLLHUP, not POLLIN, so have to check for both here. */
1772 if (!option_bool(OPT_DEBUG))
1773 for (i = 0; i < MAX_PROCS; i++)
1774 if (daemon->tcp_pipes[i] != -1 &&
1775 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1776 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1777 {
1778 close(daemon->tcp_pipes[i]);
1779 daemon->tcp_pipes[i] = -1;
1780 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001781
Simon Kelley832af0b2007-01-21 20:01:28 +00001782 for (listener = daemon->listeners; listener; listener = listener->next)
1783 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001784 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001785 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001786
Simon Kelley832af0b2007-01-21 20:01:28 +00001787#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001788 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001789 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001790#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001791
Simon Kelleyb842bc92015-07-12 21:09:11 +01001792 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001793 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001794 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001795 struct irec *iface = NULL;
1796 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001797 union mysockaddr tcp_addr;
1798 socklen_t tcp_len = sizeof(union mysockaddr);
1799
1800 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001801
Simon Kelley46b06652013-02-04 21:47:59 +00001802 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001803 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001804
Simon Kelley46b06652013-02-04 21:47:59 +00001805 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1806 {
Simon Kelley5fc639c2019-03-29 21:29:43 +00001807 close(confd);
Simon Kelley46b06652013-02-04 21:47:59 +00001808 continue;
1809 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001810
1811 /* Make sure that the interface list is up-to-date.
1812
1813 We do this here as we may need the results below, and
1814 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001815
Simon Kelley76dd75d2013-05-23 10:04:25 +01001816 Multiple calls to enumerate_interfaces() per select loop are
1817 inhibited, so calls to it in the child process (which doesn't select())
1818 have no effect. This avoids two processes reading from the same
1819 netlink fd and screwing the pooch entirely.
1820 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001821
Simon Kelley76dd75d2013-05-23 10:04:25 +01001822 enumerate_interfaces(0);
1823
1824 if (option_bool(OPT_NOWILD))
1825 iface = listener->iface; /* May be NULL */
1826 else
1827 {
1828 int if_index;
1829 char intr_name[IF_NAMESIZE];
1830
1831 /* if we can find the arrival interface, check it's one that's allowed */
1832 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1833 indextoname(listener->tcpfd, if_index, intr_name))
1834 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001835 union all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001836
Simon Kelley76dd75d2013-05-23 10:04:25 +01001837 if (tcp_addr.sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001838 addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001839 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001840 addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001841
1842 for (iface = daemon->interfaces; iface; iface = iface->next)
Petr Mensik951a2212019-07-03 17:02:16 +02001843 if (iface->index == if_index &&
1844 iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
Simon Kelley76dd75d2013-05-23 10:04:25 +01001845 break;
1846
1847 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1848 client_ok = 0;
1849 }
1850
1851 if (option_bool(OPT_CLEVERBIND))
1852 iface = listener->iface; /* May be NULL */
1853 else
1854 {
1855 /* Check for allowed interfaces when binding the wildcard address:
1856 we do this by looking for an interface with the same address as
1857 the local address of the TCP connection, then looking to see if that's
1858 an allowed interface. As a side effect, we get the netmask of the
1859 interface too, for localisation. */
1860
1861 for (iface = daemon->interfaces; iface; iface = iface->next)
1862 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1863 break;
1864
1865 if (!iface)
1866 client_ok = 0;
1867 }
1868 }
1869
Simon Kelley22ce5502013-01-22 13:53:04 +00001870 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001871 {
1872 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001873 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001874 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001875 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001876 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001877 close(pipefd[1]); /* parent needs read pipe end. */
1878 if (p == -1)
1879 close(pipefd[0]);
1880 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001881 {
1882 int i;
Simon Kelleye2cb6552020-06-20 22:30:12 +01001883#ifdef HAVE_LINUX_NETWORK
1884 /* The child process inherits the netlink socket,
1885 which it never uses, but when the parent (us)
1886 uses it in the future, the answer may go to the
1887 child, resulting in the parent blocking
1888 forever awaiting the result. To avoid this
1889 the child closes the netlink socket, but there's
1890 a nasty race, since the parent may use netlink
1891 before the child has done the close.
1892
1893 To avoid this, the parent blocks here until a
1894 single byte comes back up the pipe, which
1895 is sent by the child after it has closed the
1896 netlink socket. */
1897
1898 unsigned char a;
1899 read_write(pipefd[0], &a, 1, 1);
1900#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001901
Simon Kelley832af0b2007-01-21 20:01:28 +00001902 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001903 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001904 {
1905 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001906 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley832af0b2007-01-21 20:01:28 +00001907 break;
1908 }
1909 }
Simon Kelley5fc639c2019-03-29 21:29:43 +00001910 close(confd);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001911
1912 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1913 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001914 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001915 else
1916 {
1917 unsigned char *buff;
1918 struct server *s;
1919 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001920 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001921 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001922
Simon Kelley52d4abf2012-03-21 21:39:48 +00001923 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001924 {
1925 netmask = iface->netmask;
1926 auth_dns = iface->dns_auth;
1927 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001928 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001929 {
1930 netmask.s_addr = 0;
1931 auth_dns = 0;
1932 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001933
Josh Soref730c6742017-02-06 16:14:04 +00001934 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001935 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001936 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001937 {
Simon Kelleye2cb6552020-06-20 22:30:12 +01001938#ifdef HAVE_LINUX_NETWORK
1939 /* See comment above re: netlink socket. */
1940 unsigned char a = 0;
1941
1942 close(daemon->netlinkfd);
1943 read_write(pipefd[1], &a, 1, 0);
1944#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001945 alarm(CHILD_LIFETIME);
1946 close(pipefd[0]); /* close read end in child. */
1947 daemon->pipe_to_parent = pipefd[1];
1948 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001949
Simon Kelley832af0b2007-01-21 20:01:28 +00001950 /* start with no upstream connections. */
1951 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001952 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001953
1954 /* The connected socket inherits non-blocking
1955 attribute from the listening socket.
1956 Reset that here. */
1957 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1958 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1959
Simon Kelley4f7b3042012-11-28 21:27:02 +00001960 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001961
Simon Kelley832af0b2007-01-21 20:01:28 +00001962 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001963 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001964
1965 if (buff)
1966 free(buff);
1967
1968 for (s = daemon->servers; s; s = s->next)
1969 if (s->tcpfd != -1)
1970 {
1971 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001972 close(s->tcpfd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001973 }
Simon Kelleye2cb6552020-06-20 22:30:12 +01001974
Simon Kelley28866e92011-02-14 20:19:14 +00001975 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001976 {
Simon Kelleye2cb6552020-06-20 22:30:12 +01001977 close(daemon->pipe_to_parent);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001978 flush_log();
1979 _exit(0);
1980 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001981 }
1982 }
1983 }
Simon Kelley3be34542004-09-11 19:12:13 +01001984}
1985
Simon Kelley7622fc02009-06-04 20:32:05 +01001986#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001987int make_icmp_sock(void)
1988{
Simon Kelley7cebd202006-05-06 14:13:33 +01001989 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001990 int zeroopt = 0;
1991
1992 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1993 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001994 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001995 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1996 {
1997 close(fd);
1998 fd = -1;
1999 }
2000 }
2001
2002 return fd;
2003}
2004
Simon Kelley5aabfc72007-08-29 11:24:47 +01002005int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01002006{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002007 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01002008
Floris Bos503c6092017-04-09 23:07:13 +01002009 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01002010 struct sockaddr_in saddr;
2011 struct {
2012 struct ip ip;
2013 struct icmp icmp;
2014 } packet;
2015 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01002016 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002017 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002018
Simon Kelley824af852008-02-12 20:43:05 +00002019#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002020 if ((fd = make_icmp_sock()) == -1)
2021 return 0;
2022#else
2023 int opt = 2000;
2024 fd = daemon->dhcp_icmp_fd;
2025 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2026#endif
2027
Simon Kelley3be34542004-09-11 19:12:13 +01002028 saddr.sin_family = AF_INET;
2029 saddr.sin_port = 0;
2030 saddr.sin_addr = addr;
2031#ifdef HAVE_SOCKADDR_SA_LEN
2032 saddr.sin_len = sizeof(struct sockaddr_in);
2033#endif
2034
2035 memset(&packet.icmp, 0, sizeof(packet.icmp));
2036 packet.icmp.icmp_type = ICMP_ECHO;
2037 packet.icmp.icmp_id = id;
2038 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
2039 j += ((u16 *)&packet.icmp)[i];
2040 while (j>>16)
2041 j = (j & 0xffff) + (j >> 16);
2042 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
2043
Simon Kelleyff841eb2015-03-11 21:36:30 +00002044 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
2045 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002046
Floris Bos503c6092017-04-09 23:07:13 +01002047 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
2048
2049#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelley5fc639c2019-03-29 21:29:43 +00002050 close(fd);
Floris Bos503c6092017-04-09 23:07:13 +01002051#else
2052 opt = 1;
2053 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2054#endif
2055
2056 return gotreply;
2057}
2058
2059int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
2060{
2061 /* Delay processing DHCP packets for "sec" seconds counting from "start".
2062 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
2063 from "addr" with ICMP ID "id" and return 1 */
2064
2065 /* Note that whilst waiting, we check for
2066 (and service) events on the DNS and TFTP sockets, (so doing that
2067 better not use any resources our caller has in use...)
2068 but we remain deaf to signals or further DHCP packets. */
2069
2070 /* There can be a problem using dnsmasq_time() to end the loop, since
2071 it's not monotonic, and can go backwards if the system clock is
2072 tweaked, leading to the code getting stuck in this loop and
2073 ignoring DHCP requests. To fix this, we check to see if select returned
2074 as a result of a timeout rather than a socket becoming available. We
2075 only allow this to happen as many times as it takes to get to the wait time
2076 in quarter-second chunks. This provides a fallback way to end loop. */
2077
2078 int rc, timeout_count;
2079 time_t now;
2080
2081 for (now = dnsmasq_time(), timeout_count = 0;
2082 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002083 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01002084 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01002085 if (fd != -1)
2086 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01002087 set_dns_listeners(now);
2088 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002089
2090#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00002091 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002092 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002093#endif
2094
Simon Kelleyb842bc92015-07-12 21:09:11 +01002095 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01002096
2097 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002098 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01002099 else if (rc == 0)
2100 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01002101
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002102 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01002103
Simon Kelleyb842bc92015-07-12 21:09:11 +01002104 check_log_writer(0);
2105 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01002106
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002107#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01002108 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00002109 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002110#endif
2111
Simon Kelley832af0b2007-01-21 20:01:28 +00002112#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01002113 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00002114#endif
2115
Floris Bos503c6092017-04-09 23:07:13 +01002116 if (fd != -1)
2117 {
2118 struct {
2119 struct ip ip;
2120 struct icmp icmp;
2121 } packet;
2122 struct sockaddr_in faddr;
2123 socklen_t len = sizeof(faddr);
2124
2125 if (poll_check(fd, POLLIN) &&
2126 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
2127 addr == faddr.sin_addr.s_addr &&
2128 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
2129 packet.icmp.icmp_seq == 0 &&
2130 packet.icmp.icmp_id == id)
2131 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002132 }
2133 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002134
Floris Bos503c6092017-04-09 23:07:13 +01002135 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01002136}
Geert Stappersba26d342020-04-06 15:42:39 +01002137#endif /* HAVE_DHCP */