blob: 0f73782b79ae0fa654c685baa79828be41523118 [file] [log] [blame]
Simon Kelley2a8710a2020-01-05 16:40:06 +00001/* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelleyc72daea2012-01-05 21:33:27 +000017/* Declare static char *compiler_opts in config.h */
18#define DNSMASQ_COMPILE_OPTS
19
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020#include "dnsmasq.h"
21
Simon Kelley5aabfc72007-08-29 11:24:47 +010022struct daemon *daemon;
23
Simon Kelley5aabfc72007-08-29 11:24:47 +010024static volatile pid_t pid = 0;
25static volatile int pipewrite;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000026
Simon Kelleyb842bc92015-07-12 21:09:11 +010027static int set_dns_listeners(time_t now);
28static void check_dns_listeners(time_t now);
Simon Kelley3be34542004-09-11 19:12:13 +010029static void sig_handler(int sig);
Simon Kelley5aabfc72007-08-29 11:24:47 +010030static void async_event(int pipe, time_t now);
Simon Kelleyc72daea2012-01-05 21:33:27 +000031static void fatal_event(struct event_desc *ev, char *msg);
32static int read_event(int fd, struct event_desc *evp, char **msg);
Simon Kelley47a95162014-07-08 22:22:02 +010033static void poll_resolv(int force, int do_reload, time_t now);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000034
35int main (int argc, char **argv)
36{
Simon Kelleyde379512004-06-22 20:23:33 +010037 int bind_fallback = 0;
Simon Kelley9009d742008-11-14 20:04:27 +000038 time_t now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000039 struct sigaction sigact;
Simon Kelley26128d22004-11-14 16:43:54 +000040 struct iname *if_tmp;
Simon Kelley1a6bca82008-07-11 11:11:42 +010041 int piperead, pipefd[2], err_pipe[2];
42 struct passwd *ent_pw = NULL;
Simon Kelleyc72daea2012-01-05 21:33:27 +000043#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +010044 uid_t script_uid = 0;
45 gid_t script_gid = 0;
Simon Kelley7622fc02009-06-04 20:32:05 +010046#endif
47 struct group *gp = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +010048 long i, max_fd = sysconf(_SC_OPEN_MAX);
Simon Kelley1a6bca82008-07-11 11:11:42 +010049 char *baduser = NULL;
50 int log_err;
Simon Kelley6b54d692018-02-08 21:23:05 +000051 int chown_warn = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010052#if defined(HAVE_LINUX_NETWORK)
53 cap_user_header_t hdr = NULL;
54 cap_user_data_t data = NULL;
Simon Kelley305ffb52019-03-16 18:17:17 +000055 int need_cap_net_admin = 0;
56 int need_cap_net_raw = 0;
57 int need_cap_net_bind_service = 0;
Simon Kelley3b3f4412013-10-11 16:33:28 +010058 char *bound_device = NULL;
59 int did_bind = 0;
Simon Kelley90d7c6b2019-09-14 21:13:03 +010060 struct server *serv;
Simon Kelley1a6bca82008-07-11 11:11:42 +010061#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010062#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000063 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010064 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010065#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010066#ifdef HAVE_TFTP
67 int tftp_prefix_missing = 0;
68#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010069
Simon Kelley824af852008-02-12 20:43:05 +000070#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000071 setlocale(LC_ALL, "");
72 bindtextdomain("dnsmasq", LOCALEDIR);
73 textdomain("dnsmasq");
74#endif
75
Simon Kelley9e4abcb2004-01-22 19:47:41 +000076 sigact.sa_handler = sig_handler;
77 sigact.sa_flags = 0;
78 sigemptyset(&sigact.sa_mask);
79 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010080 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000081 sigaction(SIGHUP, &sigact, NULL);
82 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000083 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010084 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000085 sigaction(SIGINT, &sigact, NULL);
86
Simon Kelleyfeba5c12004-07-27 20:28:58 +010087 /* ignore SIGPIPE */
88 sigact.sa_handler = SIG_IGN;
89 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000090
Simon Kelley5aabfc72007-08-29 11:24:47 +010091 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelley0506a5e2020-03-19 21:56:45 +000092
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010093 rand_init(); /* Must precede read_opts() */
94
Simon Kelley5aabfc72007-08-29 11:24:47 +010095 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000096
Simon Kelley0506a5e2020-03-19 21:56:45 +000097#ifdef HAVE_LINUX_NETWORK
98 daemon->kernel_version = kernel_version();
99#endif
100
Simon Kelley3be34542004-09-11 19:12:13 +0100101 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +0000102 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +0000103
Simon Kelleyd3a8b392015-12-23 12:27:37 +0000104 /* Min buffer size: we check after adding each record, so there must be
105 memory for the largest packet, and the largest record so the
106 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
107 This might be increased is EDNS packet size if greater than the minimum. */
108 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000109 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000110
Simon Kelleyc72daea2012-01-05 21:33:27 +0000111 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000112 if (option_bool(OPT_EXTRALOG))
113 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000114
115#ifdef HAVE_DNSSEC
116 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000117 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100118 /* Note that both /000 and '.' are allowed within labels. These get
119 represented in presentation format using NAME_ESCAPE as an escape
120 character when in DNSSEC mode.
121 In theory, if all the characters in a name were /000 or
122 '.' or NAME_ESCAPE then all would have to be escaped, so the
123 presentation format would be twice as long as the spec.
124
125 daemon->namebuff was previously allocated by the option-reading
126 code before we knew if we're in DNSSEC mode, so reallocate here. */
127 free(daemon->namebuff);
128 daemon->namebuff = safe_malloc(MAXDNAME * 2);
129 daemon->keyname = safe_malloc(MAXDNAME * 2);
130 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000131 /* one char flag per possible RR in answer section (may get extended). */
132 daemon->rr_status_sz = 64;
Simon Kelleyae7a3b92019-09-03 14:40:47 +0100133 daemon->rr_status = safe_malloc(sizeof(*daemon->rr_status) * daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000134 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000135#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000136
Simon Kelley7622fc02009-06-04 20:32:05 +0100137#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100138 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000139 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000140 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100141 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000142 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100143#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000144
Simon Kelley0541a1a2020-03-02 17:10:25 +0000145 /* Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
Simon Kelleya2761752012-01-18 16:07:21 +0000146 otherwise file descriptors we create can end up being 0, 1, or 2
147 and then get accidentally closed later when we make 0, 1, and 2
148 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
149 but it's not guaranteed. By opening /dev/null three times, we
150 ensure that we're not using those fds for real stuff. */
Simon Kelley0541a1a2020-03-02 17:10:25 +0000151 for (i = 0; i < 3; i++)
152 open("/dev/null", O_RDWR);
153
154 /* Close any file descriptors we inherited apart from std{in|out|err} */
155 close_fds(max_fd, -1, -1, -1);
156
Simon Kelley801ca9a2012-03-06 19:30:17 +0000157#ifndef HAVE_LINUX_NETWORK
158# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000159 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100160 {
161 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000162 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100163 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000164# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100165
166 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100167 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100168 {
169 bind_fallback = 1;
170 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100171 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100172 }
Simon Kelley04918052015-01-26 11:23:43 +0000173#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000174
Simon Kelley04918052015-01-26 11:23:43 +0000175#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000176 if (daemon->dynamic_dirs)
177 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100178#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100179
Simon Kelley0744ca62014-01-25 16:40:15 +0000180 if (option_bool(OPT_DNSSEC_VALID))
181 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000182#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000183 struct ds_config *ds;
184
185 /* Must have at least a root trust anchor, or the DNSSEC code
186 can loop forever. */
187 for (ds = daemon->ds; ds; ds = ds->next)
188 if (ds->name[0] == 0)
189 break;
190
191 if (!ds)
192 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000193
194 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000195 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000196#else
197 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000198#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000199 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000200
Simon Kelley832af0b2007-01-21 20:01:28 +0000201#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100202 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100203 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000204#endif
205
Simon Kelley7de060b2011-08-26 17:24:52 +0100206#ifdef HAVE_CONNTRACK
207 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000208 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100209#else
210 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000211 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100212#endif
213
Simon Kelley824af852008-02-12 20:43:05 +0000214#ifdef HAVE_SOLARIS_NETWORK
215 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000216 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000217#endif
218
Simon Kelley572b41e2011-02-18 18:11:18 +0000219#ifdef __ANDROID__
220 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000221 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000222#endif
223
Simon Kelley4820dce2012-12-18 18:30:30 +0000224#ifndef HAVE_AUTH
Simon Kelley08933472018-10-05 16:34:35 +0100225 if (daemon->auth_zones)
Simon Kelley4820dce2012-12-18 18:30:30 +0000226 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
227#endif
228
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100229#ifndef HAVE_LOOP
230 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000231 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100232#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000233
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100234#ifndef HAVE_UBUS
235 if (option_bool(OPT_UBUS))
236 die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
237#endif
238
Hans Dedecker926332a2016-01-23 10:48:12 +0000239 if (daemon->max_port < daemon->min_port)
240 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
241
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100242 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000243
Simon Kelley08933472018-10-05 16:34:35 +0100244 if (daemon->auth_zones)
245 {
246 if (!daemon->authserver)
247 die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
248
249 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000250#ifdef HAVE_BROKEN_RTC
Martin Schiller53792c92018-10-08 14:55:19 +0200251 if (daemon->soa_sn == 0)
Simon Kelley08933472018-10-05 16:34:35 +0100252 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000253#else
Simon Kelley08933472018-10-05 16:34:35 +0100254 if (daemon->soa_sn == 0)
255 daemon->soa_sn = now;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000256#endif
Simon Kelley08933472018-10-05 16:34:35 +0100257 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000258
Simon Kelleyff7eea22013-09-04 18:01:38 +0100259#ifdef HAVE_DHCP6
260 if (daemon->dhcp6)
261 {
262 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000263
Simon Kelleyff7eea22013-09-04 18:01:38 +0100264 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000265 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100266 if (context->flags & CONTEXT_DHCP)
267 daemon->doing_dhcp6 = 1;
268 if (context->flags & CONTEXT_RA)
269 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000270#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100271 if (context->flags & CONTEXT_TEMPLATE)
272 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000273#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000274 }
Simon Kelley1f776932012-12-16 19:46:08 +0000275 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100276#endif
277
278#ifdef HAVE_DHCP
279 /* Note that order matters here, we must call lease_init before
280 creating any file descriptors which shouldn't be leaked
281 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000282 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000283 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000284 conditions below. */
285 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000286 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100287 {
288 dhcp_common_init();
289 if (daemon->dhcp || daemon->doing_dhcp6)
290 lease_init(now);
291 }
292
293 if (daemon->dhcp || daemon->relay4)
Simon Kelley305ffb52019-03-16 18:17:17 +0000294 {
295 dhcp_init();
296# ifdef HAVE_LINUX_NETWORK
297 if (!option_bool(OPT_NO_PING))
298 need_cap_net_raw = 1;
299 need_cap_net_admin = 1;
300# endif
301 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100302
303# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100304 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelley305ffb52019-03-16 18:17:17 +0000305 {
306 ra_init(now);
307# ifdef HAVE_LINUX_NETWORK
308 need_cap_net_raw = 1;
309 need_cap_net_admin = 1;
310# endif
311 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100312
313 if (daemon->doing_dhcp6 || daemon->relay6)
314 dhcp6_init();
315# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000316
Simon Kelley7622fc02009-06-04 20:32:05 +0100317#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100318
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000319#ifdef HAVE_IPSET
320 if (daemon->ipsets)
Simon Kelley305ffb52019-03-16 18:17:17 +0000321 {
322 ipset_init();
323# ifdef HAVE_LINUX_NETWORK
324 need_cap_net_admin = 1;
325# endif
326 }
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000327#endif
328
Simon Kelley1ee9be42013-12-09 16:50:19 +0000329#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000330 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000331#elif defined(HAVE_BSD_NETWORK)
332 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000333#endif
334
Simon Kelley1ee9be42013-12-09 16:50:19 +0000335 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
336 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
337
Simon Kelley115ac3e2013-05-20 11:28:32 +0100338 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100339 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000340
Simon Kelley54dd3932012-06-20 11:23:38 +0100341 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100342 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100343 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100344
345 if (!option_bool(OPT_CLEVERBIND))
346 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
347 if (if_tmp->name && !if_tmp->used)
348 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100349
350#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
351 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100352 bound_device = whichdevice();
353
Simon Kelley9380ba72012-04-16 14:41:56 +0100354 if (daemon->dhcp)
355 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100356 if (!daemon->relay4 && bound_device)
357 {
358 bindtodevice(bound_device, daemon->dhcpfd);
359 did_bind = 1;
360 }
361 if (daemon->enable_pxe && bound_device)
362 {
363 bindtodevice(bound_device, daemon->pxefd);
364 did_bind = 1;
365 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100366 }
367#endif
368
369#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100370 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
371 {
372 bindtodevice(bound_device, daemon->dhcp6fd);
373 did_bind = 1;
374 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100375#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100376 }
Simon Kelley28866e92011-02-14 20:19:14 +0000377 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100378 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000379
380#ifdef HAVE_DHCP6
381 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100382 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000383 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000384
385 /* After netlink_init() and before create_helper() */
386 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000387#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100388
Simon Kelley824af852008-02-12 20:43:05 +0000389 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000390 {
391 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000392
Simon Kelley82e3f452014-01-31 21:05:48 +0000393 blockdata_init();
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000394 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000395
Simon Kelley04918052015-01-26 11:23:43 +0000396#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000397 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
398 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000399 inotify_dnsmasq_init();
400 else
401 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000402#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100403
404 if (daemon->dump_file)
405#ifdef HAVE_DUMPFILE
406 dump_init();
407 else
408 daemon->dumpfd = -1;
409#else
410 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
411#endif
412
Simon Kelley28866e92011-02-14 20:19:14 +0000413 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100414#ifdef HAVE_DBUS
415 {
416 char *err;
417 daemon->dbus = NULL;
418 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100419 if ((err = dbus_init()))
420 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100421 }
422#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100423 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100424#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100425
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100426 if (option_bool(OPT_UBUS))
427#ifdef HAVE_UBUS
428 {
429 daemon->ubus = NULL;
430 ubus_init();
431 }
432#else
433 die(_("UBus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
434#endif
435
Simon Kelley824af852008-02-12 20:43:05 +0000436 if (daemon->port != 0)
437 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100438
Simon Kelleyc72daea2012-01-05 21:33:27 +0000439#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100440 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000441 if ((daemon->dhcp || daemon->dhcp6) &&
442 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000443 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100444 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000445 struct passwd *scr_pw;
446
447 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100448 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000449 script_uid = scr_pw->pw_uid;
450 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100451 }
452 else
453 baduser = daemon->scriptuser;
454 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100455#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000456
Simon Kelley1a6bca82008-07-11 11:11:42 +0100457 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
458 baduser = daemon->username;
459 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
460 baduser = daemon->groupname;
461
462 if (baduser)
463 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000464
Simon Kelley1a6bca82008-07-11 11:11:42 +0100465 /* implement group defaults, "dip" if available, or group associated with uid */
466 if (!daemon->group_set && !gp)
467 {
468 if (!(gp = getgrnam(CHGRP)) && ent_pw)
469 gp = getgrgid(ent_pw->pw_gid);
470
471 /* for error message */
472 if (gp)
473 daemon->groupname = gp->gr_name;
474 }
475
476#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000477 /* We keep CAP_NETADMIN (for ARP-injection) and
478 CAP_NET_RAW (for icmp) if we're doing dhcp,
479 if we have yet to bind ports because of DAD,
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100480 or we're doing it dynamically, we need CAP_NET_BIND_SERVICE. */
Simon Kelley305ffb52019-03-16 18:17:17 +0000481 if ((is_dad_listeners() || option_bool(OPT_CLEVERBIND)) &&
482 (option_bool(OPT_TFTP) || (daemon->port != 0 && daemon->port <= 1024)))
483 need_cap_net_bind_service = 1;
484
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100485 /* usptream servers which bind to an interface call SO_BINDTODEVICE
Simon Kelleydefd6b12019-09-16 23:02:12 +0100486 for each TCP connection, so need CAP_NET_RAW */
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100487 for (serv = daemon->servers; serv; serv = serv->next)
488 if (serv->interface[0] != 0)
Simon Kelleydefd6b12019-09-16 23:02:12 +0100489 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100490
491 /* If we're doing Dbus or UBus, the above can be set dynamically,
492 (as can ports) so always (potentially) needed. */
493#ifdef HAVE_DBUS
494 if (option_bool(OPT_DBUS))
495 {
496 need_cap_net_bind_service = 1;
Simon Kelleydefd6b12019-09-16 23:02:12 +0100497 need_cap_net_raw = 1;
Simon Kelley90d7c6b2019-09-14 21:13:03 +0100498 }
499#endif
500
501#ifdef HAVE_UBUS
502 if (option_bool(OPT_UBUS))
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
Simon Kelley1a6bca82008-07-11 11:11:42 +0100509 /* determine capability API version here, while we can still
510 call safe_malloc */
Simon Kelley305ffb52019-03-16 18:17:17 +0000511 int capsize = 1; /* for header version 1 */
512 char *fail = NULL;
513
514 hdr = safe_malloc(sizeof(*hdr));
515
516 /* find version supported by kernel */
517 memset(hdr, 0, sizeof(*hdr));
518 capget(hdr, NULL);
519
520 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100521 {
Simon Kelley305ffb52019-03-16 18:17:17 +0000522 /* if unknown version, use largest supported version (3) */
523 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
524 hdr->version = LINUX_CAPABILITY_VERSION_3;
525 capsize = 2;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100526 }
Simon Kelley305ffb52019-03-16 18:17:17 +0000527
528 data = safe_malloc(sizeof(*data) * capsize);
529 capget(hdr, data); /* Get current values, for verification */
530
531 if (need_cap_net_admin && !(data->permitted & (1 << CAP_NET_ADMIN)))
532 fail = "NET_ADMIN";
533 else if (need_cap_net_raw && !(data->permitted & (1 << CAP_NET_RAW)))
534 fail = "NET_RAW";
535 else if (need_cap_net_bind_service && !(data->permitted & (1 << CAP_NET_BIND_SERVICE)))
536 fail = "NET_BIND_SERVICE";
537
538 if (fail)
539 die(_("process is missing required capability %s"), fail, EC_MISC);
540
541 /* Now set bitmaps to set caps after daemonising */
542 memset(data, 0, sizeof(*data) * capsize);
543
544 if (need_cap_net_admin)
545 data->effective |= (1 << CAP_NET_ADMIN);
546 if (need_cap_net_raw)
547 data->effective |= (1 << CAP_NET_RAW);
548 if (need_cap_net_bind_service)
549 data->effective |= (1 << CAP_NET_BIND_SERVICE);
550
551 data->permitted = data->effective;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100552#endif
553
Simon Kelley5aabfc72007-08-29 11:24:47 +0100554 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100555 in a race-free manner and another to carry errors to daemon-invoking process */
556 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100557
558 piperead = pipefd[0];
559 pipewrite = pipefd[1];
560 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000561 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100562
563 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100564
Simon Kelley28866e92011-02-14 20:19:14 +0000565 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000566 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000567 /* The following code "daemonizes" the process.
568 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100569
Simon Kelley9e038942008-05-30 20:06:34 +0100570 if (chdir("/") != 0)
571 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
572
Simon Kelley28866e92011-02-14 20:19:14 +0000573 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100574 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100575 pid_t pid;
576
Simon Kelley1a6bca82008-07-11 11:11:42 +0100577 /* pipe to carry errors back to original process.
578 When startup is complete we close this and the process terminates. */
579 safe_pipe(err_pipe, 0);
580
Simon Kelley7622fc02009-06-04 20:32:05 +0100581 if ((pid = fork()) == -1)
582 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000583 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100584
Simon Kelley5aabfc72007-08-29 11:24:47 +0100585 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100586 {
587 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000588 char *msg;
589
Simon Kelley1a6bca82008-07-11 11:11:42 +0100590 /* close our copy of write-end */
Simon Kelley5fc639c2019-03-29 21:29:43 +0000591 close(err_pipe[1]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100592
593 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000594 if (read_event(err_pipe[0], &ev, &msg))
595 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100596
597 _exit(EC_GOOD);
598 }
599
Simon Kelley5fc639c2019-03-29 21:29:43 +0000600 close(err_pipe[0]);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100601
602 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100603
604 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100605
606 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000607 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100608
609 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100610 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100611 }
Simon Kelley9e038942008-05-30 20:06:34 +0100612
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000613 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100614 if (daemon->runfile)
615 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100616 int fd, err = 0;
617
618 sprintf(daemon->namebuff, "%d\n", (int) getpid());
619
620 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
621 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
622 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
623 extent that an attacker running as the unprivileged user could replace the pidfile with a
624 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
625
Josh Soref730c6742017-02-06 16:14:04 +0000626 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100627 ensuring that the open() fails should there be any existing file (because the unlink() failed,
628 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
629 attack can succeed.
630
631 Any compromise of the non-privileged user still theoretically allows the pid-file to be
632 replaced whilst dnsmasq is running. The worst that could allow is that the usual
633 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
634
635 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
636 failure to write the pid-file.
637 */
638
639 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100640
Simon Kelley79cfefd2012-09-02 13:29:51 +0100641 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 +0100642 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100643 /* only complain if started as root */
644 if (getuid() == 0)
645 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100646 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100647 else
648 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000649 /* We're still running as root here. Change the ownership of the PID file
650 to the user we will be running as. Note that this is not to allow
651 us to delete the file, since that depends on the permissions
652 of the directory containing the file. That directory will
653 need to by owned by the dnsmasq user, and the ownership of the
654 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000655 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
656 chown_warn = errno;
657
658 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100659 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000660 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000661 {
Simon Kelley5fc639c2019-03-29 21:29:43 +0000662 if (close(fd) == -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000663 err = 1;
664 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100665 }
666
667 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100668 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000669 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100670 _exit(0);
671 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000672 }
Simon Kelley16972692006-10-16 20:04:18 +0100673 }
674
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100675 log_err = log_start(ent_pw, err_pipe[1]);
676
Simon Kelley28866e92011-02-14 20:19:14 +0000677 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100678 {
679 /* open stdout etc to /dev/null */
680 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000681 if (nullfd != -1)
682 {
683 dup2(nullfd, STDOUT_FILENO);
684 dup2(nullfd, STDERR_FILENO);
685 dup2(nullfd, STDIN_FILENO);
686 close(nullfd);
687 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100688 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100689
Simon Kelley1a6bca82008-07-11 11:11:42 +0100690 /* if we are to run scripts, we need to fork a helper before dropping root. */
691 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000692#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000693 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000694 (daemon->lease_change_command || daemon->luascript))
695 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100696#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100697
Simon Kelley28866e92011-02-14 20:19:14 +0000698 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100699 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100700 int bad_capabilities = 0;
701 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100702
Josh Soref730c6742017-02-06 16:14:04 +0000703 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100704 if (gp &&
705 (setgroups(0, &dummy) == -1 ||
706 setgid(gp->gr_gid) == -1))
707 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000708 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100709 _exit(0);
710 }
711
Simon Kelley7cebd202006-05-06 14:13:33 +0100712 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100713 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100714#if defined(HAVE_LINUX_NETWORK)
Simon Kelley305ffb52019-03-16 18:17:17 +0000715 /* Need to be able to drop root. */
716 data->effective |= (1 << CAP_SETUID);
717 data->permitted |= (1 << CAP_SETUID);
Simon Kelley16972692006-10-16 20:04:18 +0100718 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000719 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100720 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100721
Simon Kelley7622fc02009-06-04 20:32:05 +0100722#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000723 /* http://developers.sun.com/solaris/articles/program_privileges.html */
724 priv_set_t *priv_set;
725
726 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
727 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
728 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
729 bad_capabilities = errno;
730
731 if (priv_set && bad_capabilities == 0)
732 {
733 priv_inverse(priv_set);
734
735 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
736 bad_capabilities = errno;
737 }
738
739 if (priv_set)
740 priv_freeset(priv_set);
741
Simon Kelley824af852008-02-12 20:43:05 +0000742#endif
743
Simon Kelley1a6bca82008-07-11 11:11:42 +0100744 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100745 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000746 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100747 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100748 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100749
750 /* finally drop root */
751 if (setuid(ent_pw->pw_uid) == -1)
752 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000753 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100754 _exit(0);
755 }
756
757#ifdef HAVE_LINUX_NETWORK
Simon Kelley305ffb52019-03-16 18:17:17 +0000758 data->effective &= ~(1 << CAP_SETUID);
759 data->permitted &= ~(1 << CAP_SETUID);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100760
Simon Kelley305ffb52019-03-16 18:17:17 +0000761 /* lose the setuid capability */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100762 if (capset(hdr, data) == -1)
763 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000764 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100765 _exit(0);
766 }
767#endif
768
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000769 }
Simon Kelley849a8352006-06-09 21:02:31 +0100770 }
Simon Kelley16972692006-10-16 20:04:18 +0100771
Simon Kelley16972692006-10-16 20:04:18 +0100772#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000773 free(hdr);
774 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000775 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000776 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100777#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100778
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100779#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100780 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100781 {
782 DIR *dir;
783 struct tftp_prefix *p;
784
785 if (daemon->tftp_prefix)
786 {
787 if (!((dir = opendir(daemon->tftp_prefix))))
788 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100789 tftp_prefix_missing = 1;
790 if (!option_bool(OPT_TFTP_NO_FAIL))
791 {
792 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
793 _exit(0);
794 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100795 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100796 else
797 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100798 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100799
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100800 for (p = daemon->if_prefix; p; p = p->next)
801 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100802 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100803 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100804 {
805 p->missing = 1;
806 if (!option_bool(OPT_TFTP_NO_FAIL))
807 {
808 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
809 _exit(0);
810 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100811 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100812 else
813 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100814 }
815 }
816#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100817
Simon Kelley824af852008-02-12 20:43:05 +0000818 if (daemon->port == 0)
819 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000820 else
821 {
822 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100823 {
824 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
825 if (daemon->cachesize > 10000)
826 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
827 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000828 else
829 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
830
831 if (option_bool(OPT_LOCAL_SERVICE))
832 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
833 }
Simon Kelley16972692006-10-16 20:04:18 +0100834
Simon Kelleyf2621c72007-04-29 19:47:21 +0100835 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000836
837 if (chown_warn != 0)
838 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100839
Simon Kelley3d8df262005-08-29 12:19:27 +0100840#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000841 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100842 {
843 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100844 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100845 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100846 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100847 }
848#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000849
Jan Willem Janssena2b82202019-03-25 12:42:23 +0100850#ifdef HAVE_UBUS
851 if (option_bool(OPT_UBUS))
852 {
853 if (daemon->ubus)
854 my_syslog(LOG_INFO, _("UBus support enabled: connected to system bus"));
855 else
856 my_syslog(LOG_INFO, _("UBus support enabled: bus connection pending"));
857 }
858#endif
859
Simon Kelley1d97ac42014-01-31 11:12:27 +0000860#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000861 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000862 {
Simon Kelley360f2512015-03-07 18:28:06 +0000863 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100864 struct ds_config *ds;
865
Simon Kelley360f2512015-03-07 18:28:06 +0000866 /* Delay creating the timestamp file until here, after we've changed user, so that
867 it has the correct owner to allow updating the mtime later.
868 This means we have to report fatal errors via the pipe. */
869 if ((rc = setup_timestamp()) == -1)
870 {
871 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
872 _exit(0);
873 }
874
Simon Kelleya6918532018-04-15 16:20:52 +0100875 if (option_bool(OPT_DNSSEC_IGN_NS))
876 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
877 else
878 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000879
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100880 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
881 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000882 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000883
884 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000885 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100886
887 for (ds = daemon->ds; ds; ds = ds->next)
888 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
889 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000890 }
Simon Kelleydb737462014-01-31 10:32:45 +0000891#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100892
Simon Kelley1a6bca82008-07-11 11:11:42 +0100893 if (log_err != 0)
894 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
895 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000896
Simon Kelleyde379512004-06-22 20:23:33 +0100897 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100898 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100899
Simon Kelleyf7029f52013-11-21 15:09:09 +0000900 if (option_bool(OPT_NOWILD))
901 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000902 else if (!option_bool(OPT_CLEVERBIND))
903 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000904
905 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100906
Simon Kelley28866e92011-02-14 20:19:14 +0000907 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000908 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
909 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100910 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100911
Simon Kelley28866e92011-02-14 20:19:14 +0000912 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100913 {
914 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100915 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100916 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000917 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100918 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100919 }
920
Simon Kelleyf2621c72007-04-29 19:47:21 +0100921 if (daemon->max_logs != 0)
922 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000923
Simon Kelleyf2621c72007-04-29 19:47:21 +0100924
Simon Kelley7622fc02009-06-04 20:32:05 +0100925#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000926 for (context = daemon->dhcp; context; context = context->next)
927 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100928
Simon Kelleyff7eea22013-09-04 18:01:38 +0100929 for (relay = daemon->relay4; relay; relay = relay->next)
930 log_relay(AF_INET, relay);
931
Simon Kelley1f776932012-12-16 19:46:08 +0000932# ifdef HAVE_DHCP6
933 for (context = daemon->dhcp6; context; context = context->next)
934 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000935
Simon Kelleyff7eea22013-09-04 18:01:38 +0100936 for (relay = daemon->relay6; relay; relay = relay->next)
937 log_relay(AF_INET6, relay);
938
Simon Kelley1f776932012-12-16 19:46:08 +0000939 if (daemon->doing_dhcp6 || daemon->doing_ra)
940 dhcp_construct_contexts(now);
941
942 if (option_bool(OPT_RA))
943 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
944# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000945
Simon Kelley3b3f4412013-10-11 16:33:28 +0100946# ifdef HAVE_LINUX_NETWORK
947 if (did_bind)
948 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
949# endif
950
Josh Soref730c6742017-02-06 16:14:04 +0000951 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000952 if (daemon->dhcp || daemon->doing_dhcp6)
953 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000954#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000955
Simon Kelley832af0b2007-01-21 20:01:28 +0000956#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000957 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100958 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100959 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000960
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000961 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100962 daemon->tftp_prefix ? _("root is ") : _("enabled"),
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000963 daemon->tftp_prefix ? daemon->tftp_prefix : "",
964 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "",
965 option_bool(OPT_SINGLE_PORT) ? _("single port mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100966
Stefan Tomanek30d08792015-03-31 22:32:11 +0100967 if (tftp_prefix_missing)
968 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100969
Stefan Tomanek30d08792015-03-31 22:32:11 +0100970 for (p = daemon->if_prefix; p; p = p->next)
971 if (p->missing)
972 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
973
Simon Kelley832af0b2007-01-21 20:01:28 +0000974 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100975 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000976 a single file will be sent to may clients (the file only needs
977 one fd). */
978
979 max_fd -= 30; /* use other than TFTP */
980
981 if (max_fd < 0)
982 max_fd = 5;
Simon Kelley2ac4cf02020-01-06 23:39:33 +0000983 else if (max_fd < 100 && !option_bool(OPT_SINGLE_PORT))
Simon Kelley832af0b2007-01-21 20:01:28 +0000984 max_fd = max_fd/2;
985 else
986 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000987
988 /* if we have to use a limited range of ports,
989 that will limit the number of transfers */
990 if (daemon->start_tftp_port != 0 &&
991 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
992 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000993
994 if (daemon->tftp_max > max_fd)
995 {
996 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100997 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100998 _("restricting maximum simultaneous TFTP transfers to %d"),
999 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +00001000 }
1001 }
1002#endif
1003
Simon Kelley1a6bca82008-07-11 11:11:42 +01001004 /* finished start-up - release original process */
1005 if (err_pipe[1] != -1)
Simon Kelley5fc639c2019-03-29 21:29:43 +00001006 close(err_pipe[1]);
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001007
Simon Kelley824af852008-02-12 20:43:05 +00001008 if (daemon->port != 0)
1009 check_servers();
1010
Simon Kelley7cebd202006-05-06 14:13:33 +01001011 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +01001012
1013 daemon->pipe_to_parent = -1;
1014 for (i = 0; i < MAX_PROCS; i++)
1015 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +01001016
Simon Kelley04918052015-01-26 11:23:43 +00001017#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +00001018 /* Using inotify, have to select a resolv file at startup */
1019 poll_resolv(1, 0, now);
1020#endif
1021
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001022 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001023 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001024 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001025
Simon Kelleyb842bc92015-07-12 21:09:11 +01001026 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001027
Simon Kelley16972692006-10-16 20:04:18 +01001028 /* if we are out of resources, find how long we have to wait
1029 for some to come free, we'll loop around then and restart
1030 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001031 if ((t = set_dns_listeners(now)) != 0)
1032 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +01001033
Simon Kelley832af0b2007-01-21 20:01:28 +00001034 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
1035 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +00001036 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +01001037 timeout = 250;
1038
Simon Kelley74c95c22011-10-19 09:33:39 +01001039 /* Wake every second whilst waiting for DAD to complete */
1040 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001041 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001042
Simon Kelley832af0b2007-01-21 20:01:28 +00001043#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +01001044 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001045#endif
1046
1047#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001048 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001049 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001050#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001051
Simon Kelley7622fc02009-06-04 20:32:05 +01001052#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001053 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001054 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001055 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +00001056 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001057 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001058 }
Simon Kelley7622fc02009-06-04 20:32:05 +01001059#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001060
Simon Kelley52b92f42012-01-22 16:05:15 +00001061#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +01001062 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001063 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001064
Simon Kelley1f776932012-12-16 19:46:08 +00001065 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001066 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +00001067#endif
Simon Kelley04918052015-01-26 11:23:43 +00001068
1069#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001070 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001071 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +00001072#endif
1073
1074#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001075 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +00001076#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001077 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001078#endif
Simon Kelley193de4a2014-12-10 17:32:16 +00001079
Simon Kelleyb842bc92015-07-12 21:09:11 +01001080 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001081
Simon Kelley33702ab2015-12-28 23:17:15 +00001082#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001083# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001084 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001085# endif
1086
Simon Kelley1e505122016-01-25 21:29:23 +00001087 /* Refresh cache */
1088 if (option_bool(OPT_SCRIPT_ARP))
1089 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001090 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001091
Simon Kelleya9530962012-03-20 22:07:35 +00001092# ifdef HAVE_TFTP
1093 while (helper_buf_empty() && do_tftp_script_run());
1094# endif
1095
Simon Kelley16972692006-10-16 20:04:18 +01001096 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001097 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001098#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001099 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001100# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001101 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001102# endif
1103
Simon Kelleyb633de92016-01-06 22:51:17 +00001104 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001105
1106# ifdef HAVE_TFTP
1107 while (do_tftp_script_run());
1108# endif
1109
Simon Kelley5aabfc72007-08-29 11:24:47 +01001110#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001111
Simon Kelley7622fc02009-06-04 20:32:05 +01001112
Simon Kelley66f62652020-01-05 16:21:24 +00001113 /* must do this just before do_poll(), when we know no
Simon Kelleyf2621c72007-04-29 19:47:21 +01001114 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001115 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001116
Simon Kelleyb842bc92015-07-12 21:09:11 +01001117 if (do_poll(timeout) < 0)
1118 continue;
1119
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001120 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001121
Simon Kelleyb842bc92015-07-12 21:09:11 +01001122 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001123
1124 /* prime. */
1125 enumerate_interfaces(1);
1126
Simon Kelley74c95c22011-10-19 09:33:39 +01001127 /* Check the interfaces to see if any have exited DAD state
1128 and if so, bind the address. */
1129 if (is_dad_listeners())
1130 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001131 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001132 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1133 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001134 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001135 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001136
Simon Kelley1ee9be42013-12-09 16:50:19 +00001137#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001138 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001139 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001140#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001141 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001142 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001143#endif
1144
Simon Kelley04918052015-01-26 11:23:43 +00001145#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001146 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001147 {
1148 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1149 poll_resolv(1, 1, now);
1150 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001151#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001152 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001153 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001154 if (daemon->last_resolv == 0 ||
1155 difftime(now, daemon->last_resolv) > 1.0 ||
1156 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001157 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001158 /* poll_resolv doesn't need to reload first time through, since
1159 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001160
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001161 poll_resolv(0, daemon->last_resolv != 0, now);
1162 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001163 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001164#endif
1165
Simon Kelleyb842bc92015-07-12 21:09:11 +01001166 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001167 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001168
Simon Kelley3d8df262005-08-29 12:19:27 +01001169#ifdef HAVE_DBUS
1170 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001171 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001172 {
1173 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001174 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001175 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001176 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001177 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001178 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001179 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001180#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001181
1182#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001183 if (option_bool(OPT_UBUS))
Jan Willem Janssena2b82202019-03-25 12:42:23 +01001184 {
1185 /* if we didn't create a UBus connection, retry now. */
1186 if (!daemon->ubus)
1187 {
1188 ubus_init();
1189 }
1190
1191 check_ubus_listeners();
1192 }
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001193#endif
1194
Simon Kelleyb842bc92015-07-12 21:09:11 +01001195 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001196
1197#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001198 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001199#endif
1200
Simon Kelley7622fc02009-06-04 20:32:05 +01001201#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001202 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001203 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001204 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001205 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001206 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001207 dhcp_packet(now, 1);
1208 }
Simon Kelley16972692006-10-16 20:04:18 +01001209
Simon Kelley52b92f42012-01-22 16:05:15 +00001210#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001211 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001212 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001213
Simon Kelleyb842bc92015-07-12 21:09:11 +01001214 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001215 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001216#endif
1217
Simon Kelley1f15b812009-10-13 17:49:32 +01001218# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001219 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001220 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001221# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001222#endif
1223
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001224 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001225}
1226
Simon Kelley3be34542004-09-11 19:12:13 +01001227static void sig_handler(int sig)
1228{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001229 if (pid == 0)
1230 {
Simon Kelley16972692006-10-16 20:04:18 +01001231 /* ignore anything other than TERM during startup
1232 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001233 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001234 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001235 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001236 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001237 {
Simon Kelley16972692006-10-16 20:04:18 +01001238 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001239 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001240 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001241 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001242 else
1243 {
1244 /* master process */
1245 int event, errsave = errno;
1246
1247 if (sig == SIGHUP)
1248 event = EVENT_RELOAD;
1249 else if (sig == SIGCHLD)
1250 event = EVENT_CHILD;
1251 else if (sig == SIGALRM)
1252 event = EVENT_ALARM;
1253 else if (sig == SIGTERM)
1254 event = EVENT_TERM;
1255 else if (sig == SIGUSR1)
1256 event = EVENT_DUMP;
1257 else if (sig == SIGUSR2)
1258 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001259 else if (sig == SIGINT)
1260 {
1261 /* Handle SIGINT normally in debug mode, so
1262 ctrl-c continues to operate. */
1263 if (option_bool(OPT_DEBUG))
1264 exit(EC_MISC);
1265 else
1266 event = EVENT_TIME;
1267 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001268 else
1269 return;
1270
Simon Kelleyc72daea2012-01-05 21:33:27 +00001271 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001272 errno = errsave;
1273 }
Simon Kelley3be34542004-09-11 19:12:13 +01001274}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001275
Simon Kelley353ae4d2012-03-19 20:07:51 +00001276/* now == 0 -> queue immediate callback */
1277void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001278{
Simon Kelley884a6df2012-03-20 16:20:22 +00001279 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001280 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001281 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1282 if ((now == 0 || difftime(event, now) <= 0.0))
1283 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1284 else
1285 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001286 }
Simon Kelley741c2952012-02-25 13:09:18 +00001287}
1288
Simon Kelley47a95162014-07-08 22:22:02 +01001289void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001290{
Simon Kelley47a95162014-07-08 22:22:02 +01001291 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001292}
1293
Simon Kelleyc72daea2012-01-05 21:33:27 +00001294void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001295{
1296 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001297 struct iovec iov[2];
1298
Simon Kelley5aabfc72007-08-29 11:24:47 +01001299 ev.event = event;
1300 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001301 ev.msg_sz = msg ? strlen(msg) : 0;
1302
1303 iov[0].iov_base = &ev;
1304 iov[0].iov_len = sizeof(ev);
1305 iov[1].iov_base = msg;
1306 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001307
1308 /* error pipe, debug mode. */
1309 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001310 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001311 else
1312 /* pipe is non-blocking and struct event_desc is smaller than
1313 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001314 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001315}
Simon Kelley3d8df262005-08-29 12:19:27 +01001316
Simon Kelleyc72daea2012-01-05 21:33:27 +00001317/* NOTE: the memory used to return msg is leaked: use msgs in events only
1318 to describe fatal errors. */
1319static int read_event(int fd, struct event_desc *evp, char **msg)
1320{
1321 char *buf;
1322
1323 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1324 return 0;
1325
1326 *msg = NULL;
1327
1328 if (evp->msg_sz != 0 &&
1329 (buf = malloc(evp->msg_sz + 1)) &&
1330 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1331 {
1332 buf[evp->msg_sz] = 0;
1333 *msg = buf;
1334 }
1335
1336 return 1;
1337}
1338
1339static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001340{
1341 errno = ev->data;
1342
1343 switch (ev->event)
1344 {
1345 case EVENT_DIE:
1346 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001347
1348 case EVENT_FORK_ERR:
1349 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001350
1351 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001352 case EVENT_PIPE_ERR:
1353 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001354
1355 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001356 case EVENT_CAP_ERR:
1357 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1358
Simon Kelleye7a4af82018-02-16 21:27:35 +00001359 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001360 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001361 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001362
Simon Kelleye7a4af82018-02-16 21:27:35 +00001363 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001364 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001365 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001366
1367 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001368 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001369 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001370
Simon Kelleye7a4af82018-02-16 21:27:35 +00001371 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001372 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001373 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001374
1375 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001376 case EVENT_LUA_ERR:
1377 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001378
Simon Kelleye7a4af82018-02-16 21:27:35 +00001379 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001380 case EVENT_TFTP_ERR:
1381 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001382
1383 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001384 case EVENT_TIME_ERR:
1385 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001386 }
1387}
1388
Simon Kelley5aabfc72007-08-29 11:24:47 +01001389static void async_event(int pipe, time_t now)
1390{
1391 pid_t p;
1392 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001393 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001394 char *msg;
1395
1396 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1397 to describe fatal errors. */
1398
1399 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001400 switch (ev.event)
1401 {
1402 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001403 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001404
Simon Kelleye98bd522014-03-28 20:41:23 +00001405 /* fall through */
1406
1407 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001408 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001409
Simon Kelley7b1eae42014-02-20 13:43:28 +00001410 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001411 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001412 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1413 {
1414 reload_servers(daemon->resolv_files->name);
1415 check = 1;
1416 }
1417
1418 if (daemon->servers_file)
1419 {
1420 read_servers_file();
1421 check = 1;
1422 }
1423
1424 if (check)
1425 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001426 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001427
Simon Kelley7622fc02009-06-04 20:32:05 +01001428#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001429 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001430#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001431 break;
1432
1433 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001434 if (daemon->port != 0)
1435 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001436 break;
1437
1438 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001439#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001440 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001441 {
1442 lease_prune(NULL, now);
1443 lease_update_file(now);
1444 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001445#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001446 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001447 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1448 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001449#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001450#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001451 break;
1452
1453 case EVENT_CHILD:
1454 /* See Stevens 5.10 */
1455 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1456 if (p == -1)
1457 {
1458 if (errno != EINTR)
1459 break;
1460 }
1461 else
1462 for (i = 0 ; i < MAX_PROCS; i++)
1463 if (daemon->tcp_pids[i] == p)
1464 daemon->tcp_pids[i] = 0;
1465 break;
1466
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001467#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001468 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001469 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001470 break;
1471
1472 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001473 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001474 break;
1475
1476 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001477 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1478 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001479 break;
1480
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001481 case EVENT_SCRIPT_LOG:
1482 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1483 free(msg);
1484 msg = NULL;
1485 break;
1486
Simon Kelley1a6bca82008-07-11 11:11:42 +01001487 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001488 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001489 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001490 case EVENT_LUA_ERR:
1491 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001492 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001493#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001494
Simon Kelley5aabfc72007-08-29 11:24:47 +01001495 case EVENT_REOPEN:
1496 /* Note: this may leave TCP-handling processes with the old file still open.
1497 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1498 we leave them logging to the old file. */
1499 if (daemon->log_file != NULL)
1500 log_reopen(daemon->log_file);
1501 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001502
1503 case EVENT_NEWADDR:
1504 newaddress(now);
1505 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001506
1507 case EVENT_NEWROUTE:
1508 resend_query();
1509 /* Force re-reading resolv file right now, for luck. */
1510 poll_resolv(0, 1, now);
1511 break;
1512
Simon Kelley3c973ad2018-01-14 21:05:37 +00001513 case EVENT_TIME:
1514#ifdef HAVE_DNSSEC
1515 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1516 {
1517 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1518 daemon->dnssec_no_time_check = 0;
1519 clear_cache_and_reload(now);
1520 }
1521#endif
1522 break;
1523
Simon Kelley5aabfc72007-08-29 11:24:47 +01001524 case EVENT_TERM:
1525 /* Knock all our children on the head. */
1526 for (i = 0; i < MAX_PROCS; i++)
1527 if (daemon->tcp_pids[i] != 0)
1528 kill(daemon->tcp_pids[i], SIGALRM);
1529
Simon Kelley53a91732016-01-06 17:59:13 +00001530#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001531 /* handle pending lease transitions */
1532 if (daemon->helperfd != -1)
1533 {
1534 /* block in writes until all done */
1535 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1536 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1537 do {
1538 helper_write();
1539 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelley5fc639c2019-03-29 21:29:43 +00001540 close(daemon->helperfd);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001541 }
1542#endif
1543
1544 if (daemon->lease_stream)
1545 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001546
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001547#ifdef HAVE_DNSSEC
1548 /* update timestamp file on TERM if time is considered valid */
1549 if (daemon->back_to_the_future)
1550 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001551 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001552 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1553 }
1554#endif
1555
Simon Kelley73a08a22009-02-05 20:28:08 +00001556 if (daemon->runfile)
1557 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001558
1559#ifdef HAVE_DUMPFILE
1560 if (daemon->dumpfd != -1)
1561 close(daemon->dumpfd);
1562#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001563
1564 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1565 flush_log();
1566 exit(EC_GOOD);
1567 }
1568}
1569
Simon Kelley47a95162014-07-08 22:22:02 +01001570static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001571{
1572 struct resolvc *res, *latest;
1573 struct stat statbuf;
1574 time_t last_change = 0;
1575 /* There may be more than one possible file.
1576 Go through and find the one which changed _last_.
1577 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001578
Simon Kelley28866e92011-02-14 20:19:14 +00001579 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001580 return;
1581
Simon Kelley5aabfc72007-08-29 11:24:47 +01001582 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1583 if (stat(res->name, &statbuf) == -1)
1584 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001585 if (force)
1586 {
1587 res->mtime = 0;
1588 continue;
1589 }
1590
Simon Kelley5aabfc72007-08-29 11:24:47 +01001591 if (!res->logged)
1592 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1593 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001594
1595 if (res->mtime != 0)
1596 {
1597 /* existing file evaporated, force selection of the latest
1598 file even if its mtime hasn't changed since we last looked */
1599 poll_resolv(1, do_reload, now);
1600 return;
1601 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001602 }
1603 else
1604 {
1605 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001606 if (force || (statbuf.st_mtime != res->mtime))
1607 {
1608 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001609 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1610 {
1611 last_change = statbuf.st_mtime;
1612 latest = res;
1613 }
1614 }
1615 }
1616
1617 if (latest)
1618 {
1619 static int warned = 0;
1620 if (reload_servers(latest->name))
1621 {
1622 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1623 warned = 0;
1624 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001625 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001626 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001627 }
1628 else
1629 {
1630 latest->mtime = 0;
1631 if (!warned)
1632 {
1633 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1634 warned = 1;
1635 }
1636 }
1637 }
1638}
1639
1640void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001641{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001642 (void)now;
1643
Simon Kelley824af852008-02-12 20:43:05 +00001644 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001645 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001646
Simon Kelley7622fc02009-06-04 20:32:05 +01001647#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001648 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001649 {
Simon Kelley28866e92011-02-14 20:19:14 +00001650 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001651 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001652 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001653 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001654 lease_update_from_configs();
1655 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001656 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001657 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001658#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001659 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001660 /* Not doing DHCP, so no lease system, manage
1661 alarms for ra only */
1662 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001663#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001664#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001665}
1666
Simon Kelleyb842bc92015-07-12 21:09:11 +01001667static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001668{
1669 struct serverfd *serverfdp;
1670 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001671 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001672
1673#ifdef HAVE_TFTP
1674 int tftp = 0;
1675 struct tftp_transfer *transfer;
Simon Kelley66f62652020-01-05 16:21:24 +00001676 if (!option_bool(OPT_SINGLE_PORT))
1677 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1678 {
1679 tftp++;
1680 poll_listen(transfer->sockfd, POLLIN);
1681 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001682#endif
1683
Simon Kelley16972692006-10-16 20:04:18 +01001684 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001685 if (daemon->port != 0)
Simon Kelley8caf3d72020-04-04 17:00:32 +01001686 get_new_frec(now, &wait, NULL);
Simon Kelley16972692006-10-16 20:04:18 +01001687
Simon Kelley3be34542004-09-11 19:12:13 +01001688 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001689 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001690
Simon Kelley1a6bca82008-07-11 11:11:42 +01001691 if (daemon->port != 0 && !daemon->osport)
1692 for (i = 0; i < RANDOM_SOCKS; i++)
1693 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001694 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001695
Simon Kelley3be34542004-09-11 19:12:13 +01001696 for (listener = daemon->listeners; listener; listener = listener->next)
1697 {
Simon Kelley16972692006-10-16 20:04:18 +01001698 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001699 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001700 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001701
Simon Kelley16972692006-10-16 20:04:18 +01001702 /* death of a child goes through the select loop, so
1703 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001704 if (listener->tcpfd != -1)
1705 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001706 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001707 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001708 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001709 break;
1710 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001711
Simon Kelley832af0b2007-01-21 20:01:28 +00001712#ifdef HAVE_TFTP
Simon Kelley2ac4cf02020-01-06 23:39:33 +00001713 /* tftp == 0 in single-port mode. */
Simon Kelley832af0b2007-01-21 20:01:28 +00001714 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001715 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001716#endif
1717
1718 }
1719
Simon Kelleya799ca02018-10-18 19:35:29 +01001720 if (!option_bool(OPT_DEBUG))
1721 for (i = 0; i < MAX_PROCS; i++)
1722 if (daemon->tcp_pipes[i] != -1)
1723 poll_listen(daemon->tcp_pipes[i], POLLIN);
Simon Kelleya799ca02018-10-18 19:35:29 +01001724
Simon Kelley16972692006-10-16 20:04:18 +01001725 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001726}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001727
Simon Kelleyb842bc92015-07-12 21:09:11 +01001728static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001729{
1730 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001731 struct listener *listener;
1732 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001733 int pipefd[2];
Simon Kelleya799ca02018-10-18 19:35:29 +01001734
Simon Kelley832af0b2007-01-21 20:01:28 +00001735 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001736 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001737 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1738
1739 if (daemon->port != 0 && !daemon->osport)
1740 for (i = 0; i < RANDOM_SOCKS; i++)
1741 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001742 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001743 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001744
Simon Kelleya799ca02018-10-18 19:35:29 +01001745 /* Races. The child process can die before we read all of the data from the
1746 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1747 process, and tcp_pipes to -1 and close the FD when we read the last
1748 of the data - indicated by cache_recv_insert returning zero.
1749 The order of these events is indeterminate, and both are needed
1750 to free the process slot. Once the child process has gone, poll()
1751 returns POLLHUP, not POLLIN, so have to check for both here. */
1752 if (!option_bool(OPT_DEBUG))
1753 for (i = 0; i < MAX_PROCS; i++)
1754 if (daemon->tcp_pipes[i] != -1 &&
1755 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1756 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1757 {
1758 close(daemon->tcp_pipes[i]);
1759 daemon->tcp_pipes[i] = -1;
1760 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001761
Simon Kelley832af0b2007-01-21 20:01:28 +00001762 for (listener = daemon->listeners; listener; listener = listener->next)
1763 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001764 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001765 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001766
Simon Kelley832af0b2007-01-21 20:01:28 +00001767#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001768 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001769 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001770#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001771
Simon Kelleyb842bc92015-07-12 21:09:11 +01001772 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001773 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001774 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001775 struct irec *iface = NULL;
1776 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001777 union mysockaddr tcp_addr;
1778 socklen_t tcp_len = sizeof(union mysockaddr);
1779
1780 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001781
Simon Kelley46b06652013-02-04 21:47:59 +00001782 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001783 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001784
Simon Kelley46b06652013-02-04 21:47:59 +00001785 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1786 {
Simon Kelley5fc639c2019-03-29 21:29:43 +00001787 close(confd);
Simon Kelley46b06652013-02-04 21:47:59 +00001788 continue;
1789 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001790
1791 /* Make sure that the interface list is up-to-date.
1792
1793 We do this here as we may need the results below, and
1794 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001795
Simon Kelley76dd75d2013-05-23 10:04:25 +01001796 Multiple calls to enumerate_interfaces() per select loop are
1797 inhibited, so calls to it in the child process (which doesn't select())
1798 have no effect. This avoids two processes reading from the same
1799 netlink fd and screwing the pooch entirely.
1800 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001801
Simon Kelley76dd75d2013-05-23 10:04:25 +01001802 enumerate_interfaces(0);
1803
1804 if (option_bool(OPT_NOWILD))
1805 iface = listener->iface; /* May be NULL */
1806 else
1807 {
1808 int if_index;
1809 char intr_name[IF_NAMESIZE];
1810
1811 /* if we can find the arrival interface, check it's one that's allowed */
1812 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1813 indextoname(listener->tcpfd, if_index, intr_name))
1814 {
Simon Kelleycc921df2019-01-02 22:48:59 +00001815 union all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001816
Simon Kelley76dd75d2013-05-23 10:04:25 +01001817 if (tcp_addr.sa.sa_family == AF_INET6)
Simon Kelleycc921df2019-01-02 22:48:59 +00001818 addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001819 else
Simon Kelleycc921df2019-01-02 22:48:59 +00001820 addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001821
1822 for (iface = daemon->interfaces; iface; iface = iface->next)
1823 if (iface->index == if_index)
1824 break;
1825
1826 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1827 client_ok = 0;
1828 }
1829
1830 if (option_bool(OPT_CLEVERBIND))
1831 iface = listener->iface; /* May be NULL */
1832 else
1833 {
1834 /* Check for allowed interfaces when binding the wildcard address:
1835 we do this by looking for an interface with the same address as
1836 the local address of the TCP connection, then looking to see if that's
1837 an allowed interface. As a side effect, we get the netmask of the
1838 interface too, for localisation. */
1839
1840 for (iface = daemon->interfaces; iface; iface = iface->next)
1841 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1842 break;
1843
1844 if (!iface)
1845 client_ok = 0;
1846 }
1847 }
1848
Simon Kelley22ce5502013-01-22 13:53:04 +00001849 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001850 {
1851 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001852 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001853 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001854 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001855 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001856 close(pipefd[1]); /* parent needs read pipe end. */
1857 if (p == -1)
1858 close(pipefd[0]);
1859 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001860 {
1861 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001862
Simon Kelley832af0b2007-01-21 20:01:28 +00001863 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001864 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001865 {
Simon Kelley77476582020-02-09 23:19:41 +00001866 char a;
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +00001867 (void)a; /* suppress potential unused warning */
1868
Simon Kelley832af0b2007-01-21 20:01:28 +00001869 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001870 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley77476582020-02-09 23:19:41 +00001871#ifdef HAVE_LINUX_NETWORK
1872 /* The child process inherits the netlink socket,
1873 which it never uses, but when the parent (us)
1874 uses it in the future, the answer may go to the
1875 child, resulting in the parent blocking
1876 forever awaiting the result. To avoid this
1877 the child closes the netlink socket, but there's
1878 a nasty race, since the parent may use netlink
1879 before the child has done the close.
1880
1881 To avoid this, the parent blocks here until a
1882 single byte comes back up the pipe, which
1883 is sent by the child after it has closed the
1884 netlink socket. */
1885 retry_send(read(pipefd[0], &a, 1));
1886#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001887 break;
1888 }
1889 }
Simon Kelley5fc639c2019-03-29 21:29:43 +00001890 close(confd);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001891
1892 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1893 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001894 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001895 else
1896 {
1897 unsigned char *buff;
1898 struct server *s;
1899 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001900 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001901 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001902
Simon Kelley52d4abf2012-03-21 21:39:48 +00001903 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001904 {
1905 netmask = iface->netmask;
1906 auth_dns = iface->dns_auth;
1907 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001908 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001909 {
1910 netmask.s_addr = 0;
1911 auth_dns = 0;
1912 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001913
Josh Soref730c6742017-02-06 16:14:04 +00001914 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001915 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001916 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001917 {
Simon Kelley77476582020-02-09 23:19:41 +00001918 char a = 0;
Kevin Darbyshire-Bryant70c50ef2020-03-06 10:31:15 +00001919 (void)a; /* suppress potential unused warning */
Simon Kelleya799ca02018-10-18 19:35:29 +01001920 alarm(CHILD_LIFETIME);
1921 close(pipefd[0]); /* close read end in child. */
1922 daemon->pipe_to_parent = pipefd[1];
Simon Kelley77476582020-02-09 23:19:41 +00001923#ifdef HAVE_LINUX_NETWORK
1924 /* See comment above re netlink socket. */
1925 close(daemon->netlinkfd);
1926 retry_send(write(pipefd[1], &a, 1));
1927#endif
Simon Kelleya799ca02018-10-18 19:35:29 +01001928 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001929
Simon Kelley832af0b2007-01-21 20:01:28 +00001930 /* start with no upstream connections. */
1931 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001932 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001933
1934 /* The connected socket inherits non-blocking
1935 attribute from the listening socket.
1936 Reset that here. */
1937 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1938 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1939
Simon Kelley4f7b3042012-11-28 21:27:02 +00001940 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001941
Simon Kelley832af0b2007-01-21 20:01:28 +00001942 shutdown(confd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001943 close(confd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001944
1945 if (buff)
1946 free(buff);
1947
1948 for (s = daemon->servers; s; s = s->next)
1949 if (s->tcpfd != -1)
1950 {
1951 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelley5fc639c2019-03-29 21:29:43 +00001952 close(s->tcpfd);
Simon Kelley832af0b2007-01-21 20:01:28 +00001953 }
Simon Kelley28866e92011-02-14 20:19:14 +00001954 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001955 {
1956 flush_log();
1957 _exit(0);
1958 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001959 }
1960 }
1961 }
Simon Kelley3be34542004-09-11 19:12:13 +01001962}
1963
Simon Kelley7622fc02009-06-04 20:32:05 +01001964#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001965int make_icmp_sock(void)
1966{
Simon Kelley7cebd202006-05-06 14:13:33 +01001967 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001968 int zeroopt = 0;
1969
1970 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1971 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001972 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001973 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1974 {
1975 close(fd);
1976 fd = -1;
1977 }
1978 }
1979
1980 return fd;
1981}
1982
Simon Kelley5aabfc72007-08-29 11:24:47 +01001983int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001984{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001985 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001986
Floris Bos503c6092017-04-09 23:07:13 +01001987 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001988 struct sockaddr_in saddr;
1989 struct {
1990 struct ip ip;
1991 struct icmp icmp;
1992 } packet;
1993 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001994 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001995 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001996
Simon Kelley824af852008-02-12 20:43:05 +00001997#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001998 if ((fd = make_icmp_sock()) == -1)
1999 return 0;
2000#else
2001 int opt = 2000;
2002 fd = daemon->dhcp_icmp_fd;
2003 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2004#endif
2005
Simon Kelley3be34542004-09-11 19:12:13 +01002006 saddr.sin_family = AF_INET;
2007 saddr.sin_port = 0;
2008 saddr.sin_addr = addr;
2009#ifdef HAVE_SOCKADDR_SA_LEN
2010 saddr.sin_len = sizeof(struct sockaddr_in);
2011#endif
2012
2013 memset(&packet.icmp, 0, sizeof(packet.icmp));
2014 packet.icmp.icmp_type = ICMP_ECHO;
2015 packet.icmp.icmp_id = id;
2016 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
2017 j += ((u16 *)&packet.icmp)[i];
2018 while (j>>16)
2019 j = (j & 0xffff) + (j >> 16);
2020 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
2021
Simon Kelleyff841eb2015-03-11 21:36:30 +00002022 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
2023 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002024
Floris Bos503c6092017-04-09 23:07:13 +01002025 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
2026
2027#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelley5fc639c2019-03-29 21:29:43 +00002028 close(fd);
Floris Bos503c6092017-04-09 23:07:13 +01002029#else
2030 opt = 1;
2031 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
2032#endif
2033
2034 return gotreply;
2035}
2036
2037int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
2038{
2039 /* Delay processing DHCP packets for "sec" seconds counting from "start".
2040 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
2041 from "addr" with ICMP ID "id" and return 1 */
2042
2043 /* Note that whilst waiting, we check for
2044 (and service) events on the DNS and TFTP sockets, (so doing that
2045 better not use any resources our caller has in use...)
2046 but we remain deaf to signals or further DHCP packets. */
2047
2048 /* There can be a problem using dnsmasq_time() to end the loop, since
2049 it's not monotonic, and can go backwards if the system clock is
2050 tweaked, leading to the code getting stuck in this loop and
2051 ignoring DHCP requests. To fix this, we check to see if select returned
2052 as a result of a timeout rather than a socket becoming available. We
2053 only allow this to happen as many times as it takes to get to the wait time
2054 in quarter-second chunks. This provides a fallback way to end loop. */
2055
2056 int rc, timeout_count;
2057 time_t now;
2058
2059 for (now = dnsmasq_time(), timeout_count = 0;
2060 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002061 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01002062 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01002063 if (fd != -1)
2064 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01002065 set_dns_listeners(now);
2066 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002067
2068#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00002069 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002070 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002071#endif
2072
Simon Kelleyb842bc92015-07-12 21:09:11 +01002073 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01002074
2075 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01002076 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01002077 else if (rc == 0)
2078 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01002079
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002080 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01002081
Simon Kelleyb842bc92015-07-12 21:09:11 +01002082 check_log_writer(0);
2083 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01002084
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002085#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01002086 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00002087 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00002088#endif
2089
Simon Kelley832af0b2007-01-21 20:01:28 +00002090#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01002091 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00002092#endif
2093
Floris Bos503c6092017-04-09 23:07:13 +01002094 if (fd != -1)
2095 {
2096 struct {
2097 struct ip ip;
2098 struct icmp icmp;
2099 } packet;
2100 struct sockaddr_in faddr;
2101 socklen_t len = sizeof(faddr);
2102
2103 if (poll_check(fd, POLLIN) &&
2104 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
2105 addr == faddr.sin_addr.s_addr &&
2106 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
2107 packet.icmp.icmp_seq == 0 &&
2108 packet.icmp.icmp_id == id)
2109 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002110 }
2111 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002112
Floris Bos503c6092017-04-09 23:07:13 +01002113 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01002114}
Simon Kelley7622fc02009-06-04 20:32:05 +01002115#endif
Simon Kelley0a852542005-03-23 20:28:59 +00002116
2117