blob: 5a52ea71382d4834d76d06e7418940e885a2188e [file] [log] [blame]
Simon Kelleyd1ced3a2018-01-01 22:18:03 +00001/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley
Simon Kelley9e4abcb2004-01-22 19:47:41 +00002
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
Simon Kelley824af852008-02-12 20:43:05 +00005 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
Simon Kelley9e4abcb2004-01-22 19:47:41 +00008 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
Simon Kelley824af852008-02-12 20:43:05 +000012
Simon Kelley73a08a22009-02-05 20:28:08 +000013 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
Simon Kelley9e4abcb2004-01-22 19:47:41 +000015*/
16
Simon Kelleyc72daea2012-01-05 21:33:27 +000017/* Declare static char *compiler_opts in config.h */
18#define DNSMASQ_COMPILE_OPTS
19
Simon Kelley9e4abcb2004-01-22 19:47:41 +000020#include "dnsmasq.h"
21
Simon Kelley5aabfc72007-08-29 11:24:47 +010022struct daemon *daemon;
23
Simon Kelley5aabfc72007-08-29 11:24:47 +010024static volatile pid_t pid = 0;
25static volatile int pipewrite;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000026
Simon Kelleyb842bc92015-07-12 21:09:11 +010027static int set_dns_listeners(time_t now);
28static void check_dns_listeners(time_t now);
Simon Kelley3be34542004-09-11 19:12:13 +010029static void sig_handler(int sig);
Simon Kelley5aabfc72007-08-29 11:24:47 +010030static void async_event(int pipe, time_t now);
Simon Kelleyc72daea2012-01-05 21:33:27 +000031static void fatal_event(struct event_desc *ev, char *msg);
32static int read_event(int fd, struct event_desc *evp, char **msg);
Simon Kelley47a95162014-07-08 22:22:02 +010033static void poll_resolv(int force, int do_reload, time_t now);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000034
35int main (int argc, char **argv)
36{
Simon Kelleyde379512004-06-22 20:23:33 +010037 int bind_fallback = 0;
Simon Kelley9009d742008-11-14 20:04:27 +000038 time_t now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +000039 struct sigaction sigact;
Simon Kelley26128d22004-11-14 16:43:54 +000040 struct iname *if_tmp;
Simon Kelley1a6bca82008-07-11 11:11:42 +010041 int piperead, pipefd[2], err_pipe[2];
42 struct passwd *ent_pw = NULL;
Simon Kelleyc72daea2012-01-05 21:33:27 +000043#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +010044 uid_t script_uid = 0;
45 gid_t script_gid = 0;
Simon Kelley7622fc02009-06-04 20:32:05 +010046#endif
47 struct group *gp = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +010048 long i, max_fd = sysconf(_SC_OPEN_MAX);
Simon Kelley1a6bca82008-07-11 11:11:42 +010049 char *baduser = NULL;
50 int log_err;
Simon Kelley6b54d692018-02-08 21:23:05 +000051 int chown_warn = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010052#if defined(HAVE_LINUX_NETWORK)
53 cap_user_header_t hdr = NULL;
54 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010055 char *bound_device = NULL;
56 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010057#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010058#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000059 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010060 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010061#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010062#ifdef HAVE_TFTP
63 int tftp_prefix_missing = 0;
64#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010065
Simon Kelley824af852008-02-12 20:43:05 +000066#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000067 setlocale(LC_ALL, "");
68 bindtextdomain("dnsmasq", LOCALEDIR);
69 textdomain("dnsmasq");
70#endif
71
Simon Kelley9e4abcb2004-01-22 19:47:41 +000072 sigact.sa_handler = sig_handler;
73 sigact.sa_flags = 0;
74 sigemptyset(&sigact.sa_mask);
75 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010076 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000077 sigaction(SIGHUP, &sigact, NULL);
78 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000079 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010080 sigaction(SIGCHLD, &sigact, NULL);
Simon Kelley3c973ad2018-01-14 21:05:37 +000081 sigaction(SIGINT, &sigact, NULL);
82
Simon Kelleyfeba5c12004-07-27 20:28:58 +010083 /* ignore SIGPIPE */
84 sigact.sa_handler = SIG_IGN;
85 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000086
Simon Kelley5aabfc72007-08-29 11:24:47 +010087 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010088
89 rand_init(); /* Must precede read_opts() */
90
Simon Kelley5aabfc72007-08-29 11:24:47 +010091 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000092
Simon Kelley3be34542004-09-11 19:12:13 +010093 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000094 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000095
Simon Kelleyd3a8b392015-12-23 12:27:37 +000096 /* Min buffer size: we check after adding each record, so there must be
97 memory for the largest packet, and the largest record so the
98 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
99 This might be increased is EDNS packet size if greater than the minimum. */
100 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +0000101 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000102
Simon Kelleyc72daea2012-01-05 21:33:27 +0000103 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000104 if (option_bool(OPT_EXTRALOG))
105 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000106
107#ifdef HAVE_DNSSEC
108 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000109 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100110 /* Note that both /000 and '.' are allowed within labels. These get
111 represented in presentation format using NAME_ESCAPE as an escape
112 character when in DNSSEC mode.
113 In theory, if all the characters in a name were /000 or
114 '.' or NAME_ESCAPE then all would have to be escaped, so the
115 presentation format would be twice as long as the spec.
116
117 daemon->namebuff was previously allocated by the option-reading
118 code before we knew if we're in DNSSEC mode, so reallocate here. */
119 free(daemon->namebuff);
120 daemon->namebuff = safe_malloc(MAXDNAME * 2);
121 daemon->keyname = safe_malloc(MAXDNAME * 2);
122 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley373e9172017-12-01 22:40:56 +0000123 /* one char flag per possible RR in answer section (may get extended). */
124 daemon->rr_status_sz = 64;
125 daemon->rr_status = safe_malloc(daemon->rr_status_sz);
Simon Kelley5107ace2014-02-23 10:48:32 +0000126 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000127#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000128
Simon Kelley7622fc02009-06-04 20:32:05 +0100129#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100130 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000131 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000132 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100133 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000134 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100135#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000136
Simon Kelleya2761752012-01-18 16:07:21 +0000137 /* Close any file descriptors we inherited apart from std{in|out|err}
138
139 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
140 otherwise file descriptors we create can end up being 0, 1, or 2
141 and then get accidentally closed later when we make 0, 1, and 2
142 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
143 but it's not guaranteed. By opening /dev/null three times, we
144 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100145 for (i = 0; i < max_fd; i++)
146 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
147 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000148 else
149 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100150
Simon Kelley801ca9a2012-03-06 19:30:17 +0000151#ifndef HAVE_LINUX_NETWORK
152# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000153 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100154 {
155 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000156 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100157 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000158# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100159
160 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100161 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100162 {
163 bind_fallback = 1;
164 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100165 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100166 }
Simon Kelley04918052015-01-26 11:23:43 +0000167#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000168
Simon Kelley04918052015-01-26 11:23:43 +0000169#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000170 if (daemon->dynamic_dirs)
171 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100172#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100173
Simon Kelley0744ca62014-01-25 16:40:15 +0000174 if (option_bool(OPT_DNSSEC_VALID))
175 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000176#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000177 struct ds_config *ds;
178
179 /* Must have at least a root trust anchor, or the DNSSEC code
180 can loop forever. */
181 for (ds = daemon->ds; ds; ds = ds->next)
182 if (ds->name[0] == 0)
183 break;
184
185 if (!ds)
186 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000187
188 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000189 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000190#else
191 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000192#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000193 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000194
Simon Kelley832af0b2007-01-21 20:01:28 +0000195#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100196 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100197 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000198#endif
199
Simon Kelley7de060b2011-08-26 17:24:52 +0100200#ifdef HAVE_CONNTRACK
201 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000202 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100203#else
204 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000205 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100206#endif
207
Simon Kelley824af852008-02-12 20:43:05 +0000208#ifdef HAVE_SOLARIS_NETWORK
209 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000210 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000211#endif
212
Simon Kelley572b41e2011-02-18 18:11:18 +0000213#ifdef __ANDROID__
214 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000215 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000216#endif
217
Simon Kelley4820dce2012-12-18 18:30:30 +0000218#ifndef HAVE_AUTH
Simon Kelley08933472018-10-05 16:34:35 +0100219 if (daemon->auth_zones)
Simon Kelley4820dce2012-12-18 18:30:30 +0000220 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
221#endif
222
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100223#ifndef HAVE_LOOP
224 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000225 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100226#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000227
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100228#ifndef HAVE_UBUS
229 if (option_bool(OPT_UBUS))
230 die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
231#endif
232
Hans Dedecker926332a2016-01-23 10:48:12 +0000233 if (daemon->max_port < daemon->min_port)
234 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
235
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100236 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000237
Simon Kelley08933472018-10-05 16:34:35 +0100238 if (daemon->auth_zones)
239 {
240 if (!daemon->authserver)
241 die(_("--auth-server required when an auth zone is defined."), NULL, EC_BADCONF);
242
243 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000244#ifdef HAVE_BROKEN_RTC
Martin Schiller53792c92018-10-08 14:55:19 +0200245 if (daemon->soa_sn == 0)
Simon Kelley08933472018-10-05 16:34:35 +0100246 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000247#else
Simon Kelley08933472018-10-05 16:34:35 +0100248 if (daemon->soa_sn == 0)
249 daemon->soa_sn = now;
Simon Kelley4f7b3042012-11-28 21:27:02 +0000250#endif
Simon Kelley08933472018-10-05 16:34:35 +0100251 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000252
Simon Kelleyff7eea22013-09-04 18:01:38 +0100253#ifdef HAVE_DHCP6
254 if (daemon->dhcp6)
255 {
256 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000257
Simon Kelleyff7eea22013-09-04 18:01:38 +0100258 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000259 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100260 if (context->flags & CONTEXT_DHCP)
261 daemon->doing_dhcp6 = 1;
262 if (context->flags & CONTEXT_RA)
263 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000264#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100265 if (context->flags & CONTEXT_TEMPLATE)
266 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000267#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000268 }
Simon Kelley1f776932012-12-16 19:46:08 +0000269 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100270#endif
271
272#ifdef HAVE_DHCP
273 /* Note that order matters here, we must call lease_init before
274 creating any file descriptors which shouldn't be leaked
275 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000276 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000277 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000278 conditions below. */
279 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000280 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100281 {
282 dhcp_common_init();
283 if (daemon->dhcp || daemon->doing_dhcp6)
284 lease_init(now);
285 }
286
287 if (daemon->dhcp || daemon->relay4)
288 dhcp_init();
289
290# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100291 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100292 ra_init(now);
293
294 if (daemon->doing_dhcp6 || daemon->relay6)
295 dhcp6_init();
296# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000297
Simon Kelley7622fc02009-06-04 20:32:05 +0100298#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100299
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000300#ifdef HAVE_IPSET
301 if (daemon->ipsets)
302 ipset_init();
303#endif
304
Simon Kelley1ee9be42013-12-09 16:50:19 +0000305#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000306 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000307#elif defined(HAVE_BSD_NETWORK)
308 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000309#endif
310
Simon Kelley1ee9be42013-12-09 16:50:19 +0000311 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
312 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
313
Simon Kelley115ac3e2013-05-20 11:28:32 +0100314 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100315 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000316
Simon Kelley54dd3932012-06-20 11:23:38 +0100317 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100318 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100319 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100320
321 if (!option_bool(OPT_CLEVERBIND))
322 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
323 if (if_tmp->name && !if_tmp->used)
324 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100325
326#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
327 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100328 bound_device = whichdevice();
329
Simon Kelley9380ba72012-04-16 14:41:56 +0100330 if (daemon->dhcp)
331 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100332 if (!daemon->relay4 && bound_device)
333 {
334 bindtodevice(bound_device, daemon->dhcpfd);
335 did_bind = 1;
336 }
337 if (daemon->enable_pxe && bound_device)
338 {
339 bindtodevice(bound_device, daemon->pxefd);
340 did_bind = 1;
341 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100342 }
343#endif
344
345#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100346 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
347 {
348 bindtodevice(bound_device, daemon->dhcp6fd);
349 did_bind = 1;
350 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100351#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100352 }
Simon Kelley28866e92011-02-14 20:19:14 +0000353 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100354 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000355
356#ifdef HAVE_DHCP6
357 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100358 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000359 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000360
361 /* After netlink_init() and before create_helper() */
362 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000363#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100364
Simon Kelley824af852008-02-12 20:43:05 +0000365 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000366 {
367 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000368
Simon Kelley82e3f452014-01-31 21:05:48 +0000369#ifdef HAVE_DNSSEC
370 blockdata_init();
371#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000372 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000373
Simon Kelley04918052015-01-26 11:23:43 +0000374#ifdef HAVE_INOTIFY
Petr Menšík075366a2017-11-05 16:05:39 +0000375 if ((daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
376 && (!option_bool(OPT_NO_RESOLV) || daemon->dynamic_dirs))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000377 inotify_dnsmasq_init();
378 else
379 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000380#endif
Simon Kelley6b173352018-05-08 18:32:14 +0100381
382 if (daemon->dump_file)
383#ifdef HAVE_DUMPFILE
384 dump_init();
385 else
386 daemon->dumpfd = -1;
387#else
388 die(_("Packet dumps not available: set HAVE_DUMP in src/config.h"), NULL, EC_BADCONF);
389#endif
390
Simon Kelley28866e92011-02-14 20:19:14 +0000391 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100392#ifdef HAVE_DBUS
393 {
394 char *err;
395 daemon->dbus = NULL;
396 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100397 if ((err = dbus_init()))
398 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100399 }
400#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100401 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100402#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100403
Simon Kelley824af852008-02-12 20:43:05 +0000404 if (daemon->port != 0)
405 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100406
Simon Kelleyc72daea2012-01-05 21:33:27 +0000407#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100408 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000409 if ((daemon->dhcp || daemon->dhcp6) &&
410 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000411 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100412 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000413 struct passwd *scr_pw;
414
415 if ((scr_pw = getpwnam(daemon->scriptuser)))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100416 {
Simon Kelley83e4b732018-02-06 16:57:15 +0000417 script_uid = scr_pw->pw_uid;
418 script_gid = scr_pw->pw_gid;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100419 }
420 else
421 baduser = daemon->scriptuser;
422 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100423#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000424
Simon Kelley1a6bca82008-07-11 11:11:42 +0100425 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
426 baduser = daemon->username;
427 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
428 baduser = daemon->groupname;
429
430 if (baduser)
431 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000432
Simon Kelley1a6bca82008-07-11 11:11:42 +0100433 /* implement group defaults, "dip" if available, or group associated with uid */
434 if (!daemon->group_set && !gp)
435 {
436 if (!(gp = getgrnam(CHGRP)) && ent_pw)
437 gp = getgrgid(ent_pw->pw_gid);
438
439 /* for error message */
440 if (gp)
441 daemon->groupname = gp->gr_name;
442 }
443
444#if defined(HAVE_LINUX_NETWORK)
445 /* determine capability API version here, while we can still
446 call safe_malloc */
447 if (ent_pw && ent_pw->pw_uid != 0)
448 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100449 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100450 hdr = safe_malloc(sizeof(*hdr));
451
Simon Kelley1a6bca82008-07-11 11:11:42 +0100452 /* find version supported by kernel */
453 memset(hdr, 0, sizeof(*hdr));
454 capget(hdr, NULL);
455
456 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
457 {
458 /* if unknown version, use largest supported version (3) */
459 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
460 hdr->version = LINUX_CAPABILITY_VERSION_3;
461 capsize = 2;
462 }
463
464 data = safe_malloc(sizeof(*data) * capsize);
465 memset(data, 0, sizeof(*data) * capsize);
466 }
467#endif
468
Simon Kelley5aabfc72007-08-29 11:24:47 +0100469 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100470 in a race-free manner and another to carry errors to daemon-invoking process */
471 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100472
473 piperead = pipefd[0];
474 pipewrite = pipefd[1];
475 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000476 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100477
478 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100479
Simon Kelley28866e92011-02-14 20:19:14 +0000480 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000481 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000482 /* The following code "daemonizes" the process.
483 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100484
Simon Kelley9e038942008-05-30 20:06:34 +0100485 if (chdir("/") != 0)
486 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
487
Simon Kelley28866e92011-02-14 20:19:14 +0000488 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100489 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100490 pid_t pid;
491
Simon Kelley1a6bca82008-07-11 11:11:42 +0100492 /* pipe to carry errors back to original process.
493 When startup is complete we close this and the process terminates. */
494 safe_pipe(err_pipe, 0);
495
Simon Kelley7622fc02009-06-04 20:32:05 +0100496 if ((pid = fork()) == -1)
497 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000498 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100499
Simon Kelley5aabfc72007-08-29 11:24:47 +0100500 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100501 {
502 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000503 char *msg;
504
Simon Kelley1a6bca82008-07-11 11:11:42 +0100505 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000506 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100507
508 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000509 if (read_event(err_pipe[0], &ev, &msg))
510 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100511
512 _exit(EC_GOOD);
513 }
514
Simon Kelleyff841eb2015-03-11 21:36:30 +0000515 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100516
517 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100518
519 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100520
521 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000522 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100523
524 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100525 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100526 }
Simon Kelley9e038942008-05-30 20:06:34 +0100527
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000528 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100529 if (daemon->runfile)
530 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100531 int fd, err = 0;
532
533 sprintf(daemon->namebuff, "%d\n", (int) getpid());
534
535 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
536 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
537 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
538 extent that an attacker running as the unprivileged user could replace the pidfile with a
539 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
540
Josh Soref730c6742017-02-06 16:14:04 +0000541 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100542 ensuring that the open() fails should there be any existing file (because the unlink() failed,
543 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
544 attack can succeed.
545
546 Any compromise of the non-privileged user still theoretically allows the pid-file to be
547 replaced whilst dnsmasq is running. The worst that could allow is that the usual
548 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
549
550 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
551 failure to write the pid-file.
552 */
553
554 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100555
Simon Kelley79cfefd2012-09-02 13:29:51 +0100556 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 +0100557 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100558 /* only complain if started as root */
559 if (getuid() == 0)
560 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100561 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100562 else
563 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000564 /* We're still running as root here. Change the ownership of the PID file
565 to the user we will be running as. Note that this is not to allow
566 us to delete the file, since that depends on the permissions
567 of the directory containing the file. That directory will
568 need to by owned by the dnsmasq user, and the ownership of the
569 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000570 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
571 chown_warn = errno;
572
573 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100574 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000575 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000576 {
577 while (retry_send(close(fd)));
578 if (errno != 0)
579 err = 1;
580 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100581 }
582
583 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100584 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000585 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100586 _exit(0);
587 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000588 }
Simon Kelley16972692006-10-16 20:04:18 +0100589 }
590
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100591 log_err = log_start(ent_pw, err_pipe[1]);
592
Simon Kelley28866e92011-02-14 20:19:14 +0000593 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100594 {
595 /* open stdout etc to /dev/null */
596 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000597 if (nullfd != -1)
598 {
599 dup2(nullfd, STDOUT_FILENO);
600 dup2(nullfd, STDERR_FILENO);
601 dup2(nullfd, STDIN_FILENO);
602 close(nullfd);
603 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100604 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100605
Simon Kelley1a6bca82008-07-11 11:11:42 +0100606 /* if we are to run scripts, we need to fork a helper before dropping root. */
607 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000608#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000609 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000610 (daemon->lease_change_command || daemon->luascript))
611 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100612#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100613
Simon Kelley28866e92011-02-14 20:19:14 +0000614 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100615 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100616 int bad_capabilities = 0;
617 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100618
Josh Soref730c6742017-02-06 16:14:04 +0000619 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100620 if (gp &&
621 (setgroups(0, &dummy) == -1 ||
622 setgid(gp->gr_gid) == -1))
623 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000624 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100625 _exit(0);
626 }
627
Simon Kelley7cebd202006-05-06 14:13:33 +0100628 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100629 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100630#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100631 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100632 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100633 ports because of DAD, or we're doing it dynamically,
634 we need CAP_NET_BIND_SERVICE too. */
635 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100636 data->effective = data->permitted = data->inheritable =
637 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
638 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
639 else
640 data->effective = data->permitted = data->inheritable =
641 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100642
Simon Kelley16972692006-10-16 20:04:18 +0100643 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000644 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100645 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100646
Simon Kelley7622fc02009-06-04 20:32:05 +0100647#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000648 /* http://developers.sun.com/solaris/articles/program_privileges.html */
649 priv_set_t *priv_set;
650
651 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
652 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
653 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
654 bad_capabilities = errno;
655
656 if (priv_set && bad_capabilities == 0)
657 {
658 priv_inverse(priv_set);
659
660 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
661 bad_capabilities = errno;
662 }
663
664 if (priv_set)
665 priv_freeset(priv_set);
666
Simon Kelley824af852008-02-12 20:43:05 +0000667#endif
668
Simon Kelley1a6bca82008-07-11 11:11:42 +0100669 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100670 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000671 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100672 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100673 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100674
675 /* finally drop root */
676 if (setuid(ent_pw->pw_uid) == -1)
677 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000678 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100679 _exit(0);
680 }
681
682#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100683 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100684 data->effective = data->permitted =
685 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
686 else
687 data->effective = data->permitted =
688 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100689 data->inheritable = 0;
690
Josh Soref730c6742017-02-06 16:14:04 +0000691 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100692 if (capset(hdr, data) == -1)
693 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000694 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100695 _exit(0);
696 }
697#endif
698
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000699 }
Simon Kelley849a8352006-06-09 21:02:31 +0100700 }
Simon Kelley16972692006-10-16 20:04:18 +0100701
Simon Kelley16972692006-10-16 20:04:18 +0100702#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000703 free(hdr);
704 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000705 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000706 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100707#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100708
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100709#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100710 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100711 {
712 DIR *dir;
713 struct tftp_prefix *p;
714
715 if (daemon->tftp_prefix)
716 {
717 if (!((dir = opendir(daemon->tftp_prefix))))
718 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100719 tftp_prefix_missing = 1;
720 if (!option_bool(OPT_TFTP_NO_FAIL))
721 {
722 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
723 _exit(0);
724 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100725 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100726 else
727 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100728 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100729
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100730 for (p = daemon->if_prefix; p; p = p->next)
731 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100732 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100733 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100734 {
735 p->missing = 1;
736 if (!option_bool(OPT_TFTP_NO_FAIL))
737 {
738 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
739 _exit(0);
740 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100741 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100742 else
743 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100744 }
745 }
746#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100747
Simon Kelley824af852008-02-12 20:43:05 +0000748 if (daemon->port == 0)
749 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000750 else
751 {
752 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100753 {
754 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
755 if (daemon->cachesize > 10000)
756 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
757 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000758 else
759 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
760
761 if (option_bool(OPT_LOCAL_SERVICE))
762 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
763 }
Simon Kelley16972692006-10-16 20:04:18 +0100764
Simon Kelleyf2621c72007-04-29 19:47:21 +0100765 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000766
767 if (chown_warn != 0)
768 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100769
Simon Kelley3d8df262005-08-29 12:19:27 +0100770#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000771 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100772 {
773 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100774 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100775 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100776 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100777 }
778#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000779
Simon Kelley1d97ac42014-01-31 11:12:27 +0000780#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000781 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000782 {
Simon Kelley360f2512015-03-07 18:28:06 +0000783 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100784 struct ds_config *ds;
785
Simon Kelley360f2512015-03-07 18:28:06 +0000786 /* Delay creating the timestamp file until here, after we've changed user, so that
787 it has the correct owner to allow updating the mtime later.
788 This means we have to report fatal errors via the pipe. */
789 if ((rc = setup_timestamp()) == -1)
790 {
791 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
792 _exit(0);
793 }
794
Simon Kelleya6918532018-04-15 16:20:52 +0100795 if (option_bool(OPT_DNSSEC_IGN_NS))
796 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
797 else
798 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000799
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100800 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
801 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000802 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000803
804 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000805 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100806
807 for (ds = daemon->ds; ds; ds = ds->next)
808 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
809 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000810 }
Simon Kelleydb737462014-01-31 10:32:45 +0000811#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100812
Simon Kelley1a6bca82008-07-11 11:11:42 +0100813 if (log_err != 0)
814 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
815 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000816
Simon Kelleyde379512004-06-22 20:23:33 +0100817 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100818 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100819
Simon Kelleyf7029f52013-11-21 15:09:09 +0000820 if (option_bool(OPT_NOWILD))
821 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000822 else if (!option_bool(OPT_CLEVERBIND))
823 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000824
825 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100826
Simon Kelley28866e92011-02-14 20:19:14 +0000827 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000828 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
829 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100830 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100831
Simon Kelley28866e92011-02-14 20:19:14 +0000832 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100833 {
834 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100835 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100836 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000837 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100838 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100839 }
840
Simon Kelleyf2621c72007-04-29 19:47:21 +0100841 if (daemon->max_logs != 0)
842 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000843
Simon Kelleyf2621c72007-04-29 19:47:21 +0100844
Simon Kelley7622fc02009-06-04 20:32:05 +0100845#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000846 for (context = daemon->dhcp; context; context = context->next)
847 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100848
Simon Kelleyff7eea22013-09-04 18:01:38 +0100849 for (relay = daemon->relay4; relay; relay = relay->next)
850 log_relay(AF_INET, relay);
851
Simon Kelley1f776932012-12-16 19:46:08 +0000852# ifdef HAVE_DHCP6
853 for (context = daemon->dhcp6; context; context = context->next)
854 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000855
Simon Kelleyff7eea22013-09-04 18:01:38 +0100856 for (relay = daemon->relay6; relay; relay = relay->next)
857 log_relay(AF_INET6, relay);
858
Simon Kelley1f776932012-12-16 19:46:08 +0000859 if (daemon->doing_dhcp6 || daemon->doing_ra)
860 dhcp_construct_contexts(now);
861
862 if (option_bool(OPT_RA))
863 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
864# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000865
Simon Kelley3b3f4412013-10-11 16:33:28 +0100866# ifdef HAVE_LINUX_NETWORK
867 if (did_bind)
868 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
869# endif
870
Josh Soref730c6742017-02-06 16:14:04 +0000871 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000872 if (daemon->dhcp || daemon->doing_dhcp6)
873 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000874#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000875
Simon Kelley832af0b2007-01-21 20:01:28 +0000876#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000877 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100878 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100879 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000880
Simon Kelley7622fc02009-06-04 20:32:05 +0100881 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100882 daemon->tftp_prefix ? _("root is ") : _("enabled"),
883 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000884 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100885
Stefan Tomanek30d08792015-03-31 22:32:11 +0100886 if (tftp_prefix_missing)
887 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100888
Stefan Tomanek30d08792015-03-31 22:32:11 +0100889 for (p = daemon->if_prefix; p; p = p->next)
890 if (p->missing)
891 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
892
Simon Kelley832af0b2007-01-21 20:01:28 +0000893 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100894 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000895 a single file will be sent to may clients (the file only needs
896 one fd). */
897
898 max_fd -= 30; /* use other than TFTP */
899
900 if (max_fd < 0)
901 max_fd = 5;
902 else if (max_fd < 100)
903 max_fd = max_fd/2;
904 else
905 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000906
907 /* if we have to use a limited range of ports,
908 that will limit the number of transfers */
909 if (daemon->start_tftp_port != 0 &&
910 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
911 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000912
913 if (daemon->tftp_max > max_fd)
914 {
915 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100916 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100917 _("restricting maximum simultaneous TFTP transfers to %d"),
918 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000919 }
920 }
921#endif
922
Simon Kelley1a6bca82008-07-11 11:11:42 +0100923 /* finished start-up - release original process */
924 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000925 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000926
Simon Kelley824af852008-02-12 20:43:05 +0000927 if (daemon->port != 0)
928 check_servers();
929
Simon Kelley7cebd202006-05-06 14:13:33 +0100930 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +0100931
932 daemon->pipe_to_parent = -1;
933 for (i = 0; i < MAX_PROCS; i++)
934 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +0100935
Simon Kelley04918052015-01-26 11:23:43 +0000936#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000937 /* Using inotify, have to select a resolv file at startup */
938 poll_resolv(1, 0, now);
939#endif
940
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100941 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000942 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100943 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000944
Simon Kelleyb842bc92015-07-12 21:09:11 +0100945 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000946
Simon Kelley16972692006-10-16 20:04:18 +0100947 /* if we are out of resources, find how long we have to wait
948 for some to come free, we'll loop around then and restart
949 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100950 if ((t = set_dns_listeners(now)) != 0)
951 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100952
Simon Kelley832af0b2007-01-21 20:01:28 +0000953 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
954 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000955 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100956 timeout = 250;
957
Simon Kelley74c95c22011-10-19 09:33:39 +0100958 /* Wake every second whilst waiting for DAD to complete */
959 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100960 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100961
Simon Kelley832af0b2007-01-21 20:01:28 +0000962#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100963 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100964#endif
965
966#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +0100967 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100968 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100969#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100970
Simon Kelley7622fc02009-06-04 20:32:05 +0100971#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100972 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100973 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100974 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000975 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100976 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100977 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100978#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100979
Simon Kelley52b92f42012-01-22 16:05:15 +0000980#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100981 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100982 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100983
Simon Kelley1f776932012-12-16 19:46:08 +0000984 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100985 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000986#endif
Simon Kelley04918052015-01-26 11:23:43 +0000987
988#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000989 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100990 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000991#endif
992
993#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100994 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000995#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100996 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100997#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000998
Simon Kelleyb842bc92015-07-12 21:09:11 +0100999 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001000
Simon Kelley33702ab2015-12-28 23:17:15 +00001001#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001002# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001003 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001004# endif
1005
Simon Kelley1e505122016-01-25 21:29:23 +00001006 /* Refresh cache */
1007 if (option_bool(OPT_SCRIPT_ARP))
1008 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001009 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001010
Simon Kelleya9530962012-03-20 22:07:35 +00001011# ifdef HAVE_TFTP
1012 while (helper_buf_empty() && do_tftp_script_run());
1013# endif
1014
Simon Kelley16972692006-10-16 20:04:18 +01001015 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001016 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001017#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001018 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001019# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001020 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001021# endif
1022
Simon Kelleyb633de92016-01-06 22:51:17 +00001023 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001024
1025# ifdef HAVE_TFTP
1026 while (do_tftp_script_run());
1027# endif
1028
Simon Kelley5aabfc72007-08-29 11:24:47 +01001029#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001030
Simon Kelley7622fc02009-06-04 20:32:05 +01001031
Simon Kelleyf2621c72007-04-29 19:47:21 +01001032 /* must do this just before select(), when we know no
1033 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001034 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001035
Simon Kelleyb842bc92015-07-12 21:09:11 +01001036 if (do_poll(timeout) < 0)
1037 continue;
1038
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001039 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001040
Simon Kelleyb842bc92015-07-12 21:09:11 +01001041 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001042
1043 /* prime. */
1044 enumerate_interfaces(1);
1045
Simon Kelley74c95c22011-10-19 09:33:39 +01001046 /* Check the interfaces to see if any have exited DAD state
1047 and if so, bind the address. */
1048 if (is_dad_listeners())
1049 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001050 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001051 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1052 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001053 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001054 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001055
Simon Kelley1ee9be42013-12-09 16:50:19 +00001056#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001057 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001058 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001059#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001060 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001061 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001062#endif
1063
Simon Kelley04918052015-01-26 11:23:43 +00001064#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001065 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001066 {
1067 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1068 poll_resolv(1, 1, now);
1069 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001070#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001071 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001072 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001073 if (daemon->last_resolv == 0 ||
1074 difftime(now, daemon->last_resolv) > 1.0 ||
1075 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001076 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001077 /* poll_resolv doesn't need to reload first time through, since
1078 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001079
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001080 poll_resolv(0, daemon->last_resolv != 0, now);
1081 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001082 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001083#endif
1084
Simon Kelleyb842bc92015-07-12 21:09:11 +01001085 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001086 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001087
Simon Kelley3d8df262005-08-29 12:19:27 +01001088#ifdef HAVE_DBUS
1089 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001090 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001091 {
1092 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001093 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001094 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001095 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001096 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001097 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001098 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001099#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001100
1101#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001102 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001103 check_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001104#endif
1105
Simon Kelleyb842bc92015-07-12 21:09:11 +01001106 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001107
1108#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001109 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001110#endif
1111
Simon Kelley7622fc02009-06-04 20:32:05 +01001112#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001113 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001114 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001115 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001116 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001117 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001118 dhcp_packet(now, 1);
1119 }
Simon Kelley16972692006-10-16 20:04:18 +01001120
Simon Kelley52b92f42012-01-22 16:05:15 +00001121#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001122 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001123 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001124
Simon Kelleyb842bc92015-07-12 21:09:11 +01001125 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001126 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001127#endif
1128
Simon Kelley1f15b812009-10-13 17:49:32 +01001129# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001130 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001131 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001132# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001133#endif
1134
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001135 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001136}
1137
Simon Kelley3be34542004-09-11 19:12:13 +01001138static void sig_handler(int sig)
1139{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001140 if (pid == 0)
1141 {
Simon Kelley16972692006-10-16 20:04:18 +01001142 /* ignore anything other than TERM during startup
1143 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001144 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001145 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001146 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001147 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001148 {
Simon Kelley16972692006-10-16 20:04:18 +01001149 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001150 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001151 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001152 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001153 else
1154 {
1155 /* master process */
1156 int event, errsave = errno;
1157
1158 if (sig == SIGHUP)
1159 event = EVENT_RELOAD;
1160 else if (sig == SIGCHLD)
1161 event = EVENT_CHILD;
1162 else if (sig == SIGALRM)
1163 event = EVENT_ALARM;
1164 else if (sig == SIGTERM)
1165 event = EVENT_TERM;
1166 else if (sig == SIGUSR1)
1167 event = EVENT_DUMP;
1168 else if (sig == SIGUSR2)
1169 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001170 else if (sig == SIGINT)
1171 {
1172 /* Handle SIGINT normally in debug mode, so
1173 ctrl-c continues to operate. */
1174 if (option_bool(OPT_DEBUG))
1175 exit(EC_MISC);
1176 else
1177 event = EVENT_TIME;
1178 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001179 else
1180 return;
1181
Simon Kelleyc72daea2012-01-05 21:33:27 +00001182 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001183 errno = errsave;
1184 }
Simon Kelley3be34542004-09-11 19:12:13 +01001185}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001186
Simon Kelley353ae4d2012-03-19 20:07:51 +00001187/* now == 0 -> queue immediate callback */
1188void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001189{
Simon Kelley884a6df2012-03-20 16:20:22 +00001190 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001191 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001192 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1193 if ((now == 0 || difftime(event, now) <= 0.0))
1194 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1195 else
1196 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001197 }
Simon Kelley741c2952012-02-25 13:09:18 +00001198}
1199
Simon Kelley47a95162014-07-08 22:22:02 +01001200void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001201{
Simon Kelley47a95162014-07-08 22:22:02 +01001202 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001203}
1204
Simon Kelleyc72daea2012-01-05 21:33:27 +00001205void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001206{
1207 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001208 struct iovec iov[2];
1209
Simon Kelley5aabfc72007-08-29 11:24:47 +01001210 ev.event = event;
1211 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001212 ev.msg_sz = msg ? strlen(msg) : 0;
1213
1214 iov[0].iov_base = &ev;
1215 iov[0].iov_len = sizeof(ev);
1216 iov[1].iov_base = msg;
1217 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001218
1219 /* error pipe, debug mode. */
1220 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001221 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001222 else
1223 /* pipe is non-blocking and struct event_desc is smaller than
1224 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001225 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001226}
Simon Kelley3d8df262005-08-29 12:19:27 +01001227
Simon Kelleyc72daea2012-01-05 21:33:27 +00001228/* NOTE: the memory used to return msg is leaked: use msgs in events only
1229 to describe fatal errors. */
1230static int read_event(int fd, struct event_desc *evp, char **msg)
1231{
1232 char *buf;
1233
1234 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1235 return 0;
1236
1237 *msg = NULL;
1238
1239 if (evp->msg_sz != 0 &&
1240 (buf = malloc(evp->msg_sz + 1)) &&
1241 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1242 {
1243 buf[evp->msg_sz] = 0;
1244 *msg = buf;
1245 }
1246
1247 return 1;
1248}
1249
1250static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001251{
1252 errno = ev->data;
1253
1254 switch (ev->event)
1255 {
1256 case EVENT_DIE:
1257 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001258
1259 case EVENT_FORK_ERR:
1260 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001261
1262 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001263 case EVENT_PIPE_ERR:
1264 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001265
1266 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001267 case EVENT_CAP_ERR:
1268 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1269
Simon Kelleye7a4af82018-02-16 21:27:35 +00001270 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001271 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001272 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001273
Simon Kelleye7a4af82018-02-16 21:27:35 +00001274 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001275 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001276 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001277
1278 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001279 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001280 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001281
Simon Kelleye7a4af82018-02-16 21:27:35 +00001282 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001283 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001284 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001285
1286 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001287 case EVENT_LUA_ERR:
1288 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001289
Simon Kelleye7a4af82018-02-16 21:27:35 +00001290 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001291 case EVENT_TFTP_ERR:
1292 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001293
1294 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001295 case EVENT_TIME_ERR:
1296 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001297 }
1298}
1299
Simon Kelley5aabfc72007-08-29 11:24:47 +01001300static void async_event(int pipe, time_t now)
1301{
1302 pid_t p;
1303 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001304 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001305 char *msg;
1306
1307 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1308 to describe fatal errors. */
1309
1310 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001311 switch (ev.event)
1312 {
1313 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001314 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001315
Simon Kelleye98bd522014-03-28 20:41:23 +00001316 /* fall through */
1317
1318 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001319 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001320
Simon Kelley7b1eae42014-02-20 13:43:28 +00001321 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001322 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001323 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1324 {
1325 reload_servers(daemon->resolv_files->name);
1326 check = 1;
1327 }
1328
1329 if (daemon->servers_file)
1330 {
1331 read_servers_file();
1332 check = 1;
1333 }
1334
1335 if (check)
1336 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001337 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001338
Simon Kelley7622fc02009-06-04 20:32:05 +01001339#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001340 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001341#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001342 break;
1343
1344 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001345 if (daemon->port != 0)
1346 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001347 break;
1348
1349 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001350#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001351 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001352 {
1353 lease_prune(NULL, now);
1354 lease_update_file(now);
1355 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001356#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001357 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001358 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1359 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001360#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001361#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001362 break;
1363
1364 case EVENT_CHILD:
1365 /* See Stevens 5.10 */
1366 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1367 if (p == -1)
1368 {
1369 if (errno != EINTR)
1370 break;
1371 }
1372 else
1373 for (i = 0 ; i < MAX_PROCS; i++)
1374 if (daemon->tcp_pids[i] == p)
1375 daemon->tcp_pids[i] = 0;
1376 break;
1377
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001378#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001379 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001380 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001381 break;
1382
1383 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001384 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001385 break;
1386
1387 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001388 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1389 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001390 break;
1391
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001392 case EVENT_SCRIPT_LOG:
1393 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1394 free(msg);
1395 msg = NULL;
1396 break;
1397
Simon Kelley1a6bca82008-07-11 11:11:42 +01001398 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001399 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001400 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001401 case EVENT_LUA_ERR:
1402 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001403 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001404#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001405
Simon Kelley5aabfc72007-08-29 11:24:47 +01001406 case EVENT_REOPEN:
1407 /* Note: this may leave TCP-handling processes with the old file still open.
1408 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1409 we leave them logging to the old file. */
1410 if (daemon->log_file != NULL)
1411 log_reopen(daemon->log_file);
1412 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001413
1414 case EVENT_NEWADDR:
1415 newaddress(now);
1416 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001417
1418 case EVENT_NEWROUTE:
1419 resend_query();
1420 /* Force re-reading resolv file right now, for luck. */
1421 poll_resolv(0, 1, now);
1422 break;
1423
Simon Kelley3c973ad2018-01-14 21:05:37 +00001424 case EVENT_TIME:
1425#ifdef HAVE_DNSSEC
1426 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1427 {
1428 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1429 daemon->dnssec_no_time_check = 0;
1430 clear_cache_and_reload(now);
1431 }
1432#endif
1433 break;
1434
Simon Kelley5aabfc72007-08-29 11:24:47 +01001435 case EVENT_TERM:
1436 /* Knock all our children on the head. */
1437 for (i = 0; i < MAX_PROCS; i++)
1438 if (daemon->tcp_pids[i] != 0)
1439 kill(daemon->tcp_pids[i], SIGALRM);
1440
Simon Kelley53a91732016-01-06 17:59:13 +00001441#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001442 /* handle pending lease transitions */
1443 if (daemon->helperfd != -1)
1444 {
1445 /* block in writes until all done */
1446 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1447 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1448 do {
1449 helper_write();
1450 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001451 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001452 }
1453#endif
1454
1455 if (daemon->lease_stream)
1456 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001457
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001458#ifdef HAVE_DNSSEC
1459 /* update timestamp file on TERM if time is considered valid */
1460 if (daemon->back_to_the_future)
1461 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001462 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001463 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1464 }
1465#endif
1466
Simon Kelley73a08a22009-02-05 20:28:08 +00001467 if (daemon->runfile)
1468 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001469
1470#ifdef HAVE_DUMPFILE
1471 if (daemon->dumpfd != -1)
1472 close(daemon->dumpfd);
1473#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001474
1475 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1476 flush_log();
1477 exit(EC_GOOD);
1478 }
1479}
1480
Simon Kelley47a95162014-07-08 22:22:02 +01001481static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001482{
1483 struct resolvc *res, *latest;
1484 struct stat statbuf;
1485 time_t last_change = 0;
1486 /* There may be more than one possible file.
1487 Go through and find the one which changed _last_.
1488 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001489
Simon Kelley28866e92011-02-14 20:19:14 +00001490 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001491 return;
1492
Simon Kelley5aabfc72007-08-29 11:24:47 +01001493 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1494 if (stat(res->name, &statbuf) == -1)
1495 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001496 if (force)
1497 {
1498 res->mtime = 0;
1499 continue;
1500 }
1501
Simon Kelley5aabfc72007-08-29 11:24:47 +01001502 if (!res->logged)
1503 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1504 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001505
1506 if (res->mtime != 0)
1507 {
1508 /* existing file evaporated, force selection of the latest
1509 file even if its mtime hasn't changed since we last looked */
1510 poll_resolv(1, do_reload, now);
1511 return;
1512 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001513 }
1514 else
1515 {
1516 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001517 if (force || (statbuf.st_mtime != res->mtime))
1518 {
1519 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001520 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1521 {
1522 last_change = statbuf.st_mtime;
1523 latest = res;
1524 }
1525 }
1526 }
1527
1528 if (latest)
1529 {
1530 static int warned = 0;
1531 if (reload_servers(latest->name))
1532 {
1533 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1534 warned = 0;
1535 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001536 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001537 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001538 }
1539 else
1540 {
1541 latest->mtime = 0;
1542 if (!warned)
1543 {
1544 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1545 warned = 1;
1546 }
1547 }
1548 }
1549}
1550
1551void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001552{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001553 (void)now;
1554
Simon Kelley824af852008-02-12 20:43:05 +00001555 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001556 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001557
Simon Kelley7622fc02009-06-04 20:32:05 +01001558#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001559 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001560 {
Simon Kelley28866e92011-02-14 20:19:14 +00001561 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001562 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001563 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001564 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001565 lease_update_from_configs();
1566 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001567 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001568 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001569#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001570 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001571 /* Not doing DHCP, so no lease system, manage
1572 alarms for ra only */
1573 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001574#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001575#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001576}
1577
Simon Kelleyb842bc92015-07-12 21:09:11 +01001578static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001579{
1580 struct serverfd *serverfdp;
1581 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001582 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001583
1584#ifdef HAVE_TFTP
1585 int tftp = 0;
1586 struct tftp_transfer *transfer;
1587 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1588 {
1589 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001590 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001591 }
1592#endif
1593
Simon Kelley16972692006-10-16 20:04:18 +01001594 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001595 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001596 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001597
Simon Kelley3be34542004-09-11 19:12:13 +01001598 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001599 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001600
Simon Kelley1a6bca82008-07-11 11:11:42 +01001601 if (daemon->port != 0 && !daemon->osport)
1602 for (i = 0; i < RANDOM_SOCKS; i++)
1603 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001604 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001605
Simon Kelley3be34542004-09-11 19:12:13 +01001606 for (listener = daemon->listeners; listener; listener = listener->next)
1607 {
Simon Kelley16972692006-10-16 20:04:18 +01001608 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001609 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001610 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001611
Simon Kelley16972692006-10-16 20:04:18 +01001612 /* death of a child goes through the select loop, so
1613 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001614 if (listener->tcpfd != -1)
1615 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001616 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001617 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001618 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001619 break;
1620 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001621
Simon Kelley832af0b2007-01-21 20:01:28 +00001622#ifdef HAVE_TFTP
1623 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001624 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001625#endif
1626
1627 }
1628
Simon Kelleya799ca02018-10-18 19:35:29 +01001629 if (!option_bool(OPT_DEBUG))
1630 for (i = 0; i < MAX_PROCS; i++)
1631 if (daemon->tcp_pipes[i] != -1)
1632 poll_listen(daemon->tcp_pipes[i], POLLIN);
Simon Kelleya799ca02018-10-18 19:35:29 +01001633
Simon Kelley16972692006-10-16 20:04:18 +01001634 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001635}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001636
Simon Kelleyb842bc92015-07-12 21:09:11 +01001637static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001638{
1639 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001640 struct listener *listener;
1641 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001642 int pipefd[2];
Simon Kelleya799ca02018-10-18 19:35:29 +01001643
Simon Kelley832af0b2007-01-21 20:01:28 +00001644 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001645 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001646 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1647
1648 if (daemon->port != 0 && !daemon->osport)
1649 for (i = 0; i < RANDOM_SOCKS; i++)
1650 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001651 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001652 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001653
Simon Kelleya799ca02018-10-18 19:35:29 +01001654 /* Races. The child process can die before we read all of the data from the
1655 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1656 process, and tcp_pipes to -1 and close the FD when we read the last
1657 of the data - indicated by cache_recv_insert returning zero.
1658 The order of these events is indeterminate, and both are needed
1659 to free the process slot. Once the child process has gone, poll()
1660 returns POLLHUP, not POLLIN, so have to check for both here. */
1661 if (!option_bool(OPT_DEBUG))
1662 for (i = 0; i < MAX_PROCS; i++)
1663 if (daemon->tcp_pipes[i] != -1 &&
1664 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1665 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1666 {
1667 close(daemon->tcp_pipes[i]);
1668 daemon->tcp_pipes[i] = -1;
1669 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001670
Simon Kelley832af0b2007-01-21 20:01:28 +00001671 for (listener = daemon->listeners; listener; listener = listener->next)
1672 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001673 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001674 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001675
Simon Kelley832af0b2007-01-21 20:01:28 +00001676#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001677 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001678 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001679#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001680
Simon Kelleyb842bc92015-07-12 21:09:11 +01001681 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001682 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001683 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001684 struct irec *iface = NULL;
1685 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001686 union mysockaddr tcp_addr;
1687 socklen_t tcp_len = sizeof(union mysockaddr);
1688
1689 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001690
Simon Kelley46b06652013-02-04 21:47:59 +00001691 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001692 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001693
Simon Kelley46b06652013-02-04 21:47:59 +00001694 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1695 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001696 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001697 continue;
1698 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001699
1700 /* Make sure that the interface list is up-to-date.
1701
1702 We do this here as we may need the results below, and
1703 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001704
Simon Kelley76dd75d2013-05-23 10:04:25 +01001705 Multiple calls to enumerate_interfaces() per select loop are
1706 inhibited, so calls to it in the child process (which doesn't select())
1707 have no effect. This avoids two processes reading from the same
1708 netlink fd and screwing the pooch entirely.
1709 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001710
Simon Kelley76dd75d2013-05-23 10:04:25 +01001711 enumerate_interfaces(0);
1712
1713 if (option_bool(OPT_NOWILD))
1714 iface = listener->iface; /* May be NULL */
1715 else
1716 {
1717 int if_index;
1718 char intr_name[IF_NAMESIZE];
1719
1720 /* if we can find the arrival interface, check it's one that's allowed */
1721 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1722 indextoname(listener->tcpfd, if_index, intr_name))
1723 {
1724 struct all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001725
Simon Kelley76dd75d2013-05-23 10:04:25 +01001726 if (tcp_addr.sa.sa_family == AF_INET6)
1727 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001728 else
1729 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001730
1731 for (iface = daemon->interfaces; iface; iface = iface->next)
1732 if (iface->index == if_index)
1733 break;
1734
1735 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1736 client_ok = 0;
1737 }
1738
1739 if (option_bool(OPT_CLEVERBIND))
1740 iface = listener->iface; /* May be NULL */
1741 else
1742 {
1743 /* Check for allowed interfaces when binding the wildcard address:
1744 we do this by looking for an interface with the same address as
1745 the local address of the TCP connection, then looking to see if that's
1746 an allowed interface. As a side effect, we get the netmask of the
1747 interface too, for localisation. */
1748
1749 for (iface = daemon->interfaces; iface; iface = iface->next)
1750 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1751 break;
1752
1753 if (!iface)
1754 client_ok = 0;
1755 }
1756 }
1757
Simon Kelley22ce5502013-01-22 13:53:04 +00001758 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001759 {
1760 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001761 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001762 }
Simon Kelleya799ca02018-10-18 19:35:29 +01001763 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001764 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001765 close(pipefd[1]); /* parent needs read pipe end. */
1766 if (p == -1)
1767 close(pipefd[0]);
1768 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001769 {
1770 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001771
Simon Kelley832af0b2007-01-21 20:01:28 +00001772 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001773 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001774 {
1775 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001776 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley832af0b2007-01-21 20:01:28 +00001777 break;
1778 }
1779 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001780 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001781
1782 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1783 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001784 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001785 else
1786 {
1787 unsigned char *buff;
1788 struct server *s;
1789 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001790 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001791 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001792
Simon Kelley52d4abf2012-03-21 21:39:48 +00001793 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001794 {
1795 netmask = iface->netmask;
1796 auth_dns = iface->dns_auth;
1797 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001798 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001799 {
1800 netmask.s_addr = 0;
1801 auth_dns = 0;
1802 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001803
Josh Soref730c6742017-02-06 16:14:04 +00001804 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001805 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001806 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001807 {
1808 alarm(CHILD_LIFETIME);
1809 close(pipefd[0]); /* close read end in child. */
1810 daemon->pipe_to_parent = pipefd[1];
1811 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001812
Simon Kelley832af0b2007-01-21 20:01:28 +00001813 /* start with no upstream connections. */
1814 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001815 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001816
1817 /* The connected socket inherits non-blocking
1818 attribute from the listening socket.
1819 Reset that here. */
1820 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1821 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1822
Simon Kelley4f7b3042012-11-28 21:27:02 +00001823 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001824
Simon Kelley832af0b2007-01-21 20:01:28 +00001825 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001826 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001827
1828 if (buff)
1829 free(buff);
1830
1831 for (s = daemon->servers; s; s = s->next)
1832 if (s->tcpfd != -1)
1833 {
1834 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001835 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001836 }
Simon Kelley28866e92011-02-14 20:19:14 +00001837 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001838 {
1839 flush_log();
1840 _exit(0);
1841 }
Simon Kelley832af0b2007-01-21 20:01:28 +00001842 }
1843 }
1844 }
Simon Kelley3be34542004-09-11 19:12:13 +01001845}
1846
Simon Kelley7622fc02009-06-04 20:32:05 +01001847#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001848int make_icmp_sock(void)
1849{
Simon Kelley7cebd202006-05-06 14:13:33 +01001850 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001851 int zeroopt = 0;
1852
1853 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1854 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001855 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001856 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1857 {
1858 close(fd);
1859 fd = -1;
1860 }
1861 }
1862
1863 return fd;
1864}
1865
Simon Kelley5aabfc72007-08-29 11:24:47 +01001866int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001867{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001868 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001869
Floris Bos503c6092017-04-09 23:07:13 +01001870 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001871 struct sockaddr_in saddr;
1872 struct {
1873 struct ip ip;
1874 struct icmp icmp;
1875 } packet;
1876 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001877 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001878 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001879
Simon Kelley824af852008-02-12 20:43:05 +00001880#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001881 if ((fd = make_icmp_sock()) == -1)
1882 return 0;
1883#else
1884 int opt = 2000;
1885 fd = daemon->dhcp_icmp_fd;
1886 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1887#endif
1888
Simon Kelley3be34542004-09-11 19:12:13 +01001889 saddr.sin_family = AF_INET;
1890 saddr.sin_port = 0;
1891 saddr.sin_addr = addr;
1892#ifdef HAVE_SOCKADDR_SA_LEN
1893 saddr.sin_len = sizeof(struct sockaddr_in);
1894#endif
1895
1896 memset(&packet.icmp, 0, sizeof(packet.icmp));
1897 packet.icmp.icmp_type = ICMP_ECHO;
1898 packet.icmp.icmp_id = id;
1899 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1900 j += ((u16 *)&packet.icmp)[i];
1901 while (j>>16)
1902 j = (j & 0xffff) + (j >> 16);
1903 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1904
Simon Kelleyff841eb2015-03-11 21:36:30 +00001905 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1906 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001907
Floris Bos503c6092017-04-09 23:07:13 +01001908 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1909
1910#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1911 while (retry_send(close(fd)));
1912#else
1913 opt = 1;
1914 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1915#endif
1916
1917 return gotreply;
1918}
1919
1920int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1921{
1922 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1923 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1924 from "addr" with ICMP ID "id" and return 1 */
1925
1926 /* Note that whilst waiting, we check for
1927 (and service) events on the DNS and TFTP sockets, (so doing that
1928 better not use any resources our caller has in use...)
1929 but we remain deaf to signals or further DHCP packets. */
1930
1931 /* There can be a problem using dnsmasq_time() to end the loop, since
1932 it's not monotonic, and can go backwards if the system clock is
1933 tweaked, leading to the code getting stuck in this loop and
1934 ignoring DHCP requests. To fix this, we check to see if select returned
1935 as a result of a timeout rather than a socket becoming available. We
1936 only allow this to happen as many times as it takes to get to the wait time
1937 in quarter-second chunks. This provides a fallback way to end loop. */
1938
1939 int rc, timeout_count;
1940 time_t now;
1941
1942 for (now = dnsmasq_time(), timeout_count = 0;
1943 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001944 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001945 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001946 if (fd != -1)
1947 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001948 set_dns_listeners(now);
1949 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001950
1951#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001952 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001953 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001954#endif
1955
Simon Kelleyb842bc92015-07-12 21:09:11 +01001956 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001957
1958 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001959 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001960 else if (rc == 0)
1961 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001962
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001963 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001964
Simon Kelleyb842bc92015-07-12 21:09:11 +01001965 check_log_writer(0);
1966 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001967
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001968#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001969 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001970 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001971#endif
1972
Simon Kelley832af0b2007-01-21 20:01:28 +00001973#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001974 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001975#endif
1976
Floris Bos503c6092017-04-09 23:07:13 +01001977 if (fd != -1)
1978 {
1979 struct {
1980 struct ip ip;
1981 struct icmp icmp;
1982 } packet;
1983 struct sockaddr_in faddr;
1984 socklen_t len = sizeof(faddr);
1985
1986 if (poll_check(fd, POLLIN) &&
1987 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1988 addr == faddr.sin_addr.s_addr &&
1989 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1990 packet.icmp.icmp_seq == 0 &&
1991 packet.icmp.icmp_id == id)
1992 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001993 }
1994 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001995
Floris Bos503c6092017-04-09 23:07:13 +01001996 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001997}
Simon Kelley7622fc02009-06-04 20:32:05 +01001998#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001999
2000