blob: 04d57580f24bfc7af41c15e4a70ec4ac614cebd7 [file] [log] [blame]
Simon Kelleyaff33962015-01-31 20:13:40 +00001/* dnsmasq is Copyright (c) 2000-2015 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;
51#if defined(HAVE_LINUX_NETWORK)
52 cap_user_header_t hdr = NULL;
53 cap_user_data_t data = NULL;
Simon Kelley3b3f4412013-10-11 16:33:28 +010054 char *bound_device = NULL;
55 int did_bind = 0;
Simon Kelley1a6bca82008-07-11 11:11:42 +010056#endif
Vladislav Grishenko408c3682013-09-24 16:18:49 +010057#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
Simon Kelley1f776932012-12-16 19:46:08 +000058 struct dhcp_context *context;
Simon Kelleyff7eea22013-09-04 18:01:38 +010059 struct dhcp_relay *relay;
Vladislav Grishenko408c3682013-09-24 16:18:49 +010060#endif
Stefan Tomanek30d08792015-03-31 22:32:11 +010061#ifdef HAVE_TFTP
62 int tftp_prefix_missing = 0;
63#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +010064
Simon Kelley824af852008-02-12 20:43:05 +000065#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000066 setlocale(LC_ALL, "");
67 bindtextdomain("dnsmasq", LOCALEDIR);
68 textdomain("dnsmasq");
69#endif
70
Simon Kelley9e4abcb2004-01-22 19:47:41 +000071 sigact.sa_handler = sig_handler;
72 sigact.sa_flags = 0;
73 sigemptyset(&sigact.sa_mask);
74 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010075 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000076 sigaction(SIGHUP, &sigact, NULL);
77 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000078 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010079 sigaction(SIGCHLD, &sigact, NULL);
80
81 /* ignore SIGPIPE */
82 sigact.sa_handler = SIG_IGN;
83 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000084
Simon Kelley5aabfc72007-08-29 11:24:47 +010085 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010086
87 rand_init(); /* Must precede read_opts() */
88
Simon Kelley5aabfc72007-08-29 11:24:47 +010089 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000090
Simon Kelley3be34542004-09-11 19:12:13 +010091 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000092 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000093
Simon Kelley0a852542005-03-23 20:28:59 +000094 daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
95 daemon->edns_pktsz : DNSMASQ_PACKETSZ;
96 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +000097
Simon Kelleyc72daea2012-01-05 21:33:27 +000098 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +000099 if (option_bool(OPT_EXTRALOG))
100 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000101
102#ifdef HAVE_DNSSEC
103 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000104 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100105 /* Note that both /000 and '.' are allowed within labels. These get
106 represented in presentation format using NAME_ESCAPE as an escape
107 character when in DNSSEC mode.
108 In theory, if all the characters in a name were /000 or
109 '.' or NAME_ESCAPE then all would have to be escaped, so the
110 presentation format would be twice as long as the spec.
111
112 daemon->namebuff was previously allocated by the option-reading
113 code before we knew if we're in DNSSEC mode, so reallocate here. */
114 free(daemon->namebuff);
115 daemon->namebuff = safe_malloc(MAXDNAME * 2);
116 daemon->keyname = safe_malloc(MAXDNAME * 2);
117 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley5107ace2014-02-23 10:48:32 +0000118 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000119#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000120
Simon Kelley7622fc02009-06-04 20:32:05 +0100121#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100122 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000123 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000124 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100125 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000126 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100127#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000128
Simon Kelleya2761752012-01-18 16:07:21 +0000129 /* Close any file descriptors we inherited apart from std{in|out|err}
130
131 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
132 otherwise file descriptors we create can end up being 0, 1, or 2
133 and then get accidentally closed later when we make 0, 1, and 2
134 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
135 but it's not guaranteed. By opening /dev/null three times, we
136 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100137 for (i = 0; i < max_fd; i++)
138 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
139 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000140 else
141 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100142
Simon Kelley801ca9a2012-03-06 19:30:17 +0000143#ifndef HAVE_LINUX_NETWORK
144# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000145 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100146 {
147 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000148 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100149 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000150# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100151
152 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100153 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100154 {
155 bind_fallback = 1;
156 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100157 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100158 }
Simon Kelley04918052015-01-26 11:23:43 +0000159#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000160
Simon Kelley04918052015-01-26 11:23:43 +0000161#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000162 if (daemon->dynamic_dirs)
163 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100164#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100165
Simon Kelley0744ca62014-01-25 16:40:15 +0000166 if (option_bool(OPT_DNSSEC_VALID))
167 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000168#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +0000169 if (!daemon->ds)
Simon Kelley360f2512015-03-07 18:28:06 +0000170 die(_("no trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000171
172 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000173 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000174#else
175 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000176#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000177 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000178
Simon Kelley832af0b2007-01-21 20:01:28 +0000179#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100180 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100181 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000182#endif
183
Simon Kelley7de060b2011-08-26 17:24:52 +0100184#ifdef HAVE_CONNTRACK
185 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000186 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100187#else
188 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000189 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100190#endif
191
Simon Kelley824af852008-02-12 20:43:05 +0000192#ifdef HAVE_SOLARIS_NETWORK
193 if (daemon->max_logs != 0)
194 die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
195#endif
196
Simon Kelley572b41e2011-02-18 18:11:18 +0000197#ifdef __ANDROID__
198 if (daemon->max_logs != 0)
199 die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
200#endif
201
Simon Kelley4820dce2012-12-18 18:30:30 +0000202#ifndef HAVE_AUTH
203 if (daemon->authserver)
204 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
205#endif
206
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100207#ifndef HAVE_LOOP
208 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000209 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100210#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100211
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100212 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000213
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000214 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000215 if (daemon->authinterface && daemon->soa_sn == 0)
216#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000217 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000218#else
219 daemon->soa_sn = now;
220#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000221
Simon Kelleyff7eea22013-09-04 18:01:38 +0100222#ifdef HAVE_DHCP6
223 if (daemon->dhcp6)
224 {
225 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000226
Simon Kelleyff7eea22013-09-04 18:01:38 +0100227 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000228 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100229 if (context->flags & CONTEXT_DHCP)
230 daemon->doing_dhcp6 = 1;
231 if (context->flags & CONTEXT_RA)
232 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000233#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100234 if (context->flags & CONTEXT_TEMPLATE)
235 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000236#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000237 }
Simon Kelley1f776932012-12-16 19:46:08 +0000238 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100239#endif
240
241#ifdef HAVE_DHCP
242 /* Note that order matters here, we must call lease_init before
243 creating any file descriptors which shouldn't be leaked
244 to the lease-script init process. We need to call common_init
245 before lease_init to allocate buffers it uses.*/
246 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || daemon->relay6)
247 {
248 dhcp_common_init();
249 if (daemon->dhcp || daemon->doing_dhcp6)
250 lease_init(now);
251 }
252
253 if (daemon->dhcp || daemon->relay4)
254 dhcp_init();
255
256# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100257 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100258 ra_init(now);
259
260 if (daemon->doing_dhcp6 || daemon->relay6)
261 dhcp6_init();
262# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000263
Simon Kelley7622fc02009-06-04 20:32:05 +0100264#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100265
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000266#ifdef HAVE_IPSET
267 if (daemon->ipsets)
268 ipset_init();
269#endif
270
Simon Kelley1ee9be42013-12-09 16:50:19 +0000271#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000272 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000273#elif defined(HAVE_BSD_NETWORK)
274 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000275#endif
276
Simon Kelley1ee9be42013-12-09 16:50:19 +0000277 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
278 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
279
Simon Kelley115ac3e2013-05-20 11:28:32 +0100280 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100281 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000282
Simon Kelley54dd3932012-06-20 11:23:38 +0100283 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100284 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100285 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100286
287 if (!option_bool(OPT_CLEVERBIND))
288 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
289 if (if_tmp->name && !if_tmp->used)
290 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100291
292#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
293 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100294 bound_device = whichdevice();
295
Simon Kelley9380ba72012-04-16 14:41:56 +0100296 if (daemon->dhcp)
297 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100298 if (!daemon->relay4 && bound_device)
299 {
300 bindtodevice(bound_device, daemon->dhcpfd);
301 did_bind = 1;
302 }
303 if (daemon->enable_pxe && bound_device)
304 {
305 bindtodevice(bound_device, daemon->pxefd);
306 did_bind = 1;
307 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100308 }
309#endif
310
311#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100312 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
313 {
314 bindtodevice(bound_device, daemon->dhcp6fd);
315 did_bind = 1;
316 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100317#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100318 }
Simon Kelley28866e92011-02-14 20:19:14 +0000319 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100320 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000321
322#ifdef HAVE_DHCP6
323 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100324 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000325 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000326
327 /* After netlink_init() and before create_helper() */
328 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000329#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100330
Simon Kelley824af852008-02-12 20:43:05 +0000331 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000332 {
333 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000334
Simon Kelley82e3f452014-01-31 21:05:48 +0000335#ifdef HAVE_DNSSEC
336 blockdata_init();
337#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000338 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000339
Simon Kelley04918052015-01-26 11:23:43 +0000340#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000341 if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000342 inotify_dnsmasq_init();
343 else
344 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000345#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000346
Simon Kelley28866e92011-02-14 20:19:14 +0000347 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100348#ifdef HAVE_DBUS
349 {
350 char *err;
351 daemon->dbus = NULL;
352 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100353 if ((err = dbus_init()))
354 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100355 }
356#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100357 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100358#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100359
Simon Kelley824af852008-02-12 20:43:05 +0000360 if (daemon->port != 0)
361 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100362
Simon Kelleyc72daea2012-01-05 21:33:27 +0000363#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100364 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000365 if ((daemon->dhcp || daemon->dhcp6) &&
366 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000367 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100368 {
369 if ((ent_pw = getpwnam(daemon->scriptuser)))
370 {
371 script_uid = ent_pw->pw_uid;
372 script_gid = ent_pw->pw_gid;
373 }
374 else
375 baduser = daemon->scriptuser;
376 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100377#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000378
Simon Kelley1a6bca82008-07-11 11:11:42 +0100379 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
380 baduser = daemon->username;
381 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
382 baduser = daemon->groupname;
383
384 if (baduser)
385 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000386
Simon Kelley1a6bca82008-07-11 11:11:42 +0100387 /* implement group defaults, "dip" if available, or group associated with uid */
388 if (!daemon->group_set && !gp)
389 {
390 if (!(gp = getgrnam(CHGRP)) && ent_pw)
391 gp = getgrgid(ent_pw->pw_gid);
392
393 /* for error message */
394 if (gp)
395 daemon->groupname = gp->gr_name;
396 }
397
398#if defined(HAVE_LINUX_NETWORK)
399 /* determine capability API version here, while we can still
400 call safe_malloc */
401 if (ent_pw && ent_pw->pw_uid != 0)
402 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100403 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100404 hdr = safe_malloc(sizeof(*hdr));
405
Simon Kelley1a6bca82008-07-11 11:11:42 +0100406 /* find version supported by kernel */
407 memset(hdr, 0, sizeof(*hdr));
408 capget(hdr, NULL);
409
410 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
411 {
412 /* if unknown version, use largest supported version (3) */
413 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
414 hdr->version = LINUX_CAPABILITY_VERSION_3;
415 capsize = 2;
416 }
417
418 data = safe_malloc(sizeof(*data) * capsize);
419 memset(data, 0, sizeof(*data) * capsize);
420 }
421#endif
422
Simon Kelley5aabfc72007-08-29 11:24:47 +0100423 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100424 in a race-free manner and another to carry errors to daemon-invoking process */
425 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100426
427 piperead = pipefd[0];
428 pipewrite = pipefd[1];
429 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000430 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100431
432 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100433
Simon Kelley28866e92011-02-14 20:19:14 +0000434 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000435 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000436 /* The following code "daemonizes" the process.
437 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100438
Simon Kelley9e038942008-05-30 20:06:34 +0100439 if (chdir("/") != 0)
440 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
441
Simon Kelley16972692006-10-16 20:04:18 +0100442#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000443 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100444 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100445 pid_t pid;
446
Simon Kelley1a6bca82008-07-11 11:11:42 +0100447 /* pipe to carry errors back to original process.
448 When startup is complete we close this and the process terminates. */
449 safe_pipe(err_pipe, 0);
450
Simon Kelley7622fc02009-06-04 20:32:05 +0100451 if ((pid = fork()) == -1)
452 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000453 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100454
Simon Kelley5aabfc72007-08-29 11:24:47 +0100455 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100456 {
457 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000458 char *msg;
459
Simon Kelley1a6bca82008-07-11 11:11:42 +0100460 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000461 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100462
463 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000464 if (read_event(err_pipe[0], &ev, &msg))
465 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100466
467 _exit(EC_GOOD);
468 }
469
Simon Kelleyff841eb2015-03-11 21:36:30 +0000470 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100471
472 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100473
474 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100475
476 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000477 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100478
479 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100480 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100481 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000482#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100483
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000484 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100485 if (daemon->runfile)
486 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100487 int fd, err = 0;
488
489 sprintf(daemon->namebuff, "%d\n", (int) getpid());
490
491 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
492 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
493 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
494 extent that an attacker running as the unprivileged user could replace the pidfile with a
495 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
496
497 The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
498 ensuring that the open() fails should there be any existing file (because the unlink() failed,
499 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
500 attack can succeed.
501
502 Any compromise of the non-privileged user still theoretically allows the pid-file to be
503 replaced whilst dnsmasq is running. The worst that could allow is that the usual
504 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
505
506 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
507 failure to write the pid-file.
508 */
509
510 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100511
Simon Kelley79cfefd2012-09-02 13:29:51 +0100512 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 +0100513 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100514 /* only complain if started as root */
515 if (getuid() == 0)
516 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100517 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100518 else
519 {
520 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
521 err = 1;
Simon Kelleyff841eb2015-03-11 21:36:30 +0000522 else
523 {
524 while (retry_send(close(fd)));
525 if (errno != 0)
526 err = 1;
527 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100528 }
529
530 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100531 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000532 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100533 _exit(0);
534 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000535 }
Simon Kelley16972692006-10-16 20:04:18 +0100536 }
537
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100538 log_err = log_start(ent_pw, err_pipe[1]);
539
Simon Kelley28866e92011-02-14 20:19:14 +0000540 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100541 {
542 /* open stdout etc to /dev/null */
543 int nullfd = open("/dev/null", O_RDWR);
544 dup2(nullfd, STDOUT_FILENO);
545 dup2(nullfd, STDERR_FILENO);
546 dup2(nullfd, STDIN_FILENO);
547 close(nullfd);
548 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100549
Simon Kelley1a6bca82008-07-11 11:11:42 +0100550 /* if we are to run scripts, we need to fork a helper before dropping root. */
551 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000552#ifdef HAVE_SCRIPT
Simon Kelley52b92f42012-01-22 16:05:15 +0000553 if ((daemon->dhcp || daemon->dhcp6) && (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100554 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
555#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100556
Simon Kelley28866e92011-02-14 20:19:14 +0000557 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100558 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100559 int bad_capabilities = 0;
560 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100561
Simon Kelley1a6bca82008-07-11 11:11:42 +0100562 /* remove all supplimentary groups */
563 if (gp &&
564 (setgroups(0, &dummy) == -1 ||
565 setgid(gp->gr_gid) == -1))
566 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000567 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100568 _exit(0);
569 }
570
Simon Kelley7cebd202006-05-06 14:13:33 +0100571 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100572 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100573#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100574 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100575 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100576 ports because of DAD, or we're doing it dynamically,
577 we need CAP_NET_BIND_SERVICE too. */
578 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100579 data->effective = data->permitted = data->inheritable =
580 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
581 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
582 else
583 data->effective = data->permitted = data->inheritable =
584 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100585
Simon Kelley16972692006-10-16 20:04:18 +0100586 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000587 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100588 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100589
Simon Kelley7622fc02009-06-04 20:32:05 +0100590#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000591 /* http://developers.sun.com/solaris/articles/program_privileges.html */
592 priv_set_t *priv_set;
593
594 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
595 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
596 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
597 bad_capabilities = errno;
598
599 if (priv_set && bad_capabilities == 0)
600 {
601 priv_inverse(priv_set);
602
603 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
604 bad_capabilities = errno;
605 }
606
607 if (priv_set)
608 priv_freeset(priv_set);
609
Simon Kelley824af852008-02-12 20:43:05 +0000610#endif
611
Simon Kelley1a6bca82008-07-11 11:11:42 +0100612 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100613 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000614 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100615 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100616 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100617
618 /* finally drop root */
619 if (setuid(ent_pw->pw_uid) == -1)
620 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000621 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100622 _exit(0);
623 }
624
625#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100626 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100627 data->effective = data->permitted =
628 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
629 else
630 data->effective = data->permitted =
631 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100632 data->inheritable = 0;
633
634 /* lose the setuid and setgid capbilities */
635 if (capset(hdr, data) == -1)
636 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000637 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100638 _exit(0);
639 }
640#endif
641
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000642 }
Simon Kelley849a8352006-06-09 21:02:31 +0100643 }
Simon Kelley16972692006-10-16 20:04:18 +0100644
Simon Kelley16972692006-10-16 20:04:18 +0100645#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000646 free(hdr);
647 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000648 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000649 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100650#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100651
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100652#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100653 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100654 {
655 DIR *dir;
656 struct tftp_prefix *p;
657
658 if (daemon->tftp_prefix)
659 {
660 if (!((dir = opendir(daemon->tftp_prefix))))
661 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100662 tftp_prefix_missing = 1;
663 if (!option_bool(OPT_TFTP_NO_FAIL))
664 {
665 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
666 _exit(0);
667 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100668 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100669 else
670 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100671 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100672
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100673 for (p = daemon->if_prefix; p; p = p->next)
674 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100675 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100676 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100677 {
678 p->missing = 1;
679 if (!option_bool(OPT_TFTP_NO_FAIL))
680 {
681 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
682 _exit(0);
683 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100684 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100685 else
686 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100687 }
688 }
689#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100690
Simon Kelley824af852008-02-12 20:43:05 +0000691 if (daemon->port == 0)
692 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
693 else if (daemon->cachesize != 0)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100694 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000695 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100696 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
Simon Kelley16972692006-10-16 20:04:18 +0100697
Simon Kelleyf2621c72007-04-29 19:47:21 +0100698 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley16972692006-10-16 20:04:18 +0100699
Simon Kelley3d8df262005-08-29 12:19:27 +0100700#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000701 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100702 {
703 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100704 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100705 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100706 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100707 }
708#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000709
710 if (option_bool(OPT_LOCAL_SERVICE))
711 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
Simon Kelleydb737462014-01-31 10:32:45 +0000712
Simon Kelley1d97ac42014-01-31 11:12:27 +0000713#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000714 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000715 {
Simon Kelley360f2512015-03-07 18:28:06 +0000716 int rc;
717
718 /* Delay creating the timestamp file until here, after we've changed user, so that
719 it has the correct owner to allow updating the mtime later.
720 This means we have to report fatal errors via the pipe. */
721 if ((rc = setup_timestamp()) == -1)
722 {
723 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
724 _exit(0);
725 }
726
Simon Kelleye98bd522014-03-28 20:41:23 +0000727 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000728
Simon Kelleye98bd522014-03-28 20:41:23 +0000729 if (option_bool(OPT_DNSSEC_TIME))
730 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
Simon Kelley360f2512015-03-07 18:28:06 +0000731
732 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000733 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000734 }
Simon Kelleydb737462014-01-31 10:32:45 +0000735#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100736
Simon Kelley1a6bca82008-07-11 11:11:42 +0100737 if (log_err != 0)
738 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
739 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000740
Simon Kelleyde379512004-06-22 20:23:33 +0100741 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100742 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100743
Simon Kelleyf7029f52013-11-21 15:09:09 +0000744 if (option_bool(OPT_NOWILD))
745 warn_bound_listeners();
746
747 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100748
Simon Kelley28866e92011-02-14 20:19:14 +0000749 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000750 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
751 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100752 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100753
Simon Kelley28866e92011-02-14 20:19:14 +0000754 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100755 {
756 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100757 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100758 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000759 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100760 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100761 }
762
Simon Kelleyf2621c72007-04-29 19:47:21 +0100763 if (daemon->max_logs != 0)
764 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000765
Simon Kelleyf2621c72007-04-29 19:47:21 +0100766
Simon Kelley7622fc02009-06-04 20:32:05 +0100767#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000768 for (context = daemon->dhcp; context; context = context->next)
769 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100770
Simon Kelleyff7eea22013-09-04 18:01:38 +0100771 for (relay = daemon->relay4; relay; relay = relay->next)
772 log_relay(AF_INET, relay);
773
Simon Kelley1f776932012-12-16 19:46:08 +0000774# ifdef HAVE_DHCP6
775 for (context = daemon->dhcp6; context; context = context->next)
776 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000777
Simon Kelleyff7eea22013-09-04 18:01:38 +0100778 for (relay = daemon->relay6; relay; relay = relay->next)
779 log_relay(AF_INET6, relay);
780
Simon Kelley1f776932012-12-16 19:46:08 +0000781 if (daemon->doing_dhcp6 || daemon->doing_ra)
782 dhcp_construct_contexts(now);
783
784 if (option_bool(OPT_RA))
785 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
786# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000787
Simon Kelley3b3f4412013-10-11 16:33:28 +0100788# ifdef HAVE_LINUX_NETWORK
789 if (did_bind)
790 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
791# endif
792
Simon Kelley8445f5d2012-12-17 21:54:08 +0000793 /* after dhcp_contruct_contexts */
794 if (daemon->dhcp || daemon->doing_dhcp6)
795 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000796#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000797
Simon Kelley832af0b2007-01-21 20:01:28 +0000798#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000799 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100800 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100801 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000802
Simon Kelley7622fc02009-06-04 20:32:05 +0100803 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100804 daemon->tftp_prefix ? _("root is ") : _("enabled"),
805 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000806 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100807
Stefan Tomanek30d08792015-03-31 22:32:11 +0100808 if (tftp_prefix_missing)
809 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100810
Stefan Tomanek30d08792015-03-31 22:32:11 +0100811 for (p = daemon->if_prefix; p; p = p->next)
812 if (p->missing)
813 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
814
Simon Kelley832af0b2007-01-21 20:01:28 +0000815 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100816 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000817 a single file will be sent to may clients (the file only needs
818 one fd). */
819
820 max_fd -= 30; /* use other than TFTP */
821
822 if (max_fd < 0)
823 max_fd = 5;
824 else if (max_fd < 100)
825 max_fd = max_fd/2;
826 else
827 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000828
829 /* if we have to use a limited range of ports,
830 that will limit the number of transfers */
831 if (daemon->start_tftp_port != 0 &&
832 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
833 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000834
835 if (daemon->tftp_max > max_fd)
836 {
837 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100838 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100839 _("restricting maximum simultaneous TFTP transfers to %d"),
840 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000841 }
842 }
843#endif
844
Simon Kelley1a6bca82008-07-11 11:11:42 +0100845 /* finished start-up - release original process */
846 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000847 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000848
Simon Kelley824af852008-02-12 20:43:05 +0000849 if (daemon->port != 0)
850 check_servers();
851
Simon Kelley7cebd202006-05-06 14:13:33 +0100852 pid = getpid();
853
Simon Kelley04918052015-01-26 11:23:43 +0000854#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000855 /* Using inotify, have to select a resolv file at startup */
856 poll_resolv(1, 0, now);
857#endif
858
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100859 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000860 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100861 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000862
Simon Kelleyb842bc92015-07-12 21:09:11 +0100863 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000864
Simon Kelley16972692006-10-16 20:04:18 +0100865 /* if we are out of resources, find how long we have to wait
866 for some to come free, we'll loop around then and restart
867 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100868 if ((t = set_dns_listeners(now)) != 0)
869 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100870
Simon Kelley832af0b2007-01-21 20:01:28 +0000871 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
872 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000873 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100874 timeout = 250;
875
Simon Kelley74c95c22011-10-19 09:33:39 +0100876 /* Wake every second whilst waiting for DAD to complete */
877 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100878 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100879
Simon Kelley832af0b2007-01-21 20:01:28 +0000880#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100881 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100882#endif
883
Simon Kelley7622fc02009-06-04 20:32:05 +0100884#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100885 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100886 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100887 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000888 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100889 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100890 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100891#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100892
Simon Kelley52b92f42012-01-22 16:05:15 +0000893#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100894 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100895 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100896
Simon Kelley1f776932012-12-16 19:46:08 +0000897 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100898 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000899#endif
Simon Kelley04918052015-01-26 11:23:43 +0000900
901#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000902 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100903 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000904#endif
905
906#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100907 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000908#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100909 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100910#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000911
Simon Kelleyb842bc92015-07-12 21:09:11 +0100912 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100913
Simon Kelley7622fc02009-06-04 20:32:05 +0100914#ifdef HAVE_DHCP
Simon Kelley1f15b812009-10-13 17:49:32 +0100915# ifdef HAVE_SCRIPT
Simon Kelley5aabfc72007-08-29 11:24:47 +0100916 while (helper_buf_empty() && do_script_run(now));
Simon Kelley16972692006-10-16 20:04:18 +0100917
Simon Kelleya9530962012-03-20 22:07:35 +0000918# ifdef HAVE_TFTP
919 while (helper_buf_empty() && do_tftp_script_run());
920# endif
921
Simon Kelley16972692006-10-16 20:04:18 +0100922 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100923 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley7622fc02009-06-04 20:32:05 +0100924# else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100925 /* need this for other side-effects */
926 while (do_script_run(now));
Simon Kelleya9530962012-03-20 22:07:35 +0000927
928# ifdef HAVE_TFTP
929 while (do_tftp_script_run());
930# endif
931
Simon Kelley7622fc02009-06-04 20:32:05 +0100932# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100933#endif
Simon Kelley7622fc02009-06-04 20:32:05 +0100934
Simon Kelleyf2621c72007-04-29 19:47:21 +0100935 /* must do this just before select(), when we know no
936 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100937 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +0100938
Simon Kelleyb842bc92015-07-12 21:09:11 +0100939 if (do_poll(timeout) < 0)
940 continue;
941
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100942 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000943
Simon Kelleyb842bc92015-07-12 21:09:11 +0100944 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100945
946 /* prime. */
947 enumerate_interfaces(1);
948
Simon Kelley74c95c22011-10-19 09:33:39 +0100949 /* Check the interfaces to see if any have exited DAD state
950 and if so, bind the address. */
951 if (is_dad_listeners())
952 {
Simon Kelley115ac3e2013-05-20 11:28:32 +0100953 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +0100954 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
955 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +0100956 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +0100957 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100958
Simon Kelley1ee9be42013-12-09 16:50:19 +0000959#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100960 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +0100961 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000962#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100963 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +0100964 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +0100965#endif
966
Simon Kelley04918052015-01-26 11:23:43 +0000967#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +0100968 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000969 {
970 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
971 poll_resolv(1, 1, now);
972 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000973#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000974 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +0100975 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +0000976 if (daemon->last_resolv == 0 ||
977 difftime(now, daemon->last_resolv) > 1.0 ||
978 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000979 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100980 /* poll_resolv doesn't need to reload first time through, since
981 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +0100982
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100983 poll_resolv(0, daemon->last_resolv != 0, now);
984 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000985 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000986#endif
987
Simon Kelleyb842bc92015-07-12 21:09:11 +0100988 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100989 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +0100990
Simon Kelley3d8df262005-08-29 12:19:27 +0100991#ifdef HAVE_DBUS
992 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +0000993 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +0100994 {
995 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100996 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +0100997 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +0100998 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100999 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001000 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001001 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001002#endif
Simon Kelley824af852008-02-12 20:43:05 +00001003
Simon Kelleyb842bc92015-07-12 21:09:11 +01001004 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001005
1006#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001007 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001008#endif
1009
Simon Kelley7622fc02009-06-04 20:32:05 +01001010#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001011 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001012 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001013 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001014 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001015 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001016 dhcp_packet(now, 1);
1017 }
Simon Kelley16972692006-10-16 20:04:18 +01001018
Simon Kelley52b92f42012-01-22 16:05:15 +00001019#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001020 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001021 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001022
Simon Kelleyb842bc92015-07-12 21:09:11 +01001023 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001024 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001025#endif
1026
Simon Kelley1f15b812009-10-13 17:49:32 +01001027# ifdef HAVE_SCRIPT
Simon Kelleyb842bc92015-07-12 21:09:11 +01001028 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001029 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001030# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001031#endif
1032
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001033 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001034}
1035
Simon Kelley3be34542004-09-11 19:12:13 +01001036static void sig_handler(int sig)
1037{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001038 if (pid == 0)
1039 {
Simon Kelley16972692006-10-16 20:04:18 +01001040 /* ignore anything other than TERM during startup
1041 and in helper proc. (helper ignore TERM too) */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001042 if (sig == SIGTERM)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001043 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001044 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001045 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001046 {
Simon Kelley16972692006-10-16 20:04:18 +01001047 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001048 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001049 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001050 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001051 else
1052 {
1053 /* master process */
1054 int event, errsave = errno;
1055
1056 if (sig == SIGHUP)
1057 event = EVENT_RELOAD;
1058 else if (sig == SIGCHLD)
1059 event = EVENT_CHILD;
1060 else if (sig == SIGALRM)
1061 event = EVENT_ALARM;
1062 else if (sig == SIGTERM)
1063 event = EVENT_TERM;
1064 else if (sig == SIGUSR1)
1065 event = EVENT_DUMP;
1066 else if (sig == SIGUSR2)
1067 event = EVENT_REOPEN;
1068 else
1069 return;
1070
Simon Kelleyc72daea2012-01-05 21:33:27 +00001071 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001072 errno = errsave;
1073 }
Simon Kelley3be34542004-09-11 19:12:13 +01001074}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001075
Simon Kelley353ae4d2012-03-19 20:07:51 +00001076/* now == 0 -> queue immediate callback */
1077void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001078{
Simon Kelley884a6df2012-03-20 16:20:22 +00001079 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001080 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001081 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1082 if ((now == 0 || difftime(event, now) <= 0.0))
1083 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1084 else
1085 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001086 }
Simon Kelley741c2952012-02-25 13:09:18 +00001087}
1088
Simon Kelley47a95162014-07-08 22:22:02 +01001089void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001090{
Simon Kelley47a95162014-07-08 22:22:02 +01001091 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001092}
1093
Simon Kelleyc72daea2012-01-05 21:33:27 +00001094void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001095{
1096 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001097 struct iovec iov[2];
1098
Simon Kelley5aabfc72007-08-29 11:24:47 +01001099 ev.event = event;
1100 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001101 ev.msg_sz = msg ? strlen(msg) : 0;
1102
1103 iov[0].iov_base = &ev;
1104 iov[0].iov_len = sizeof(ev);
1105 iov[1].iov_base = msg;
1106 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001107
1108 /* error pipe, debug mode. */
1109 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001110 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001111 else
1112 /* pipe is non-blocking and struct event_desc is smaller than
1113 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001114 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001115}
Simon Kelley3d8df262005-08-29 12:19:27 +01001116
Simon Kelleyc72daea2012-01-05 21:33:27 +00001117/* NOTE: the memory used to return msg is leaked: use msgs in events only
1118 to describe fatal errors. */
1119static int read_event(int fd, struct event_desc *evp, char **msg)
1120{
1121 char *buf;
1122
1123 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1124 return 0;
1125
1126 *msg = NULL;
1127
1128 if (evp->msg_sz != 0 &&
1129 (buf = malloc(evp->msg_sz + 1)) &&
1130 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1131 {
1132 buf[evp->msg_sz] = 0;
1133 *msg = buf;
1134 }
1135
1136 return 1;
1137}
1138
1139static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001140{
1141 errno = ev->data;
1142
1143 switch (ev->event)
1144 {
1145 case EVENT_DIE:
1146 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001147
1148 case EVENT_FORK_ERR:
1149 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001150
1151 case EVENT_PIPE_ERR:
1152 die(_("failed to create helper: %s"), NULL, EC_MISC);
1153
1154 case EVENT_CAP_ERR:
1155 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1156
1157 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001158 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001159
1160 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001161 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001162
1163 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001164 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001165
1166 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001167 die(_("cannot open log %s: %s"), msg, EC_FILE);
1168
1169 case EVENT_LUA_ERR:
1170 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001171
1172 case EVENT_TFTP_ERR:
1173 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelley360f2512015-03-07 18:28:06 +00001174
1175 case EVENT_TIME_ERR:
1176 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001177 }
1178}
1179
Simon Kelley5aabfc72007-08-29 11:24:47 +01001180static void async_event(int pipe, time_t now)
1181{
1182 pid_t p;
1183 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001184 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001185 char *msg;
1186
1187 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1188 to describe fatal errors. */
1189
1190 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001191 switch (ev.event)
1192 {
1193 case EVENT_RELOAD:
Simon Kelleye98bd522014-03-28 20:41:23 +00001194#ifdef HAVE_DNSSEC
1195 if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1196 {
1197 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1198 reset_option_bool(OPT_DNSSEC_TIME);
1199 }
1200#endif
1201 /* fall through */
1202
1203 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001204 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001205
Simon Kelley7b1eae42014-02-20 13:43:28 +00001206 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001207 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001208 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1209 {
1210 reload_servers(daemon->resolv_files->name);
1211 check = 1;
1212 }
1213
1214 if (daemon->servers_file)
1215 {
1216 read_servers_file();
1217 check = 1;
1218 }
1219
1220 if (check)
1221 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001222 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001223
Simon Kelley7622fc02009-06-04 20:32:05 +01001224#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001225 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001226#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001227 break;
1228
1229 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001230 if (daemon->port != 0)
1231 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001232 break;
1233
1234 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001235#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001236 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001237 {
1238 lease_prune(NULL, now);
1239 lease_update_file(now);
1240 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001241#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001242 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001243 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1244 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001245#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001246#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001247 break;
1248
1249 case EVENT_CHILD:
1250 /* See Stevens 5.10 */
1251 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1252 if (p == -1)
1253 {
1254 if (errno != EINTR)
1255 break;
1256 }
1257 else
1258 for (i = 0 ; i < MAX_PROCS; i++)
1259 if (daemon->tcp_pids[i] == p)
1260 daemon->tcp_pids[i] = 0;
1261 break;
1262
1263 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001264 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001265 break;
1266
1267 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001268 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001269 break;
1270
1271 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001272 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1273 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001274 break;
1275
Simon Kelley1a6bca82008-07-11 11:11:42 +01001276 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001277 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001278 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001279 case EVENT_LUA_ERR:
1280 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001281 break;
1282
Simon Kelley5aabfc72007-08-29 11:24:47 +01001283 case EVENT_REOPEN:
1284 /* Note: this may leave TCP-handling processes with the old file still open.
1285 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1286 we leave them logging to the old file. */
1287 if (daemon->log_file != NULL)
1288 log_reopen(daemon->log_file);
1289 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001290
1291 case EVENT_NEWADDR:
1292 newaddress(now);
1293 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001294
1295 case EVENT_NEWROUTE:
1296 resend_query();
1297 /* Force re-reading resolv file right now, for luck. */
1298 poll_resolv(0, 1, now);
1299 break;
1300
Simon Kelley5aabfc72007-08-29 11:24:47 +01001301 case EVENT_TERM:
1302 /* Knock all our children on the head. */
1303 for (i = 0; i < MAX_PROCS; i++)
1304 if (daemon->tcp_pids[i] != 0)
1305 kill(daemon->tcp_pids[i], SIGALRM);
1306
Simon Kelleyc72daea2012-01-05 21:33:27 +00001307#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001308 /* handle pending lease transitions */
1309 if (daemon->helperfd != -1)
1310 {
1311 /* block in writes until all done */
1312 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1313 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1314 do {
1315 helper_write();
1316 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001317 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001318 }
1319#endif
1320
1321 if (daemon->lease_stream)
1322 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001323
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001324#ifdef HAVE_DNSSEC
1325 /* update timestamp file on TERM if time is considered valid */
1326 if (daemon->back_to_the_future)
1327 {
1328 if (utime(daemon->timestamp_file, NULL) == -1)
1329 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1330 }
1331#endif
1332
Simon Kelley73a08a22009-02-05 20:28:08 +00001333 if (daemon->runfile)
1334 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001335
1336 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1337 flush_log();
1338 exit(EC_GOOD);
1339 }
1340}
1341
Simon Kelley47a95162014-07-08 22:22:02 +01001342static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001343{
1344 struct resolvc *res, *latest;
1345 struct stat statbuf;
1346 time_t last_change = 0;
1347 /* There may be more than one possible file.
1348 Go through and find the one which changed _last_.
1349 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001350
Simon Kelley28866e92011-02-14 20:19:14 +00001351 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001352 return;
1353
Simon Kelley5aabfc72007-08-29 11:24:47 +01001354 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1355 if (stat(res->name, &statbuf) == -1)
1356 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001357 if (force)
1358 {
1359 res->mtime = 0;
1360 continue;
1361 }
1362
Simon Kelley5aabfc72007-08-29 11:24:47 +01001363 if (!res->logged)
1364 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1365 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001366
1367 if (res->mtime != 0)
1368 {
1369 /* existing file evaporated, force selection of the latest
1370 file even if its mtime hasn't changed since we last looked */
1371 poll_resolv(1, do_reload, now);
1372 return;
1373 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001374 }
1375 else
1376 {
1377 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001378 if (force || (statbuf.st_mtime != res->mtime))
1379 {
1380 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001381 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1382 {
1383 last_change = statbuf.st_mtime;
1384 latest = res;
1385 }
1386 }
1387 }
1388
1389 if (latest)
1390 {
1391 static int warned = 0;
1392 if (reload_servers(latest->name))
1393 {
1394 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1395 warned = 0;
1396 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001397 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001398 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001399 }
1400 else
1401 {
1402 latest->mtime = 0;
1403 if (!warned)
1404 {
1405 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1406 warned = 1;
1407 }
1408 }
1409 }
1410}
1411
1412void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001413{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001414 (void)now;
1415
Simon Kelley824af852008-02-12 20:43:05 +00001416 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001417 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001418
Simon Kelley7622fc02009-06-04 20:32:05 +01001419#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001420 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001421 {
Simon Kelley28866e92011-02-14 20:19:14 +00001422 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001423 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001424 reread_dhcp();
Simon Kelley04918052015-01-26 11:23:43 +00001425#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +00001426 set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001427#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001428 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001429 lease_update_from_configs();
1430 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001431 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001432 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001433#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001434 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001435 /* Not doing DHCP, so no lease system, manage
1436 alarms for ra only */
1437 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001438#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001439#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001440}
1441
Simon Kelleyb842bc92015-07-12 21:09:11 +01001442static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001443{
1444 struct serverfd *serverfdp;
1445 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001446 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001447
1448#ifdef HAVE_TFTP
1449 int tftp = 0;
1450 struct tftp_transfer *transfer;
1451 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1452 {
1453 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001454 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001455 }
1456#endif
1457
Simon Kelley16972692006-10-16 20:04:18 +01001458 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001459 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001460 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001461
Simon Kelley3be34542004-09-11 19:12:13 +01001462 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001463 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001464
Simon Kelley1a6bca82008-07-11 11:11:42 +01001465 if (daemon->port != 0 && !daemon->osport)
1466 for (i = 0; i < RANDOM_SOCKS; i++)
1467 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001468 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001469
Simon Kelley3be34542004-09-11 19:12:13 +01001470 for (listener = daemon->listeners; listener; listener = listener->next)
1471 {
Simon Kelley16972692006-10-16 20:04:18 +01001472 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001473 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001474 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001475
Simon Kelley16972692006-10-16 20:04:18 +01001476 /* death of a child goes through the select loop, so
1477 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001478 if (listener->tcpfd != -1)
1479 for (i = 0; i < MAX_PROCS; i++)
1480 if (daemon->tcp_pids[i] == 0)
1481 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001482 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001483 break;
1484 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001485
Simon Kelley832af0b2007-01-21 20:01:28 +00001486#ifdef HAVE_TFTP
1487 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001488 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001489#endif
1490
1491 }
1492
Simon Kelley16972692006-10-16 20:04:18 +01001493 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001494}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001495
Simon Kelleyb842bc92015-07-12 21:09:11 +01001496static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001497{
1498 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001499 struct listener *listener;
1500 int i;
1501
Simon Kelley832af0b2007-01-21 20:01:28 +00001502 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001503 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001504 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1505
1506 if (daemon->port != 0 && !daemon->osport)
1507 for (i = 0; i < RANDOM_SOCKS; i++)
1508 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001509 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001510 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001511
1512 for (listener = daemon->listeners; listener; listener = listener->next)
1513 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001514 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001515 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001516
Simon Kelley832af0b2007-01-21 20:01:28 +00001517#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001518 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001519 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001520#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001521
Simon Kelleyb842bc92015-07-12 21:09:11 +01001522 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001523 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001524 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001525 struct irec *iface = NULL;
1526 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001527 union mysockaddr tcp_addr;
1528 socklen_t tcp_len = sizeof(union mysockaddr);
1529
1530 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001531
Simon Kelley46b06652013-02-04 21:47:59 +00001532 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001533 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001534
Simon Kelley46b06652013-02-04 21:47:59 +00001535 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1536 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001537 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001538 continue;
1539 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001540
1541 /* Make sure that the interface list is up-to-date.
1542
1543 We do this here as we may need the results below, and
1544 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001545
Simon Kelley76dd75d2013-05-23 10:04:25 +01001546 Multiple calls to enumerate_interfaces() per select loop are
1547 inhibited, so calls to it in the child process (which doesn't select())
1548 have no effect. This avoids two processes reading from the same
1549 netlink fd and screwing the pooch entirely.
1550 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001551
Simon Kelley76dd75d2013-05-23 10:04:25 +01001552 enumerate_interfaces(0);
1553
1554 if (option_bool(OPT_NOWILD))
1555 iface = listener->iface; /* May be NULL */
1556 else
1557 {
1558 int if_index;
1559 char intr_name[IF_NAMESIZE];
1560
1561 /* if we can find the arrival interface, check it's one that's allowed */
1562 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1563 indextoname(listener->tcpfd, if_index, intr_name))
1564 {
1565 struct all_addr addr;
1566 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001567#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001568 if (tcp_addr.sa.sa_family == AF_INET6)
1569 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001570#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001571
1572 for (iface = daemon->interfaces; iface; iface = iface->next)
1573 if (iface->index == if_index)
1574 break;
1575
1576 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1577 client_ok = 0;
1578 }
1579
1580 if (option_bool(OPT_CLEVERBIND))
1581 iface = listener->iface; /* May be NULL */
1582 else
1583 {
1584 /* Check for allowed interfaces when binding the wildcard address:
1585 we do this by looking for an interface with the same address as
1586 the local address of the TCP connection, then looking to see if that's
1587 an allowed interface. As a side effect, we get the netmask of the
1588 interface too, for localisation. */
1589
1590 for (iface = daemon->interfaces; iface; iface = iface->next)
1591 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1592 break;
1593
1594 if (!iface)
1595 client_ok = 0;
1596 }
1597 }
1598
Simon Kelley22ce5502013-01-22 13:53:04 +00001599 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001600 {
1601 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001602 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001603 }
1604#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001605 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001606 {
1607 if (p != -1)
1608 {
1609 int i;
1610 for (i = 0; i < MAX_PROCS; i++)
1611 if (daemon->tcp_pids[i] == 0)
1612 {
1613 daemon->tcp_pids[i] = p;
1614 break;
1615 }
1616 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001617 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001618
1619 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1620 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001621 }
1622#endif
1623 else
1624 {
1625 unsigned char *buff;
1626 struct server *s;
1627 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001628 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001629 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001630
1631 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001632 {
1633 netmask = iface->netmask;
1634 auth_dns = iface->dns_auth;
1635 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001636 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001637 {
1638 netmask.s_addr = 0;
1639 auth_dns = 0;
1640 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001641
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001642#ifndef NO_FORK
1643 /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
1644 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001645 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001646 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001647#endif
1648
Simon Kelley832af0b2007-01-21 20:01:28 +00001649 /* start with no upstream connections. */
1650 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001651 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001652
1653 /* The connected socket inherits non-blocking
1654 attribute from the listening socket.
1655 Reset that here. */
1656 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1657 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1658
Simon Kelley4f7b3042012-11-28 21:27:02 +00001659 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001660
Simon Kelley832af0b2007-01-21 20:01:28 +00001661 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001662 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001663
1664 if (buff)
1665 free(buff);
1666
1667 for (s = daemon->servers; s; s = s->next)
1668 if (s->tcpfd != -1)
1669 {
1670 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001671 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001672 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001673#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001674 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001675 {
1676 flush_log();
1677 _exit(0);
1678 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001679#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001680 }
1681 }
1682 }
Simon Kelley3be34542004-09-11 19:12:13 +01001683}
1684
Simon Kelley7622fc02009-06-04 20:32:05 +01001685#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001686int make_icmp_sock(void)
1687{
Simon Kelley7cebd202006-05-06 14:13:33 +01001688 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001689 int zeroopt = 0;
1690
1691 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1692 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001693 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001694 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1695 {
1696 close(fd);
1697 fd = -1;
1698 }
1699 }
1700
1701 return fd;
1702}
1703
Simon Kelley5aabfc72007-08-29 11:24:47 +01001704int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001705{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001706 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001707
1708 /* Note that whilst in the three second wait, we check for
Simon Kelley832af0b2007-01-21 20:01:28 +00001709 (and service) events on the DNS and TFTP sockets, (so doing that
Simon Kelley3be34542004-09-11 19:12:13 +01001710 better not use any resources our caller has in use...)
1711 but we remain deaf to signals or further DHCP packets. */
1712
Simon Kelley5e95a552015-07-05 22:31:30 +01001713 /* There can be a problem using dnsmasq_time() to end the loop, since
1714 it's not monotonic, and can go backwards if the system clock is
1715 tweaked, leading to the code getting stuck in this loop and
1716 ignoring DHCP requests. To fix this, we check to see if select returned
1717 as a result of a timeout rather than a socket becoming available. We
1718 only allow this to happen as many times as it takes to get to the wait time
1719 in quarter-second chunks. This provides a fallback way to end loop. */
1720
1721 int fd, rc;
Simon Kelley3be34542004-09-11 19:12:13 +01001722 struct sockaddr_in saddr;
1723 struct {
1724 struct ip ip;
1725 struct icmp icmp;
1726 } packet;
1727 unsigned short id = rand16();
Simon Kelley5e95a552015-07-05 22:31:30 +01001728 unsigned int i, j, timeout_count;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001729 int gotreply = 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001730 time_t start, now;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001731
Simon Kelley824af852008-02-12 20:43:05 +00001732#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001733 if ((fd = make_icmp_sock()) == -1)
1734 return 0;
1735#else
1736 int opt = 2000;
1737 fd = daemon->dhcp_icmp_fd;
1738 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1739#endif
1740
Simon Kelley3be34542004-09-11 19:12:13 +01001741 saddr.sin_family = AF_INET;
1742 saddr.sin_port = 0;
1743 saddr.sin_addr = addr;
1744#ifdef HAVE_SOCKADDR_SA_LEN
1745 saddr.sin_len = sizeof(struct sockaddr_in);
1746#endif
1747
1748 memset(&packet.icmp, 0, sizeof(packet.icmp));
1749 packet.icmp.icmp_type = ICMP_ECHO;
1750 packet.icmp.icmp_id = id;
1751 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1752 j += ((u16 *)&packet.icmp)[i];
1753 while (j>>16)
1754 j = (j & 0xffff) + (j >> 16);
1755 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1756
Simon Kelleyff841eb2015-03-11 21:36:30 +00001757 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1758 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001759
Simon Kelley5e95a552015-07-05 22:31:30 +01001760 for (now = start = dnsmasq_time(), timeout_count = 0;
1761 (difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001762 {
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001763 struct sockaddr_in faddr;
Simon Kelley3d8df262005-08-29 12:19:27 +01001764 socklen_t len = sizeof(faddr);
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001765
Simon Kelleyb842bc92015-07-12 21:09:11 +01001766 poll_reset();
1767 poll_listen(fd, POLLIN);
1768 set_dns_listeners(now);
1769 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001770
1771#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001772 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001773 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001774#endif
1775
Simon Kelleyb842bc92015-07-12 21:09:11 +01001776 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001777
1778 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001779 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001780 else if (rc == 0)
1781 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001782
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001783 now = dnsmasq_time();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001784
Simon Kelleyb842bc92015-07-12 21:09:11 +01001785 check_log_writer(0);
1786 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001787
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001788#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001789 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001790 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001791#endif
1792
Simon Kelley832af0b2007-01-21 20:01:28 +00001793#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001794 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001795#endif
1796
Simon Kelleyb842bc92015-07-12 21:09:11 +01001797 if (poll_check(fd, POLLIN) &&
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001798 recvfrom(fd, &packet, sizeof(packet), 0,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001799 (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1800 saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
1801 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1802 packet.icmp.icmp_seq == 0 &&
1803 packet.icmp.icmp_id == id)
1804 {
1805 gotreply = 1;
1806 break;
1807 }
1808 }
1809
Simon Kelley824af852008-02-12 20:43:05 +00001810#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelleyff841eb2015-03-11 21:36:30 +00001811 while (retry_send(close(fd)));
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001812#else
Simon Kelley3be34542004-09-11 19:12:13 +01001813 opt = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001814 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1815#endif
1816
Simon Kelley3be34542004-09-11 19:12:13 +01001817 return gotreply;
1818}
Simon Kelley7622fc02009-06-04 20:32:05 +01001819#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001820
1821