blob: 97a3517e5fcf107755df4439129cac28f926fdb6 [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 Kelley16972692006-10-16 20:04:18 +0100488#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000489 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100490 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100491 pid_t pid;
492
Simon Kelley1a6bca82008-07-11 11:11:42 +0100493 /* pipe to carry errors back to original process.
494 When startup is complete we close this and the process terminates. */
495 safe_pipe(err_pipe, 0);
496
Simon Kelley7622fc02009-06-04 20:32:05 +0100497 if ((pid = fork()) == -1)
498 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000499 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100500
Simon Kelley5aabfc72007-08-29 11:24:47 +0100501 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100502 {
503 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000504 char *msg;
505
Simon Kelley1a6bca82008-07-11 11:11:42 +0100506 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000507 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100508
509 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000510 if (read_event(err_pipe[0], &ev, &msg))
511 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100512
513 _exit(EC_GOOD);
514 }
515
Simon Kelleyff841eb2015-03-11 21:36:30 +0000516 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100517
518 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100519
520 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100521
522 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000523 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100524
525 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100526 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100527 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000528#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100529
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000530 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100531 if (daemon->runfile)
532 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100533 int fd, err = 0;
534
535 sprintf(daemon->namebuff, "%d\n", (int) getpid());
536
537 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
538 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
539 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
540 extent that an attacker running as the unprivileged user could replace the pidfile with a
541 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
542
Josh Soref730c6742017-02-06 16:14:04 +0000543 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100544 ensuring that the open() fails should there be any existing file (because the unlink() failed,
545 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
546 attack can succeed.
547
548 Any compromise of the non-privileged user still theoretically allows the pid-file to be
549 replaced whilst dnsmasq is running. The worst that could allow is that the usual
550 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
551
552 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
553 failure to write the pid-file.
554 */
555
556 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100557
Simon Kelley79cfefd2012-09-02 13:29:51 +0100558 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 +0100559 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100560 /* only complain if started as root */
561 if (getuid() == 0)
562 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100563 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100564 else
565 {
Simon Kelley246a31c2018-02-06 17:27:55 +0000566 /* We're still running as root here. Change the ownership of the PID file
567 to the user we will be running as. Note that this is not to allow
568 us to delete the file, since that depends on the permissions
569 of the directory containing the file. That directory will
570 need to by owned by the dnsmasq user, and the ownership of the
571 file has to match, to keep systemd >273 happy. */
Simon Kelley6b54d692018-02-08 21:23:05 +0000572 if (getuid() == 0 && ent_pw && ent_pw->pw_uid != 0 && fchown(fd, ent_pw->pw_uid, ent_pw->pw_gid) == -1)
573 chown_warn = errno;
574
575 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
Simon Kelley79cfefd2012-09-02 13:29:51 +0100576 err = 1;
Simon Kelley83e4b732018-02-06 16:57:15 +0000577 else
Simon Kelleyff841eb2015-03-11 21:36:30 +0000578 {
579 while (retry_send(close(fd)));
580 if (errno != 0)
581 err = 1;
582 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100583 }
584
585 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100586 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000587 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100588 _exit(0);
589 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000590 }
Simon Kelley16972692006-10-16 20:04:18 +0100591 }
592
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100593 log_err = log_start(ent_pw, err_pipe[1]);
594
Simon Kelley28866e92011-02-14 20:19:14 +0000595 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100596 {
597 /* open stdout etc to /dev/null */
598 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000599 if (nullfd != -1)
600 {
601 dup2(nullfd, STDOUT_FILENO);
602 dup2(nullfd, STDERR_FILENO);
603 dup2(nullfd, STDIN_FILENO);
604 close(nullfd);
605 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100606 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100607
Simon Kelley1a6bca82008-07-11 11:11:42 +0100608 /* if we are to run scripts, we need to fork a helper before dropping root. */
609 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000610#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000611 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000612 (daemon->lease_change_command || daemon->luascript))
613 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100614#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100615
Simon Kelley28866e92011-02-14 20:19:14 +0000616 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100617 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100618 int bad_capabilities = 0;
619 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100620
Josh Soref730c6742017-02-06 16:14:04 +0000621 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100622 if (gp &&
623 (setgroups(0, &dummy) == -1 ||
624 setgid(gp->gr_gid) == -1))
625 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000626 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100627 _exit(0);
628 }
629
Simon Kelley7cebd202006-05-06 14:13:33 +0100630 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100631 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100632#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100633 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100634 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100635 ports because of DAD, or we're doing it dynamically,
636 we need CAP_NET_BIND_SERVICE too. */
637 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100638 data->effective = data->permitted = data->inheritable =
639 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
640 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
641 else
642 data->effective = data->permitted = data->inheritable =
643 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100644
Simon Kelley16972692006-10-16 20:04:18 +0100645 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000646 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100647 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100648
Simon Kelley7622fc02009-06-04 20:32:05 +0100649#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000650 /* http://developers.sun.com/solaris/articles/program_privileges.html */
651 priv_set_t *priv_set;
652
653 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
654 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
655 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
656 bad_capabilities = errno;
657
658 if (priv_set && bad_capabilities == 0)
659 {
660 priv_inverse(priv_set);
661
662 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
663 bad_capabilities = errno;
664 }
665
666 if (priv_set)
667 priv_freeset(priv_set);
668
Simon Kelley824af852008-02-12 20:43:05 +0000669#endif
670
Simon Kelley1a6bca82008-07-11 11:11:42 +0100671 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100672 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000673 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100674 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100675 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100676
677 /* finally drop root */
678 if (setuid(ent_pw->pw_uid) == -1)
679 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000680 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100681 _exit(0);
682 }
683
684#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100685 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100686 data->effective = data->permitted =
687 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
688 else
689 data->effective = data->permitted =
690 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100691 data->inheritable = 0;
692
Josh Soref730c6742017-02-06 16:14:04 +0000693 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100694 if (capset(hdr, data) == -1)
695 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000696 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100697 _exit(0);
698 }
699#endif
700
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000701 }
Simon Kelley849a8352006-06-09 21:02:31 +0100702 }
Simon Kelley16972692006-10-16 20:04:18 +0100703
Simon Kelley16972692006-10-16 20:04:18 +0100704#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000705 free(hdr);
706 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000707 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000708 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100709#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100710
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100711#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100712 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100713 {
714 DIR *dir;
715 struct tftp_prefix *p;
716
717 if (daemon->tftp_prefix)
718 {
719 if (!((dir = opendir(daemon->tftp_prefix))))
720 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100721 tftp_prefix_missing = 1;
722 if (!option_bool(OPT_TFTP_NO_FAIL))
723 {
724 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
725 _exit(0);
726 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100727 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100728 else
729 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100730 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100731
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100732 for (p = daemon->if_prefix; p; p = p->next)
733 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100734 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100735 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100736 {
737 p->missing = 1;
738 if (!option_bool(OPT_TFTP_NO_FAIL))
739 {
740 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
741 _exit(0);
742 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100743 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100744 else
745 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100746 }
747 }
748#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100749
Simon Kelley824af852008-02-12 20:43:05 +0000750 if (daemon->port == 0)
751 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000752 else
753 {
754 if (daemon->cachesize != 0)
Simon Kelley1f1873a2018-05-11 23:38:23 +0100755 {
756 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
757 if (daemon->cachesize > 10000)
758 my_syslog(LOG_WARNING, _("cache size greater than 10000 may cause performance issues, and is unlikely to be useful."));
759 }
Simon Kelley0ef13342017-01-15 16:42:39 +0000760 else
761 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
762
763 if (option_bool(OPT_LOCAL_SERVICE))
764 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
765 }
Simon Kelley16972692006-10-16 20:04:18 +0100766
Simon Kelleyf2621c72007-04-29 19:47:21 +0100767 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley6b54d692018-02-08 21:23:05 +0000768
769 if (chown_warn != 0)
770 my_syslog(LOG_WARNING, "chown of PID file %s failed: %s", daemon->runfile, strerror(chown_warn));
Simon Kelley16972692006-10-16 20:04:18 +0100771
Simon Kelley3d8df262005-08-29 12:19:27 +0100772#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000773 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100774 {
775 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100776 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100777 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100778 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100779 }
780#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000781
Simon Kelley1d97ac42014-01-31 11:12:27 +0000782#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000783 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000784 {
Simon Kelley360f2512015-03-07 18:28:06 +0000785 int rc;
Simon Kelley3b6eb192018-07-20 21:23:56 +0100786 struct ds_config *ds;
787
Simon Kelley360f2512015-03-07 18:28:06 +0000788 /* Delay creating the timestamp file until here, after we've changed user, so that
789 it has the correct owner to allow updating the mtime later.
790 This means we have to report fatal errors via the pipe. */
791 if ((rc = setup_timestamp()) == -1)
792 {
793 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
794 _exit(0);
795 }
796
Simon Kelleya6918532018-04-15 16:20:52 +0100797 if (option_bool(OPT_DNSSEC_IGN_NS))
798 my_syslog(LOG_INFO, _("DNSSEC validation enabled but all unsigned answers are trusted"));
799 else
800 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000801
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100802 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
803 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelley3c973ad2018-01-14 21:05:37 +0000804 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until receipt of SIGINT"));
Simon Kelley360f2512015-03-07 18:28:06 +0000805
806 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000807 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelley3b6eb192018-07-20 21:23:56 +0100808
809 for (ds = daemon->ds; ds; ds = ds->next)
810 my_syslog(LOG_INFO, _("configured with trust anchor for %s keytag %u"),
811 ds->name[0] == 0 ? "<root>" : ds->name, ds->keytag);
Simon Kelleye98bd522014-03-28 20:41:23 +0000812 }
Simon Kelleydb737462014-01-31 10:32:45 +0000813#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100814
Simon Kelley1a6bca82008-07-11 11:11:42 +0100815 if (log_err != 0)
816 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
817 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000818
Simon Kelleyde379512004-06-22 20:23:33 +0100819 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100820 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100821
Simon Kelleyf7029f52013-11-21 15:09:09 +0000822 if (option_bool(OPT_NOWILD))
823 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000824 else if (!option_bool(OPT_CLEVERBIND))
825 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000826
827 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100828
Simon Kelley28866e92011-02-14 20:19:14 +0000829 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000830 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
831 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100832 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100833
Simon Kelley28866e92011-02-14 20:19:14 +0000834 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100835 {
836 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100837 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100838 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000839 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100840 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100841 }
842
Simon Kelleyf2621c72007-04-29 19:47:21 +0100843 if (daemon->max_logs != 0)
844 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000845
Simon Kelleyf2621c72007-04-29 19:47:21 +0100846
Simon Kelley7622fc02009-06-04 20:32:05 +0100847#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000848 for (context = daemon->dhcp; context; context = context->next)
849 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100850
Simon Kelleyff7eea22013-09-04 18:01:38 +0100851 for (relay = daemon->relay4; relay; relay = relay->next)
852 log_relay(AF_INET, relay);
853
Simon Kelley1f776932012-12-16 19:46:08 +0000854# ifdef HAVE_DHCP6
855 for (context = daemon->dhcp6; context; context = context->next)
856 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000857
Simon Kelleyff7eea22013-09-04 18:01:38 +0100858 for (relay = daemon->relay6; relay; relay = relay->next)
859 log_relay(AF_INET6, relay);
860
Simon Kelley1f776932012-12-16 19:46:08 +0000861 if (daemon->doing_dhcp6 || daemon->doing_ra)
862 dhcp_construct_contexts(now);
863
864 if (option_bool(OPT_RA))
865 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
866# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000867
Simon Kelley3b3f4412013-10-11 16:33:28 +0100868# ifdef HAVE_LINUX_NETWORK
869 if (did_bind)
870 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
871# endif
872
Josh Soref730c6742017-02-06 16:14:04 +0000873 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000874 if (daemon->dhcp || daemon->doing_dhcp6)
875 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000876#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000877
Simon Kelley832af0b2007-01-21 20:01:28 +0000878#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000879 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100880 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100881 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000882
Simon Kelley7622fc02009-06-04 20:32:05 +0100883 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100884 daemon->tftp_prefix ? _("root is ") : _("enabled"),
885 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000886 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100887
Stefan Tomanek30d08792015-03-31 22:32:11 +0100888 if (tftp_prefix_missing)
889 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100890
Stefan Tomanek30d08792015-03-31 22:32:11 +0100891 for (p = daemon->if_prefix; p; p = p->next)
892 if (p->missing)
893 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
894
Simon Kelley832af0b2007-01-21 20:01:28 +0000895 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100896 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000897 a single file will be sent to may clients (the file only needs
898 one fd). */
899
900 max_fd -= 30; /* use other than TFTP */
901
902 if (max_fd < 0)
903 max_fd = 5;
904 else if (max_fd < 100)
905 max_fd = max_fd/2;
906 else
907 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000908
909 /* if we have to use a limited range of ports,
910 that will limit the number of transfers */
911 if (daemon->start_tftp_port != 0 &&
912 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
913 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000914
915 if (daemon->tftp_max > max_fd)
916 {
917 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100918 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100919 _("restricting maximum simultaneous TFTP transfers to %d"),
920 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000921 }
922 }
923#endif
924
Simon Kelley1a6bca82008-07-11 11:11:42 +0100925 /* finished start-up - release original process */
926 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000927 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000928
Simon Kelley824af852008-02-12 20:43:05 +0000929 if (daemon->port != 0)
930 check_servers();
931
Simon Kelley7cebd202006-05-06 14:13:33 +0100932 pid = getpid();
Simon Kelleya799ca02018-10-18 19:35:29 +0100933
934 daemon->pipe_to_parent = -1;
935 for (i = 0; i < MAX_PROCS; i++)
936 daemon->tcp_pipes[i] = -1;
Simon Kelley7cebd202006-05-06 14:13:33 +0100937
Simon Kelley04918052015-01-26 11:23:43 +0000938#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000939 /* Using inotify, have to select a resolv file at startup */
940 poll_resolv(1, 0, now);
941#endif
942
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100943 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000944 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100945 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000946
Simon Kelleyb842bc92015-07-12 21:09:11 +0100947 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000948
Simon Kelley16972692006-10-16 20:04:18 +0100949 /* if we are out of resources, find how long we have to wait
950 for some to come free, we'll loop around then and restart
951 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100952 if ((t = set_dns_listeners(now)) != 0)
953 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100954
Simon Kelley832af0b2007-01-21 20:01:28 +0000955 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
956 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000957 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100958 timeout = 250;
959
Simon Kelley74c95c22011-10-19 09:33:39 +0100960 /* Wake every second whilst waiting for DAD to complete */
961 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100962 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100963
Simon Kelley832af0b2007-01-21 20:01:28 +0000964#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100965 set_dbus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100966#endif
967
968#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +0100969 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100970 set_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +0100971#endif
Julian Kornberger8dcdb332018-07-21 22:11:08 +0100972
Simon Kelley7622fc02009-06-04 20:32:05 +0100973#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100974 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100975 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100976 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000977 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100978 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100979 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100980#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100981
Simon Kelley52b92f42012-01-22 16:05:15 +0000982#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100983 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100984 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100985
Simon Kelley1f776932012-12-16 19:46:08 +0000986 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100987 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000988#endif
Simon Kelley04918052015-01-26 11:23:43 +0000989
990#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000991 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100992 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000993#endif
994
995#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100996 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000997#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100998 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100999#endif
Simon Kelley193de4a2014-12-10 17:32:16 +00001000
Simon Kelleyb842bc92015-07-12 21:09:11 +01001001 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +01001002
Simon Kelley33702ab2015-12-28 23:17:15 +00001003#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +00001004# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +00001005 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001006# endif
1007
Simon Kelley1e505122016-01-25 21:29:23 +00001008 /* Refresh cache */
1009 if (option_bool(OPT_SCRIPT_ARP))
1010 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +00001011 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +01001012
Simon Kelleya9530962012-03-20 22:07:35 +00001013# ifdef HAVE_TFTP
1014 while (helper_buf_empty() && do_tftp_script_run());
1015# endif
1016
Simon Kelley16972692006-10-16 20:04:18 +01001017 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +01001018 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +00001019#else
Simon Kelley5aabfc72007-08-29 11:24:47 +01001020 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +00001021# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001022 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +00001023# endif
1024
Simon Kelleyb633de92016-01-06 22:51:17 +00001025 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +00001026
1027# ifdef HAVE_TFTP
1028 while (do_tftp_script_run());
1029# endif
1030
Simon Kelley5aabfc72007-08-29 11:24:47 +01001031#endif
Simon Kelley33702ab2015-12-28 23:17:15 +00001032
Simon Kelley7622fc02009-06-04 20:32:05 +01001033
Simon Kelleyf2621c72007-04-29 19:47:21 +01001034 /* must do this just before select(), when we know no
1035 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +01001036 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001037
Simon Kelleyb842bc92015-07-12 21:09:11 +01001038 if (do_poll(timeout) < 0)
1039 continue;
1040
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001041 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001042
Simon Kelleyb842bc92015-07-12 21:09:11 +01001043 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +01001044
1045 /* prime. */
1046 enumerate_interfaces(1);
1047
Simon Kelley74c95c22011-10-19 09:33:39 +01001048 /* Check the interfaces to see if any have exited DAD state
1049 and if so, bind the address. */
1050 if (is_dad_listeners())
1051 {
Simon Kelley115ac3e2013-05-20 11:28:32 +01001052 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +01001053 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
1054 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +01001055 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +01001056 }
Simon Kelleyf2621c72007-04-29 19:47:21 +01001057
Simon Kelley1ee9be42013-12-09 16:50:19 +00001058#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001059 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001060 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001061#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001062 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001063 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001064#endif
1065
Simon Kelley04918052015-01-26 11:23:43 +00001066#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001067 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001068 {
1069 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1070 poll_resolv(1, 1, now);
1071 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001072#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001073 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001074 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001075 if (daemon->last_resolv == 0 ||
1076 difftime(now, daemon->last_resolv) > 1.0 ||
1077 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001078 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001079 /* poll_resolv doesn't need to reload first time through, since
1080 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001081
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001082 poll_resolv(0, daemon->last_resolv != 0, now);
1083 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001084 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001085#endif
1086
Simon Kelleyb842bc92015-07-12 21:09:11 +01001087 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001088 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001089
Simon Kelley3d8df262005-08-29 12:19:27 +01001090#ifdef HAVE_DBUS
1091 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001092 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001093 {
1094 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001095 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001096 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001097 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001098 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001099 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001100 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001101#endif
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001102
1103#ifdef HAVE_UBUS
Kevin Darbyshire-Bryant9d6fd172018-07-28 13:26:39 +01001104 if (option_bool(OPT_UBUS))
Julian Kornberger8dcdb332018-07-21 22:11:08 +01001105 check_ubus_listeners();
Julian Kornbergercaf4d572018-07-21 21:45:03 +01001106#endif
1107
Simon Kelleyb842bc92015-07-12 21:09:11 +01001108 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001109
1110#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001111 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001112#endif
1113
Simon Kelley7622fc02009-06-04 20:32:05 +01001114#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001115 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001116 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001117 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001118 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001119 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001120 dhcp_packet(now, 1);
1121 }
Simon Kelley16972692006-10-16 20:04:18 +01001122
Simon Kelley52b92f42012-01-22 16:05:15 +00001123#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001124 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001125 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001126
Simon Kelleyb842bc92015-07-12 21:09:11 +01001127 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001128 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001129#endif
1130
Simon Kelley1f15b812009-10-13 17:49:32 +01001131# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001132 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001133 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001134# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001135#endif
1136
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001137 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001138}
1139
Simon Kelley3be34542004-09-11 19:12:13 +01001140static void sig_handler(int sig)
1141{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001142 if (pid == 0)
1143 {
Simon Kelley16972692006-10-16 20:04:18 +01001144 /* ignore anything other than TERM during startup
1145 and in helper proc. (helper ignore TERM too) */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001146 if (sig == SIGTERM || sig == SIGINT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001147 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001148 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001149 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001150 {
Simon Kelley16972692006-10-16 20:04:18 +01001151 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001152 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001153 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001154 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001155 else
1156 {
1157 /* master process */
1158 int event, errsave = errno;
1159
1160 if (sig == SIGHUP)
1161 event = EVENT_RELOAD;
1162 else if (sig == SIGCHLD)
1163 event = EVENT_CHILD;
1164 else if (sig == SIGALRM)
1165 event = EVENT_ALARM;
1166 else if (sig == SIGTERM)
1167 event = EVENT_TERM;
1168 else if (sig == SIGUSR1)
1169 event = EVENT_DUMP;
1170 else if (sig == SIGUSR2)
1171 event = EVENT_REOPEN;
Simon Kelley3c973ad2018-01-14 21:05:37 +00001172 else if (sig == SIGINT)
1173 {
1174 /* Handle SIGINT normally in debug mode, so
1175 ctrl-c continues to operate. */
1176 if (option_bool(OPT_DEBUG))
1177 exit(EC_MISC);
1178 else
1179 event = EVENT_TIME;
1180 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001181 else
1182 return;
1183
Simon Kelleyc72daea2012-01-05 21:33:27 +00001184 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001185 errno = errsave;
1186 }
Simon Kelley3be34542004-09-11 19:12:13 +01001187}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001188
Simon Kelley353ae4d2012-03-19 20:07:51 +00001189/* now == 0 -> queue immediate callback */
1190void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001191{
Simon Kelley884a6df2012-03-20 16:20:22 +00001192 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001193 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001194 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1195 if ((now == 0 || difftime(event, now) <= 0.0))
1196 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1197 else
1198 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001199 }
Simon Kelley741c2952012-02-25 13:09:18 +00001200}
1201
Simon Kelley47a95162014-07-08 22:22:02 +01001202void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001203{
Simon Kelley47a95162014-07-08 22:22:02 +01001204 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001205}
1206
Simon Kelleyc72daea2012-01-05 21:33:27 +00001207void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001208{
1209 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001210 struct iovec iov[2];
1211
Simon Kelley5aabfc72007-08-29 11:24:47 +01001212 ev.event = event;
1213 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001214 ev.msg_sz = msg ? strlen(msg) : 0;
1215
1216 iov[0].iov_base = &ev;
1217 iov[0].iov_len = sizeof(ev);
1218 iov[1].iov_base = msg;
1219 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001220
1221 /* error pipe, debug mode. */
1222 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001223 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001224 else
1225 /* pipe is non-blocking and struct event_desc is smaller than
1226 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001227 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001228}
Simon Kelley3d8df262005-08-29 12:19:27 +01001229
Simon Kelleyc72daea2012-01-05 21:33:27 +00001230/* NOTE: the memory used to return msg is leaked: use msgs in events only
1231 to describe fatal errors. */
1232static int read_event(int fd, struct event_desc *evp, char **msg)
1233{
1234 char *buf;
1235
1236 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1237 return 0;
1238
1239 *msg = NULL;
1240
1241 if (evp->msg_sz != 0 &&
1242 (buf = malloc(evp->msg_sz + 1)) &&
1243 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1244 {
1245 buf[evp->msg_sz] = 0;
1246 *msg = buf;
1247 }
1248
1249 return 1;
1250}
1251
1252static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001253{
1254 errno = ev->data;
1255
1256 switch (ev->event)
1257 {
1258 case EVENT_DIE:
1259 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001260
1261 case EVENT_FORK_ERR:
1262 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001263
1264 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001265 case EVENT_PIPE_ERR:
1266 die(_("failed to create helper: %s"), NULL, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001267
1268 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001269 case EVENT_CAP_ERR:
1270 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1271
Simon Kelleye7a4af82018-02-16 21:27:35 +00001272 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001273 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001274 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001275
Simon Kelleye7a4af82018-02-16 21:27:35 +00001276 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001277 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001278 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001279
1280 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001281 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001282 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001283
Simon Kelleye7a4af82018-02-16 21:27:35 +00001284 /* fall through */
Simon Kelley1a6bca82008-07-11 11:11:42 +01001285 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001286 die(_("cannot open log %s: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001287
1288 /* fall through */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001289 case EVENT_LUA_ERR:
1290 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001291
Simon Kelleye7a4af82018-02-16 21:27:35 +00001292 /* fall through */
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001293 case EVENT_TFTP_ERR:
1294 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelleye7a4af82018-02-16 21:27:35 +00001295
1296 /* fall through */
Simon Kelley360f2512015-03-07 18:28:06 +00001297 case EVENT_TIME_ERR:
1298 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001299 }
1300}
1301
Simon Kelley5aabfc72007-08-29 11:24:47 +01001302static void async_event(int pipe, time_t now)
1303{
1304 pid_t p;
1305 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001306 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001307 char *msg;
1308
1309 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1310 to describe fatal errors. */
1311
1312 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001313 switch (ev.event)
1314 {
1315 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001316 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
Simon Kelley3c973ad2018-01-14 21:05:37 +00001317
Simon Kelleye98bd522014-03-28 20:41:23 +00001318 /* fall through */
1319
1320 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001321 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001322
Simon Kelley7b1eae42014-02-20 13:43:28 +00001323 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001324 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001325 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1326 {
1327 reload_servers(daemon->resolv_files->name);
1328 check = 1;
1329 }
1330
1331 if (daemon->servers_file)
1332 {
1333 read_servers_file();
1334 check = 1;
1335 }
1336
1337 if (check)
1338 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001339 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001340
Simon Kelley7622fc02009-06-04 20:32:05 +01001341#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001342 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001343#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001344 break;
1345
1346 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001347 if (daemon->port != 0)
1348 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001349 break;
1350
1351 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001352#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001353 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001354 {
1355 lease_prune(NULL, now);
1356 lease_update_file(now);
1357 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001358#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001359 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001360 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1361 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001362#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001363#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001364 break;
1365
1366 case EVENT_CHILD:
1367 /* See Stevens 5.10 */
1368 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1369 if (p == -1)
1370 {
1371 if (errno != EINTR)
1372 break;
1373 }
1374 else
1375 for (i = 0 ; i < MAX_PROCS; i++)
1376 if (daemon->tcp_pids[i] == p)
1377 daemon->tcp_pids[i] = 0;
1378 break;
1379
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001380#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001381 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001382 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001383 break;
1384
1385 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001386 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001387 break;
1388
1389 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001390 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1391 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001392 break;
1393
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001394 case EVENT_SCRIPT_LOG:
1395 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1396 free(msg);
1397 msg = NULL;
1398 break;
1399
Simon Kelley1a6bca82008-07-11 11:11:42 +01001400 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001401 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001402 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001403 case EVENT_LUA_ERR:
1404 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001405 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001406#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001407
Simon Kelley5aabfc72007-08-29 11:24:47 +01001408 case EVENT_REOPEN:
1409 /* Note: this may leave TCP-handling processes with the old file still open.
1410 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1411 we leave them logging to the old file. */
1412 if (daemon->log_file != NULL)
1413 log_reopen(daemon->log_file);
1414 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001415
1416 case EVENT_NEWADDR:
1417 newaddress(now);
1418 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001419
1420 case EVENT_NEWROUTE:
1421 resend_query();
1422 /* Force re-reading resolv file right now, for luck. */
1423 poll_resolv(0, 1, now);
1424 break;
1425
Simon Kelley3c973ad2018-01-14 21:05:37 +00001426 case EVENT_TIME:
1427#ifdef HAVE_DNSSEC
1428 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1429 {
1430 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1431 daemon->dnssec_no_time_check = 0;
1432 clear_cache_and_reload(now);
1433 }
1434#endif
1435 break;
1436
Simon Kelley5aabfc72007-08-29 11:24:47 +01001437 case EVENT_TERM:
1438 /* Knock all our children on the head. */
1439 for (i = 0; i < MAX_PROCS; i++)
1440 if (daemon->tcp_pids[i] != 0)
1441 kill(daemon->tcp_pids[i], SIGALRM);
1442
Simon Kelley53a91732016-01-06 17:59:13 +00001443#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001444 /* handle pending lease transitions */
1445 if (daemon->helperfd != -1)
1446 {
1447 /* block in writes until all done */
1448 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1449 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1450 do {
1451 helper_write();
1452 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001453 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001454 }
1455#endif
1456
1457 if (daemon->lease_stream)
1458 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001459
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001460#ifdef HAVE_DNSSEC
1461 /* update timestamp file on TERM if time is considered valid */
1462 if (daemon->back_to_the_future)
1463 {
Vladislav Grishenko4583dd92017-05-03 23:16:51 +01001464 if (utimes(daemon->timestamp_file, NULL) == -1)
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001465 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1466 }
1467#endif
1468
Simon Kelley73a08a22009-02-05 20:28:08 +00001469 if (daemon->runfile)
1470 unlink(daemon->runfile);
Simon Kelley6b173352018-05-08 18:32:14 +01001471
1472#ifdef HAVE_DUMPFILE
1473 if (daemon->dumpfd != -1)
1474 close(daemon->dumpfd);
1475#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001476
1477 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1478 flush_log();
1479 exit(EC_GOOD);
1480 }
1481}
1482
Simon Kelley47a95162014-07-08 22:22:02 +01001483static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001484{
1485 struct resolvc *res, *latest;
1486 struct stat statbuf;
1487 time_t last_change = 0;
1488 /* There may be more than one possible file.
1489 Go through and find the one which changed _last_.
1490 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001491
Simon Kelley28866e92011-02-14 20:19:14 +00001492 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001493 return;
1494
Simon Kelley5aabfc72007-08-29 11:24:47 +01001495 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1496 if (stat(res->name, &statbuf) == -1)
1497 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001498 if (force)
1499 {
1500 res->mtime = 0;
1501 continue;
1502 }
1503
Simon Kelley5aabfc72007-08-29 11:24:47 +01001504 if (!res->logged)
1505 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1506 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001507
1508 if (res->mtime != 0)
1509 {
1510 /* existing file evaporated, force selection of the latest
1511 file even if its mtime hasn't changed since we last looked */
1512 poll_resolv(1, do_reload, now);
1513 return;
1514 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001515 }
1516 else
1517 {
1518 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001519 if (force || (statbuf.st_mtime != res->mtime))
1520 {
1521 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001522 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1523 {
1524 last_change = statbuf.st_mtime;
1525 latest = res;
1526 }
1527 }
1528 }
1529
1530 if (latest)
1531 {
1532 static int warned = 0;
1533 if (reload_servers(latest->name))
1534 {
1535 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1536 warned = 0;
1537 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001538 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001539 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001540 }
1541 else
1542 {
1543 latest->mtime = 0;
1544 if (!warned)
1545 {
1546 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1547 warned = 1;
1548 }
1549 }
1550 }
1551}
1552
1553void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001554{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001555 (void)now;
1556
Simon Kelley824af852008-02-12 20:43:05 +00001557 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001558 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001559
Simon Kelley7622fc02009-06-04 20:32:05 +01001560#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001561 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001562 {
Simon Kelley28866e92011-02-14 20:19:14 +00001563 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001564 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001565 reread_dhcp();
Simon Kelley3d8df262005-08-29 12:19:27 +01001566 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001567 lease_update_from_configs();
1568 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001569 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001570 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001571#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001572 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001573 /* Not doing DHCP, so no lease system, manage
1574 alarms for ra only */
1575 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001576#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001577#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001578}
1579
Simon Kelleyb842bc92015-07-12 21:09:11 +01001580static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001581{
1582 struct serverfd *serverfdp;
1583 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001584 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001585
1586#ifdef HAVE_TFTP
1587 int tftp = 0;
1588 struct tftp_transfer *transfer;
1589 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1590 {
1591 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001592 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001593 }
1594#endif
1595
Simon Kelley16972692006-10-16 20:04:18 +01001596 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001597 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001598 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001599
Simon Kelley3be34542004-09-11 19:12:13 +01001600 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001601 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001602
Simon Kelley1a6bca82008-07-11 11:11:42 +01001603 if (daemon->port != 0 && !daemon->osport)
1604 for (i = 0; i < RANDOM_SOCKS; i++)
1605 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001606 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001607
Simon Kelley3be34542004-09-11 19:12:13 +01001608 for (listener = daemon->listeners; listener; listener = listener->next)
1609 {
Simon Kelley16972692006-10-16 20:04:18 +01001610 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001611 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001612 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001613
Simon Kelley16972692006-10-16 20:04:18 +01001614 /* death of a child goes through the select loop, so
1615 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001616 if (listener->tcpfd != -1)
1617 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001618 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley824af852008-02-12 20:43:05 +00001619 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001620 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001621 break;
1622 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001623
Simon Kelley832af0b2007-01-21 20:01:28 +00001624#ifdef HAVE_TFTP
1625 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001626 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001627#endif
1628
1629 }
1630
Simon Kelleya799ca02018-10-18 19:35:29 +01001631#ifndef NO_FORK
1632 if (!option_bool(OPT_DEBUG))
1633 for (i = 0; i < MAX_PROCS; i++)
1634 if (daemon->tcp_pipes[i] != -1)
1635 poll_listen(daemon->tcp_pipes[i], POLLIN);
1636#endif
1637
Simon Kelley16972692006-10-16 20:04:18 +01001638 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001639}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001640
Simon Kelleyb842bc92015-07-12 21:09:11 +01001641static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001642{
1643 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001644 struct listener *listener;
1645 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001646#ifndef NO_FORK
1647 int pipefd[2];
1648#endif
1649
Simon Kelley832af0b2007-01-21 20:01:28 +00001650 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001651 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001652 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1653
1654 if (daemon->port != 0 && !daemon->osport)
1655 for (i = 0; i < RANDOM_SOCKS; i++)
1656 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001657 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001658 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelleya799ca02018-10-18 19:35:29 +01001659
1660#ifndef NO_FORK
1661 /* Races. The child process can die before we read all of the data from the
1662 pipe, or vice versa. Therefore send tcp_pids to zero when we wait() the
1663 process, and tcp_pipes to -1 and close the FD when we read the last
1664 of the data - indicated by cache_recv_insert returning zero.
1665 The order of these events is indeterminate, and both are needed
1666 to free the process slot. Once the child process has gone, poll()
1667 returns POLLHUP, not POLLIN, so have to check for both here. */
1668 if (!option_bool(OPT_DEBUG))
1669 for (i = 0; i < MAX_PROCS; i++)
1670 if (daemon->tcp_pipes[i] != -1 &&
1671 poll_check(daemon->tcp_pipes[i], POLLIN | POLLHUP) &&
1672 !cache_recv_insert(now, daemon->tcp_pipes[i]))
1673 {
1674 close(daemon->tcp_pipes[i]);
1675 daemon->tcp_pipes[i] = -1;
1676 }
1677#endif
1678
Simon Kelley832af0b2007-01-21 20:01:28 +00001679 for (listener = daemon->listeners; listener; listener = listener->next)
1680 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001681 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001682 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001683
Simon Kelley832af0b2007-01-21 20:01:28 +00001684#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001685 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001686 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001687#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001688
Simon Kelleyb842bc92015-07-12 21:09:11 +01001689 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001690 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001691 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001692 struct irec *iface = NULL;
1693 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001694 union mysockaddr tcp_addr;
1695 socklen_t tcp_len = sizeof(union mysockaddr);
1696
1697 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001698
Simon Kelley46b06652013-02-04 21:47:59 +00001699 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001700 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001701
Simon Kelley46b06652013-02-04 21:47:59 +00001702 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1703 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001704 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001705 continue;
1706 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001707
1708 /* Make sure that the interface list is up-to-date.
1709
1710 We do this here as we may need the results below, and
1711 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001712
Simon Kelley76dd75d2013-05-23 10:04:25 +01001713 Multiple calls to enumerate_interfaces() per select loop are
1714 inhibited, so calls to it in the child process (which doesn't select())
1715 have no effect. This avoids two processes reading from the same
1716 netlink fd and screwing the pooch entirely.
1717 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001718
Simon Kelley76dd75d2013-05-23 10:04:25 +01001719 enumerate_interfaces(0);
1720
1721 if (option_bool(OPT_NOWILD))
1722 iface = listener->iface; /* May be NULL */
1723 else
1724 {
1725 int if_index;
1726 char intr_name[IF_NAMESIZE];
1727
1728 /* if we can find the arrival interface, check it's one that's allowed */
1729 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1730 indextoname(listener->tcpfd, if_index, intr_name))
1731 {
1732 struct all_addr addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001733
Simon Kelley76dd75d2013-05-23 10:04:25 +01001734 if (tcp_addr.sa.sa_family == AF_INET6)
1735 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleyee875042018-10-23 22:10:17 +01001736 else
1737 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001738
1739 for (iface = daemon->interfaces; iface; iface = iface->next)
1740 if (iface->index == if_index)
1741 break;
1742
1743 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1744 client_ok = 0;
1745 }
1746
1747 if (option_bool(OPT_CLEVERBIND))
1748 iface = listener->iface; /* May be NULL */
1749 else
1750 {
1751 /* Check for allowed interfaces when binding the wildcard address:
1752 we do this by looking for an interface with the same address as
1753 the local address of the TCP connection, then looking to see if that's
1754 an allowed interface. As a side effect, we get the netmask of the
1755 interface too, for localisation. */
1756
1757 for (iface = daemon->interfaces; iface; iface = iface->next)
1758 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1759 break;
1760
1761 if (!iface)
1762 client_ok = 0;
1763 }
1764 }
1765
Simon Kelley22ce5502013-01-22 13:53:04 +00001766 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001767 {
1768 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001769 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001770 }
1771#ifndef NO_FORK
Simon Kelleya799ca02018-10-18 19:35:29 +01001772 else if (!option_bool(OPT_DEBUG) && pipe(pipefd) == 0 && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001773 {
Simon Kelleya799ca02018-10-18 19:35:29 +01001774 close(pipefd[1]); /* parent needs read pipe end. */
1775 if (p == -1)
1776 close(pipefd[0]);
1777 else
Simon Kelley832af0b2007-01-21 20:01:28 +00001778 {
1779 int i;
Simon Kelleya799ca02018-10-18 19:35:29 +01001780
Simon Kelley832af0b2007-01-21 20:01:28 +00001781 for (i = 0; i < MAX_PROCS; i++)
Simon Kelleya799ca02018-10-18 19:35:29 +01001782 if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001783 {
1784 daemon->tcp_pids[i] = p;
Simon Kelleya799ca02018-10-18 19:35:29 +01001785 daemon->tcp_pipes[i] = pipefd[0];
Simon Kelley832af0b2007-01-21 20:01:28 +00001786 break;
1787 }
1788 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001789 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001790
1791 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1792 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001793 }
1794#endif
1795 else
1796 {
1797 unsigned char *buff;
1798 struct server *s;
1799 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001800 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001801 int auth_dns;
Simon Kelleya799ca02018-10-18 19:35:29 +01001802
Simon Kelley52d4abf2012-03-21 21:39:48 +00001803 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001804 {
1805 netmask = iface->netmask;
1806 auth_dns = iface->dns_auth;
1807 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001808 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001809 {
1810 netmask.s_addr = 0;
1811 auth_dns = 0;
1812 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001813
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001814#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001815 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001816 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001817 if (!option_bool(OPT_DEBUG))
Simon Kelleya799ca02018-10-18 19:35:29 +01001818 {
1819 alarm(CHILD_LIFETIME);
1820 close(pipefd[0]); /* close read end in child. */
1821 daemon->pipe_to_parent = pipefd[1];
1822 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001823#endif
1824
Simon Kelley832af0b2007-01-21 20:01:28 +00001825 /* start with no upstream connections. */
1826 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001827 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001828
1829 /* The connected socket inherits non-blocking
1830 attribute from the listening socket.
1831 Reset that here. */
1832 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1833 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1834
Simon Kelley4f7b3042012-11-28 21:27:02 +00001835 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001836
Simon Kelley832af0b2007-01-21 20:01:28 +00001837 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001838 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001839
1840 if (buff)
1841 free(buff);
1842
1843 for (s = daemon->servers; s; s = s->next)
1844 if (s->tcpfd != -1)
1845 {
1846 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001847 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001848 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001849#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001850 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001851 {
1852 flush_log();
1853 _exit(0);
1854 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001855#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001856 }
1857 }
1858 }
Simon Kelley3be34542004-09-11 19:12:13 +01001859}
1860
Simon Kelley7622fc02009-06-04 20:32:05 +01001861#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001862int make_icmp_sock(void)
1863{
Simon Kelley7cebd202006-05-06 14:13:33 +01001864 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001865 int zeroopt = 0;
1866
1867 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1868 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001869 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001870 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1871 {
1872 close(fd);
1873 fd = -1;
1874 }
1875 }
1876
1877 return fd;
1878}
1879
Simon Kelley5aabfc72007-08-29 11:24:47 +01001880int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001881{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001882 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001883
Floris Bos503c6092017-04-09 23:07:13 +01001884 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001885 struct sockaddr_in saddr;
1886 struct {
1887 struct ip ip;
1888 struct icmp icmp;
1889 } packet;
1890 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001891 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001892 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001893
Simon Kelley824af852008-02-12 20:43:05 +00001894#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001895 if ((fd = make_icmp_sock()) == -1)
1896 return 0;
1897#else
1898 int opt = 2000;
1899 fd = daemon->dhcp_icmp_fd;
1900 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1901#endif
1902
Simon Kelley3be34542004-09-11 19:12:13 +01001903 saddr.sin_family = AF_INET;
1904 saddr.sin_port = 0;
1905 saddr.sin_addr = addr;
1906#ifdef HAVE_SOCKADDR_SA_LEN
1907 saddr.sin_len = sizeof(struct sockaddr_in);
1908#endif
1909
1910 memset(&packet.icmp, 0, sizeof(packet.icmp));
1911 packet.icmp.icmp_type = ICMP_ECHO;
1912 packet.icmp.icmp_id = id;
1913 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1914 j += ((u16 *)&packet.icmp)[i];
1915 while (j>>16)
1916 j = (j & 0xffff) + (j >> 16);
1917 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1918
Simon Kelleyff841eb2015-03-11 21:36:30 +00001919 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1920 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001921
Floris Bos503c6092017-04-09 23:07:13 +01001922 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1923
1924#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1925 while (retry_send(close(fd)));
1926#else
1927 opt = 1;
1928 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1929#endif
1930
1931 return gotreply;
1932}
1933
1934int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1935{
1936 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1937 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1938 from "addr" with ICMP ID "id" and return 1 */
1939
1940 /* Note that whilst waiting, we check for
1941 (and service) events on the DNS and TFTP sockets, (so doing that
1942 better not use any resources our caller has in use...)
1943 but we remain deaf to signals or further DHCP packets. */
1944
1945 /* There can be a problem using dnsmasq_time() to end the loop, since
1946 it's not monotonic, and can go backwards if the system clock is
1947 tweaked, leading to the code getting stuck in this loop and
1948 ignoring DHCP requests. To fix this, we check to see if select returned
1949 as a result of a timeout rather than a socket becoming available. We
1950 only allow this to happen as many times as it takes to get to the wait time
1951 in quarter-second chunks. This provides a fallback way to end loop. */
1952
1953 int rc, timeout_count;
1954 time_t now;
1955
1956 for (now = dnsmasq_time(), timeout_count = 0;
1957 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001958 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001959 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001960 if (fd != -1)
1961 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001962 set_dns_listeners(now);
1963 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001964
1965#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001966 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001967 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001968#endif
1969
Simon Kelleyb842bc92015-07-12 21:09:11 +01001970 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001971
1972 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001973 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001974 else if (rc == 0)
1975 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001976
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001977 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001978
Simon Kelleyb842bc92015-07-12 21:09:11 +01001979 check_log_writer(0);
1980 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001981
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001982#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001983 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001984 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001985#endif
1986
Simon Kelley832af0b2007-01-21 20:01:28 +00001987#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001988 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001989#endif
1990
Floris Bos503c6092017-04-09 23:07:13 +01001991 if (fd != -1)
1992 {
1993 struct {
1994 struct ip ip;
1995 struct icmp icmp;
1996 } packet;
1997 struct sockaddr_in faddr;
1998 socklen_t len = sizeof(faddr);
1999
2000 if (poll_check(fd, POLLIN) &&
2001 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
2002 addr == faddr.sin_addr.s_addr &&
2003 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
2004 packet.icmp.icmp_seq == 0 &&
2005 packet.icmp.icmp_id == id)
2006 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01002007 }
2008 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01002009
Floris Bos503c6092017-04-09 23:07:13 +01002010 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01002011}
Simon Kelley7622fc02009-06-04 20:32:05 +01002012#endif
Simon Kelley0a852542005-03-23 20:28:59 +00002013
2014