blob: 04cc98278f62b0cbce89820389bdc3866457b0d8 [file] [log] [blame]
Simon Kelleyc47e3ba2014-01-08 17:07:54 +00001/* dnsmasq is Copyright (c) 2000-2014 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 Kelley5aabfc72007-08-29 11:24:47 +010027static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
28static void check_dns_listeners(fd_set *set, 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
Simon Kelley5aabfc72007-08-29 11:24:47 +010061
Simon Kelley824af852008-02-12 20:43:05 +000062#ifdef LOCALEDIR
Simon Kelleyb8187c82005-11-26 21:46:27 +000063 setlocale(LC_ALL, "");
64 bindtextdomain("dnsmasq", LOCALEDIR);
65 textdomain("dnsmasq");
66#endif
67
Simon Kelley9e4abcb2004-01-22 19:47:41 +000068 sigact.sa_handler = sig_handler;
69 sigact.sa_flags = 0;
70 sigemptyset(&sigact.sa_mask);
71 sigaction(SIGUSR1, &sigact, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +010072 sigaction(SIGUSR2, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000073 sigaction(SIGHUP, &sigact, NULL);
74 sigaction(SIGTERM, &sigact, NULL);
Simon Kelley44a2a312004-03-10 20:04:35 +000075 sigaction(SIGALRM, &sigact, NULL);
Simon Kelleyfeba5c12004-07-27 20:28:58 +010076 sigaction(SIGCHLD, &sigact, NULL);
77
78 /* ignore SIGPIPE */
79 sigact.sa_handler = SIG_IGN;
80 sigaction(SIGPIPE, &sigact, NULL);
Simon Kelley9e4abcb2004-01-22 19:47:41 +000081
Simon Kelley5aabfc72007-08-29 11:24:47 +010082 umask(022); /* known umask, create leases and pid files as 0644 */
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +010083
84 rand_init(); /* Must precede read_opts() */
85
Simon Kelley5aabfc72007-08-29 11:24:47 +010086 read_opts(argc, argv, compile_opts);
Simon Kelleyc3e0b9b2013-12-31 13:50:39 +000087
Simon Kelley3be34542004-09-11 19:12:13 +010088 if (daemon->edns_pktsz < PACKETSZ)
Simon Kelley60b68062014-01-08 12:10:28 +000089 daemon->edns_pktsz = PACKETSZ;
Simon Kelley3ddacb82014-01-08 14:32:03 +000090
Simon Kelley0a852542005-03-23 20:28:59 +000091 daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
92 daemon->edns_pktsz : DNSMASQ_PACKETSZ;
93 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +000094
Simon Kelleyc72daea2012-01-05 21:33:27 +000095 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +000096 if (option_bool(OPT_EXTRALOG))
97 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +000098
99#ifdef HAVE_DNSSEC
100 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000101 {
102 daemon->keyname = safe_malloc(MAXDNAME);
103 daemon->workspacename = safe_malloc(MAXDNAME);
104 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000105#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000106
Simon Kelley7622fc02009-06-04 20:32:05 +0100107#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100108 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000109 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000110 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100111 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000112 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100113#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000114
Simon Kelleya2761752012-01-18 16:07:21 +0000115 /* Close any file descriptors we inherited apart from std{in|out|err}
116
117 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
118 otherwise file descriptors we create can end up being 0, 1, or 2
119 and then get accidentally closed later when we make 0, 1, and 2
120 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
121 but it's not guaranteed. By opening /dev/null three times, we
122 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100123 for (i = 0; i < max_fd; i++)
124 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
125 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000126 else
127 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100128
Simon Kelley801ca9a2012-03-06 19:30:17 +0000129#ifndef HAVE_LINUX_NETWORK
130# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000131 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100132 {
133 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000134 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100135 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000136# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100137
138 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100139 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100140 {
141 bind_fallback = 1;
142 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100143 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100144 }
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000145
146 if (daemon->inotify_hosts)
147 die(_("dhcp-hostsdir not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100148#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100149
Simon Kelley0744ca62014-01-25 16:40:15 +0000150 if (option_bool(OPT_DNSSEC_VALID))
151 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000152#ifdef HAVE_DNSSEC
Simon Kelleyee415862014-02-11 11:07:22 +0000153 if (!daemon->ds)
Simon Kelley0744ca62014-01-25 16:40:15 +0000154 die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
155
156 if (daemon->cachesize < CACHESIZ)
157 die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
158#else
159 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000160#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000161 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000162
Simon Kelley832af0b2007-01-21 20:01:28 +0000163#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100164 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100165 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000166#endif
167
Simon Kelley7de060b2011-08-26 17:24:52 +0100168#ifdef HAVE_CONNTRACK
169 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
170 die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
171#else
172 if (option_bool(OPT_CONNTRACK))
173 die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
174#endif
175
Simon Kelley824af852008-02-12 20:43:05 +0000176#ifdef HAVE_SOLARIS_NETWORK
177 if (daemon->max_logs != 0)
178 die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
179#endif
180
Simon Kelley572b41e2011-02-18 18:11:18 +0000181#ifdef __ANDROID__
182 if (daemon->max_logs != 0)
183 die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
184#endif
185
Simon Kelley4820dce2012-12-18 18:30:30 +0000186#ifndef HAVE_AUTH
187 if (daemon->authserver)
188 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
189#endif
190
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100191#ifndef HAVE_LOOP
192 if (option_bool(OPT_LOOP_DETECT))
193 die(_("Loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
194#endif
Simon Kelley1a6bca82008-07-11 11:11:42 +0100195
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100196 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000197
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000198 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000199 if (daemon->authinterface && daemon->soa_sn == 0)
200#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000201 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000202#else
203 daemon->soa_sn = now;
204#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000205
Simon Kelleyff7eea22013-09-04 18:01:38 +0100206#ifdef HAVE_DHCP6
207 if (daemon->dhcp6)
208 {
209 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000210
Simon Kelleyff7eea22013-09-04 18:01:38 +0100211 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000212 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100213 if (context->flags & CONTEXT_DHCP)
214 daemon->doing_dhcp6 = 1;
215 if (context->flags & CONTEXT_RA)
216 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000217#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100218 if (context->flags & CONTEXT_TEMPLATE)
219 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000220#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000221 }
Simon Kelley1f776932012-12-16 19:46:08 +0000222 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100223#endif
224
225#ifdef HAVE_DHCP
226 /* Note that order matters here, we must call lease_init before
227 creating any file descriptors which shouldn't be leaked
228 to the lease-script init process. We need to call common_init
229 before lease_init to allocate buffers it uses.*/
230 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || daemon->relay6)
231 {
232 dhcp_common_init();
233 if (daemon->dhcp || daemon->doing_dhcp6)
234 lease_init(now);
235 }
236
237 if (daemon->dhcp || daemon->relay4)
238 dhcp_init();
239
240# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100241 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100242 ra_init(now);
243
244 if (daemon->doing_dhcp6 || daemon->relay6)
245 dhcp6_init();
246# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000247
Simon Kelley7622fc02009-06-04 20:32:05 +0100248#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100249
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000250#ifdef HAVE_IPSET
251 if (daemon->ipsets)
252 ipset_init();
253#endif
254
Simon Kelley1ee9be42013-12-09 16:50:19 +0000255#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000256 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000257#elif defined(HAVE_BSD_NETWORK)
258 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000259#endif
260
Simon Kelley1ee9be42013-12-09 16:50:19 +0000261 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
262 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
263
Simon Kelley115ac3e2013-05-20 11:28:32 +0100264 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100265 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000266
Simon Kelley54dd3932012-06-20 11:23:38 +0100267 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100268 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100269 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100270
271 if (!option_bool(OPT_CLEVERBIND))
272 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
273 if (if_tmp->name && !if_tmp->used)
274 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100275
276#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
277 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100278 bound_device = whichdevice();
279
Simon Kelley9380ba72012-04-16 14:41:56 +0100280 if (daemon->dhcp)
281 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100282 if (!daemon->relay4 && bound_device)
283 {
284 bindtodevice(bound_device, daemon->dhcpfd);
285 did_bind = 1;
286 }
287 if (daemon->enable_pxe && bound_device)
288 {
289 bindtodevice(bound_device, daemon->pxefd);
290 did_bind = 1;
291 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100292 }
293#endif
294
295#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100296 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
297 {
298 bindtodevice(bound_device, daemon->dhcp6fd);
299 did_bind = 1;
300 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100301#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100302 }
Simon Kelley28866e92011-02-14 20:19:14 +0000303 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100304 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000305
306#ifdef HAVE_DHCP6
307 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100308 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000309 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000310
311 /* After netlink_init() and before create_helper() */
312 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000313#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100314
Simon Kelley824af852008-02-12 20:43:05 +0000315 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000316 {
317 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000318
Simon Kelley82e3f452014-01-31 21:05:48 +0000319#ifdef HAVE_DNSSEC
320 blockdata_init();
321#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000322 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000323
324#ifdef HAVE_LINUX_NETWORK
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000325 if ((!option_bool(OPT_NO_POLL) && daemon->port != 0) ||
326 daemon->dhcp || daemon->doing_dhcp6)
327 inotify_dnsmasq_init();
328 else
329 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000330#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000331
Simon Kelley28866e92011-02-14 20:19:14 +0000332 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100333#ifdef HAVE_DBUS
334 {
335 char *err;
336 daemon->dbus = NULL;
337 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100338 if ((err = dbus_init()))
339 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100340 }
341#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100342 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100343#endif
344
Simon Kelley824af852008-02-12 20:43:05 +0000345 if (daemon->port != 0)
346 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100347
Simon Kelleyc72daea2012-01-05 21:33:27 +0000348#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100349 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000350 if ((daemon->dhcp || daemon->dhcp6) &&
351 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000352 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100353 {
354 if ((ent_pw = getpwnam(daemon->scriptuser)))
355 {
356 script_uid = ent_pw->pw_uid;
357 script_gid = ent_pw->pw_gid;
358 }
359 else
360 baduser = daemon->scriptuser;
361 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100362#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000363
Simon Kelley1a6bca82008-07-11 11:11:42 +0100364 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
365 baduser = daemon->username;
366 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
367 baduser = daemon->groupname;
368
369 if (baduser)
370 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
371
372 /* implement group defaults, "dip" if available, or group associated with uid */
373 if (!daemon->group_set && !gp)
374 {
375 if (!(gp = getgrnam(CHGRP)) && ent_pw)
376 gp = getgrgid(ent_pw->pw_gid);
377
378 /* for error message */
379 if (gp)
380 daemon->groupname = gp->gr_name;
381 }
382
383#if defined(HAVE_LINUX_NETWORK)
384 /* determine capability API version here, while we can still
385 call safe_malloc */
386 if (ent_pw && ent_pw->pw_uid != 0)
387 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100388 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100389 hdr = safe_malloc(sizeof(*hdr));
390
Simon Kelley1a6bca82008-07-11 11:11:42 +0100391 /* find version supported by kernel */
392 memset(hdr, 0, sizeof(*hdr));
393 capget(hdr, NULL);
394
395 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
396 {
397 /* if unknown version, use largest supported version (3) */
398 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
399 hdr->version = LINUX_CAPABILITY_VERSION_3;
400 capsize = 2;
401 }
402
403 data = safe_malloc(sizeof(*data) * capsize);
404 memset(data, 0, sizeof(*data) * capsize);
405 }
406#endif
407
Simon Kelley5aabfc72007-08-29 11:24:47 +0100408 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100409 in a race-free manner and another to carry errors to daemon-invoking process */
410 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100411
412 piperead = pipefd[0];
413 pipewrite = pipefd[1];
414 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000415 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100416
417 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100418
Simon Kelley28866e92011-02-14 20:19:14 +0000419 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000420 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000421 /* The following code "daemonizes" the process.
422 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100423
Simon Kelley9e038942008-05-30 20:06:34 +0100424 if (chdir("/") != 0)
425 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
426
Simon Kelley16972692006-10-16 20:04:18 +0100427#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000428 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100429 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100430 pid_t pid;
431
Simon Kelley1a6bca82008-07-11 11:11:42 +0100432 /* pipe to carry errors back to original process.
433 When startup is complete we close this and the process terminates. */
434 safe_pipe(err_pipe, 0);
435
Simon Kelley7622fc02009-06-04 20:32:05 +0100436 if ((pid = fork()) == -1)
437 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000438 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100439
Simon Kelley5aabfc72007-08-29 11:24:47 +0100440 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100441 {
442 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000443 char *msg;
444
Simon Kelley1a6bca82008-07-11 11:11:42 +0100445 /* close our copy of write-end */
446 close(err_pipe[1]);
447
448 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000449 if (read_event(err_pipe[0], &ev, &msg))
450 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100451
452 _exit(EC_GOOD);
453 }
454
455 close(err_pipe[0]);
456
457 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100458
459 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100460
461 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000462 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100463
464 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100465 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100466 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000467#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100468
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000469 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100470 if (daemon->runfile)
471 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100472 int fd, err = 0;
473
474 sprintf(daemon->namebuff, "%d\n", (int) getpid());
475
476 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
477 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
478 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
479 extent that an attacker running as the unprivileged user could replace the pidfile with a
480 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
481
482 The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
483 ensuring that the open() fails should there be any existing file (because the unlink() failed,
484 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
485 attack can succeed.
486
487 Any compromise of the non-privileged user still theoretically allows the pid-file to be
488 replaced whilst dnsmasq is running. The worst that could allow is that the usual
489 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
490
491 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
492 failure to write the pid-file.
493 */
494
495 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100496
Simon Kelley79cfefd2012-09-02 13:29:51 +0100497 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 +0100498 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100499 /* only complain if started as root */
500 if (getuid() == 0)
501 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100502 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100503 else
504 {
505 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
506 err = 1;
507
508 while (!err && close(fd) == -1)
509 if (!retry_send())
510 err = 1;
511 }
512
513 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100514 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000515 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100516 _exit(0);
517 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000518 }
Simon Kelley16972692006-10-16 20:04:18 +0100519 }
520
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100521 log_err = log_start(ent_pw, err_pipe[1]);
522
Simon Kelley28866e92011-02-14 20:19:14 +0000523 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100524 {
525 /* open stdout etc to /dev/null */
526 int nullfd = open("/dev/null", O_RDWR);
527 dup2(nullfd, STDOUT_FILENO);
528 dup2(nullfd, STDERR_FILENO);
529 dup2(nullfd, STDIN_FILENO);
530 close(nullfd);
531 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100532
Simon Kelley1a6bca82008-07-11 11:11:42 +0100533 /* if we are to run scripts, we need to fork a helper before dropping root. */
534 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000535#ifdef HAVE_SCRIPT
Simon Kelley52b92f42012-01-22 16:05:15 +0000536 if ((daemon->dhcp || daemon->dhcp6) && (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100537 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
538#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100539
Simon Kelley28866e92011-02-14 20:19:14 +0000540 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100541 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100542 int bad_capabilities = 0;
543 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100544
Simon Kelley1a6bca82008-07-11 11:11:42 +0100545 /* remove all supplimentary groups */
546 if (gp &&
547 (setgroups(0, &dummy) == -1 ||
548 setgid(gp->gr_gid) == -1))
549 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000550 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100551 _exit(0);
552 }
553
Simon Kelley7cebd202006-05-06 14:13:33 +0100554 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100555 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100556#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100557 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100558 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100559 ports because of DAD, or we're doing it dynamically,
560 we need CAP_NET_BIND_SERVICE too. */
561 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100562 data->effective = data->permitted = data->inheritable =
563 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
564 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
565 else
566 data->effective = data->permitted = data->inheritable =
567 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100568
Simon Kelley16972692006-10-16 20:04:18 +0100569 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000570 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100571 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100572
Simon Kelley7622fc02009-06-04 20:32:05 +0100573#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000574 /* http://developers.sun.com/solaris/articles/program_privileges.html */
575 priv_set_t *priv_set;
576
577 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
578 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
579 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
580 bad_capabilities = errno;
581
582 if (priv_set && bad_capabilities == 0)
583 {
584 priv_inverse(priv_set);
585
586 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
587 bad_capabilities = errno;
588 }
589
590 if (priv_set)
591 priv_freeset(priv_set);
592
Simon Kelley824af852008-02-12 20:43:05 +0000593#endif
594
Simon Kelley1a6bca82008-07-11 11:11:42 +0100595 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100596 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000597 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100598 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100599 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100600
601 /* finally drop root */
602 if (setuid(ent_pw->pw_uid) == -1)
603 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000604 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100605 _exit(0);
606 }
607
608#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100609 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100610 data->effective = data->permitted =
611 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
612 else
613 data->effective = data->permitted =
614 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100615 data->inheritable = 0;
616
617 /* lose the setuid and setgid capbilities */
618 if (capset(hdr, data) == -1)
619 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000620 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100621 _exit(0);
622 }
623#endif
624
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000625 }
Simon Kelley849a8352006-06-09 21:02:31 +0100626 }
Simon Kelley16972692006-10-16 20:04:18 +0100627
Simon Kelley16972692006-10-16 20:04:18 +0100628#ifdef HAVE_LINUX_NETWORK
Simon Kelley28866e92011-02-14 20:19:14 +0000629 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000630 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100631#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100632
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100633#ifdef HAVE_TFTP
Simon Kelley8bc4cec2012-07-03 21:04:11 +0100634 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100635 {
636 DIR *dir;
637 struct tftp_prefix *p;
638
639 if (daemon->tftp_prefix)
640 {
641 if (!((dir = opendir(daemon->tftp_prefix))))
642 {
643 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
644 _exit(0);
645 }
646 closedir(dir);
647 }
648
649 for (p = daemon->if_prefix; p; p = p->next)
650 {
651 if (!((dir = opendir(p->prefix))))
652 {
653 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
654 _exit(0);
655 }
656 closedir(dir);
657 }
658 }
659#endif
660
Simon Kelley824af852008-02-12 20:43:05 +0000661 if (daemon->port == 0)
662 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
663 else if (daemon->cachesize != 0)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100664 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000665 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100666 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
Simon Kelley16972692006-10-16 20:04:18 +0100667
Simon Kelleyf2621c72007-04-29 19:47:21 +0100668 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley16972692006-10-16 20:04:18 +0100669
Simon Kelley3d8df262005-08-29 12:19:27 +0100670#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000671 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100672 {
673 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100674 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100675 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100676 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100677 }
678#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000679
680 if (option_bool(OPT_LOCAL_SERVICE))
681 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
Simon Kelleydb737462014-01-31 10:32:45 +0000682
Simon Kelley1d97ac42014-01-31 11:12:27 +0000683#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000684 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000685 {
686 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
687 if (option_bool(OPT_DNSSEC_TIME))
688 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
689 }
Simon Kelleydb737462014-01-31 10:32:45 +0000690#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100691
Simon Kelley1a6bca82008-07-11 11:11:42 +0100692 if (log_err != 0)
693 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
694 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000695
Simon Kelleyde379512004-06-22 20:23:33 +0100696 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100697 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100698
Simon Kelleyf7029f52013-11-21 15:09:09 +0000699 if (option_bool(OPT_NOWILD))
700 warn_bound_listeners();
701
702 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100703
Simon Kelley28866e92011-02-14 20:19:14 +0000704 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000705 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
706 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100707 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100708
Simon Kelley28866e92011-02-14 20:19:14 +0000709 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100710 {
711 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100712 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100713 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000714 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100715 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100716 }
717
Simon Kelleyf2621c72007-04-29 19:47:21 +0100718 if (daemon->max_logs != 0)
719 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000720
Simon Kelleyf2621c72007-04-29 19:47:21 +0100721
Simon Kelley7622fc02009-06-04 20:32:05 +0100722#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000723 for (context = daemon->dhcp; context; context = context->next)
724 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100725
Simon Kelleyff7eea22013-09-04 18:01:38 +0100726 for (relay = daemon->relay4; relay; relay = relay->next)
727 log_relay(AF_INET, relay);
728
Simon Kelley1f776932012-12-16 19:46:08 +0000729# ifdef HAVE_DHCP6
730 for (context = daemon->dhcp6; context; context = context->next)
731 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000732
Simon Kelleyff7eea22013-09-04 18:01:38 +0100733 for (relay = daemon->relay6; relay; relay = relay->next)
734 log_relay(AF_INET6, relay);
735
Simon Kelley1f776932012-12-16 19:46:08 +0000736 if (daemon->doing_dhcp6 || daemon->doing_ra)
737 dhcp_construct_contexts(now);
738
739 if (option_bool(OPT_RA))
740 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
741# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000742
Simon Kelley3b3f4412013-10-11 16:33:28 +0100743# ifdef HAVE_LINUX_NETWORK
744 if (did_bind)
745 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
746# endif
747
Simon Kelley8445f5d2012-12-17 21:54:08 +0000748 /* after dhcp_contruct_contexts */
749 if (daemon->dhcp || daemon->doing_dhcp6)
750 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000751#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000752
Simon Kelley832af0b2007-01-21 20:01:28 +0000753#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000754 if (option_bool(OPT_TFTP))
Simon Kelley832af0b2007-01-21 20:01:28 +0000755 {
Simon Kelley832af0b2007-01-21 20:01:28 +0000756#ifdef FD_SETSIZE
Simon Kelley5aabfc72007-08-29 11:24:47 +0100757 if (FD_SETSIZE < (unsigned)max_fd)
Simon Kelley832af0b2007-01-21 20:01:28 +0000758 max_fd = FD_SETSIZE;
759#endif
760
Simon Kelley7622fc02009-06-04 20:32:05 +0100761 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100762 daemon->tftp_prefix ? _("root is ") : _("enabled"),
763 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000764 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Simon Kelleyf2621c72007-04-29 19:47:21 +0100765
Simon Kelley832af0b2007-01-21 20:01:28 +0000766 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100767 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000768 a single file will be sent to may clients (the file only needs
769 one fd). */
770
771 max_fd -= 30; /* use other than TFTP */
772
773 if (max_fd < 0)
774 max_fd = 5;
775 else if (max_fd < 100)
776 max_fd = max_fd/2;
777 else
778 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000779
780 /* if we have to use a limited range of ports,
781 that will limit the number of transfers */
782 if (daemon->start_tftp_port != 0 &&
783 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
784 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000785
786 if (daemon->tftp_max > max_fd)
787 {
788 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100789 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100790 _("restricting maximum simultaneous TFTP transfers to %d"),
791 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000792 }
793 }
794#endif
795
Simon Kelley1a6bca82008-07-11 11:11:42 +0100796 /* finished start-up - release original process */
797 if (err_pipe[1] != -1)
798 close(err_pipe[1]);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000799
Simon Kelley824af852008-02-12 20:43:05 +0000800 if (daemon->port != 0)
801 check_servers();
802
Simon Kelley7cebd202006-05-06 14:13:33 +0100803 pid = getpid();
804
Simon Kelley193de4a2014-12-10 17:32:16 +0000805#ifdef HAVE_LINUX_NETWORK
806 /* Using inotify, have to select a resolv file at startup */
807 poll_resolv(1, 0, now);
808#endif
809
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100810 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000811 {
Simon Kelley16972692006-10-16 20:04:18 +0100812 int maxfd = -1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100813 struct timeval t, *tp = NULL;
Simon Kelley3d8df262005-08-29 12:19:27 +0100814 fd_set rset, wset, eset;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000815
816 FD_ZERO(&rset);
Simon Kelley3d8df262005-08-29 12:19:27 +0100817 FD_ZERO(&wset);
818 FD_ZERO(&eset);
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000819
Simon Kelley16972692006-10-16 20:04:18 +0100820 /* if we are out of resources, find how long we have to wait
821 for some to come free, we'll loop around then and restart
822 listening for queries */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100823 if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100824 {
825 t.tv_usec = 0;
826 tp = &t;
827 }
828
Simon Kelley832af0b2007-01-21 20:01:28 +0000829 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
830 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000831 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000832 {
Simon Kelley16972692006-10-16 20:04:18 +0100833 t.tv_sec = 0;
834 t.tv_usec = 250000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100835 tp = &t;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000836 }
Simon Kelley74c95c22011-10-19 09:33:39 +0100837 /* Wake every second whilst waiting for DAD to complete */
838 else if (is_dad_listeners())
839 {
840 t.tv_sec = 1;
841 t.tv_usec = 0;
842 tp = &t;
843 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100844
Simon Kelley832af0b2007-01-21 20:01:28 +0000845#ifdef HAVE_DBUS
Simon Kelley5aabfc72007-08-29 11:24:47 +0100846 set_dbus_listeners(&maxfd, &rset, &wset, &eset);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100847#endif
848
Simon Kelley7622fc02009-06-04 20:32:05 +0100849#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100850 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100851 {
852 FD_SET(daemon->dhcpfd, &rset);
Simon Kelley16972692006-10-16 20:04:18 +0100853 bump_maxfd(daemon->dhcpfd, &maxfd);
Simon Kelley316e2732010-01-22 20:16:09 +0000854 if (daemon->pxefd != -1)
855 {
856 FD_SET(daemon->pxefd, &rset);
857 bump_maxfd(daemon->pxefd, &maxfd);
858 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100859 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100860#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100861
Simon Kelley52b92f42012-01-22 16:05:15 +0000862#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100863 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelley52b92f42012-01-22 16:05:15 +0000864 {
865 FD_SET(daemon->dhcp6fd, &rset);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +0000866 bump_maxfd(daemon->dhcp6fd, &maxfd);
Simon Kelley5d71d832012-03-24 14:40:42 +0000867 }
868
Simon Kelley1f776932012-12-16 19:46:08 +0000869 if (daemon->doing_ra)
Simon Kelley5d71d832012-03-24 14:40:42 +0000870 {
871 FD_SET(daemon->icmp6fd, &rset);
872 bump_maxfd(daemon->icmp6fd, &maxfd);
Simon Kelley52b92f42012-01-22 16:05:15 +0000873 }
874#endif
875
Simon Kelley1ee9be42013-12-09 16:50:19 +0000876#if defined(HAVE_LINUX_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100877 FD_SET(daemon->netlinkfd, &rset);
Simon Kelley16972692006-10-16 20:04:18 +0100878 bump_maxfd(daemon->netlinkfd, &maxfd);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000879 if (daemon->inotifyfd != -1)
Simon Kelley193de4a2014-12-10 17:32:16 +0000880 {
881 FD_SET(daemon->inotifyfd, &rset);
882 bump_maxfd(daemon->inotifyfd, &maxfd);
883 }
Simon Kelley1ee9be42013-12-09 16:50:19 +0000884#elif defined(HAVE_BSD_NETWORK)
885 FD_SET(daemon->routefd, &rset);
886 bump_maxfd(daemon->routefd, &maxfd);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100887#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000888
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100889 FD_SET(piperead, &rset);
Simon Kelley16972692006-10-16 20:04:18 +0100890 bump_maxfd(piperead, &maxfd);
891
Simon Kelley7622fc02009-06-04 20:32:05 +0100892#ifdef HAVE_DHCP
Simon Kelley1f15b812009-10-13 17:49:32 +0100893# ifdef HAVE_SCRIPT
Simon Kelley5aabfc72007-08-29 11:24:47 +0100894 while (helper_buf_empty() && do_script_run(now));
Simon Kelley16972692006-10-16 20:04:18 +0100895
Simon Kelleya9530962012-03-20 22:07:35 +0000896# ifdef HAVE_TFTP
897 while (helper_buf_empty() && do_tftp_script_run());
898# endif
899
Simon Kelley16972692006-10-16 20:04:18 +0100900 if (!helper_buf_empty())
901 {
902 FD_SET(daemon->helperfd, &wset);
903 bump_maxfd(daemon->helperfd, &maxfd);
904 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100905# else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100906 /* need this for other side-effects */
907 while (do_script_run(now));
Simon Kelleya9530962012-03-20 22:07:35 +0000908
909# ifdef HAVE_TFTP
910 while (do_tftp_script_run());
911# endif
912
Simon Kelley7622fc02009-06-04 20:32:05 +0100913# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100914#endif
Simon Kelley7622fc02009-06-04 20:32:05 +0100915
Simon Kelleyf2621c72007-04-29 19:47:21 +0100916 /* must do this just before select(), when we know no
917 more calls to my_syslog() can occur */
918 set_log_writer(&wset, &maxfd);
919
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100920 if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
921 {
922 /* otherwise undefined after error */
923 FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
924 }
925
926 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000927
Simon Kelleyf2621c72007-04-29 19:47:21 +0100928 check_log_writer(&wset);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100929
930 /* prime. */
931 enumerate_interfaces(1);
932
Simon Kelley74c95c22011-10-19 09:33:39 +0100933 /* Check the interfaces to see if any have exited DAD state
934 and if so, bind the address. */
935 if (is_dad_listeners())
936 {
Simon Kelley115ac3e2013-05-20 11:28:32 +0100937 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +0100938 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
939 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +0100940 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +0100941 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100942
Simon Kelley1ee9be42013-12-09 16:50:19 +0000943#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyc52e1892010-06-07 22:01:39 +0100944 if (FD_ISSET(daemon->netlinkfd, &rset))
Simon Kelleya0358e52014-06-07 13:38:48 +0100945 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000946#elif defined(HAVE_BSD_NETWORK)
947 if (FD_ISSET(daemon->routefd, &rset))
Simon Kelleya0358e52014-06-07 13:38:48 +0100948 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +0100949#endif
950
Simon Kelley193de4a2014-12-10 17:32:16 +0000951#ifdef HAVE_LINUX_NETWORK
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000952 if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now))
953 {
954 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
955 poll_resolv(1, 1, now);
956 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000957#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000958 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +0100959 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +0000960 if (daemon->last_resolv == 0 ||
961 difftime(now, daemon->last_resolv) > 1.0 ||
962 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000963 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100964 /* poll_resolv doesn't need to reload first time through, since
965 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +0100966
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100967 poll_resolv(0, daemon->last_resolv != 0, now);
968 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000969 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000970#endif
971
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100972 if (FD_ISSET(piperead, &rset))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100973 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +0100974
Simon Kelley3d8df262005-08-29 12:19:27 +0100975#ifdef HAVE_DBUS
976 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +0000977 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +0100978 {
979 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100980 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +0100981 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +0100982 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100983 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100984 }
Simon Kelley5aabfc72007-08-29 11:24:47 +0100985 check_dbus_listeners(&rset, &wset, &eset);
Simon Kelley3d8df262005-08-29 12:19:27 +0100986#endif
Simon Kelley824af852008-02-12 20:43:05 +0000987
Simon Kelley5aabfc72007-08-29 11:24:47 +0100988 check_dns_listeners(&rset, now);
Simon Kelley832af0b2007-01-21 20:01:28 +0000989
990#ifdef HAVE_TFTP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100991 check_tftp_listeners(&rset, now);
Simon Kelley832af0b2007-01-21 20:01:28 +0000992#endif
993
Simon Kelley7622fc02009-06-04 20:32:05 +0100994#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100995 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +0000996 {
997 if (FD_ISSET(daemon->dhcpfd, &rset))
998 dhcp_packet(now, 0);
999 if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
1000 dhcp_packet(now, 1);
1001 }
Simon Kelley16972692006-10-16 20:04:18 +01001002
Simon Kelley52b92f42012-01-22 16:05:15 +00001003#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +01001004 if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001005 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001006
Simon Kelley1f776932012-12-16 19:46:08 +00001007 if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
1008 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001009#endif
1010
Simon Kelley1f15b812009-10-13 17:49:32 +01001011# ifdef HAVE_SCRIPT
Simon Kelley16972692006-10-16 20:04:18 +01001012 if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001013 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001014# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001015#endif
1016
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001017 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001018}
1019
Simon Kelley3be34542004-09-11 19:12:13 +01001020static void sig_handler(int sig)
1021{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001022 if (pid == 0)
1023 {
Simon Kelley16972692006-10-16 20:04:18 +01001024 /* ignore anything other than TERM during startup
1025 and in helper proc. (helper ignore TERM too) */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001026 if (sig == SIGTERM)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001027 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001028 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001029 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001030 {
Simon Kelley16972692006-10-16 20:04:18 +01001031 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001032 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001033 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001034 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001035 else
1036 {
1037 /* master process */
1038 int event, errsave = errno;
1039
1040 if (sig == SIGHUP)
1041 event = EVENT_RELOAD;
1042 else if (sig == SIGCHLD)
1043 event = EVENT_CHILD;
1044 else if (sig == SIGALRM)
1045 event = EVENT_ALARM;
1046 else if (sig == SIGTERM)
1047 event = EVENT_TERM;
1048 else if (sig == SIGUSR1)
1049 event = EVENT_DUMP;
1050 else if (sig == SIGUSR2)
1051 event = EVENT_REOPEN;
1052 else
1053 return;
1054
Simon Kelleyc72daea2012-01-05 21:33:27 +00001055 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001056 errno = errsave;
1057 }
Simon Kelley3be34542004-09-11 19:12:13 +01001058}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001059
Simon Kelley353ae4d2012-03-19 20:07:51 +00001060/* now == 0 -> queue immediate callback */
1061void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001062{
Simon Kelley884a6df2012-03-20 16:20:22 +00001063 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001064 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001065 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1066 if ((now == 0 || difftime(event, now) <= 0.0))
1067 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1068 else
1069 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001070 }
Simon Kelley741c2952012-02-25 13:09:18 +00001071}
1072
Simon Kelley47a95162014-07-08 22:22:02 +01001073void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001074{
Simon Kelley47a95162014-07-08 22:22:02 +01001075 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001076}
1077
Simon Kelleyc72daea2012-01-05 21:33:27 +00001078void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001079{
1080 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001081 struct iovec iov[2];
1082
Simon Kelley5aabfc72007-08-29 11:24:47 +01001083 ev.event = event;
1084 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001085 ev.msg_sz = msg ? strlen(msg) : 0;
1086
1087 iov[0].iov_base = &ev;
1088 iov[0].iov_len = sizeof(ev);
1089 iov[1].iov_base = msg;
1090 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001091
1092 /* error pipe, debug mode. */
1093 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001094 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001095 else
1096 /* pipe is non-blocking and struct event_desc is smaller than
1097 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001098 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001099}
Simon Kelley3d8df262005-08-29 12:19:27 +01001100
Simon Kelleyc72daea2012-01-05 21:33:27 +00001101/* NOTE: the memory used to return msg is leaked: use msgs in events only
1102 to describe fatal errors. */
1103static int read_event(int fd, struct event_desc *evp, char **msg)
1104{
1105 char *buf;
1106
1107 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1108 return 0;
1109
1110 *msg = NULL;
1111
1112 if (evp->msg_sz != 0 &&
1113 (buf = malloc(evp->msg_sz + 1)) &&
1114 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1115 {
1116 buf[evp->msg_sz] = 0;
1117 *msg = buf;
1118 }
1119
1120 return 1;
1121}
1122
1123static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001124{
1125 errno = ev->data;
1126
1127 switch (ev->event)
1128 {
1129 case EVENT_DIE:
1130 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001131
1132 case EVENT_FORK_ERR:
1133 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001134
1135 case EVENT_PIPE_ERR:
1136 die(_("failed to create helper: %s"), NULL, EC_MISC);
1137
1138 case EVENT_CAP_ERR:
1139 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1140
1141 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001142 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001143
1144 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001145 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001146
1147 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001148 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001149
1150 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001151 die(_("cannot open log %s: %s"), msg, EC_FILE);
1152
1153 case EVENT_LUA_ERR:
1154 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001155
1156 case EVENT_TFTP_ERR:
1157 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001158 }
1159}
1160
Simon Kelley5aabfc72007-08-29 11:24:47 +01001161static void async_event(int pipe, time_t now)
1162{
1163 pid_t p;
1164 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001165 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001166 char *msg;
1167
1168 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1169 to describe fatal errors. */
1170
1171 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001172 switch (ev.event)
1173 {
1174 case EVENT_RELOAD:
Simon Kelleye98bd522014-03-28 20:41:23 +00001175#ifdef HAVE_DNSSEC
1176 if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
1177 {
1178 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
1179 reset_option_bool(OPT_DNSSEC_TIME);
1180 }
1181#endif
1182 /* fall through */
1183
1184 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001185 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001186
Simon Kelley7b1eae42014-02-20 13:43:28 +00001187 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001188 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001189 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1190 {
1191 reload_servers(daemon->resolv_files->name);
1192 check = 1;
1193 }
1194
1195 if (daemon->servers_file)
1196 {
1197 read_servers_file();
1198 check = 1;
1199 }
1200
1201 if (check)
1202 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001203 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001204
Simon Kelley7622fc02009-06-04 20:32:05 +01001205#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001206 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001207#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001208 break;
1209
1210 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001211 if (daemon->port != 0)
1212 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001213 break;
1214
1215 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001216#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001217 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001218 {
1219 lease_prune(NULL, now);
1220 lease_update_file(now);
1221 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001222#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001223 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001224 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1225 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001226#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001227#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001228 break;
1229
1230 case EVENT_CHILD:
1231 /* See Stevens 5.10 */
1232 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1233 if (p == -1)
1234 {
1235 if (errno != EINTR)
1236 break;
1237 }
1238 else
1239 for (i = 0 ; i < MAX_PROCS; i++)
1240 if (daemon->tcp_pids[i] == p)
1241 daemon->tcp_pids[i] = 0;
1242 break;
1243
1244 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001245 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001246 break;
1247
1248 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001249 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001250 break;
1251
1252 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001253 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1254 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001255 break;
1256
Simon Kelley1a6bca82008-07-11 11:11:42 +01001257 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001258 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001259 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001260 case EVENT_LUA_ERR:
1261 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001262 break;
1263
Simon Kelley5aabfc72007-08-29 11:24:47 +01001264 case EVENT_REOPEN:
1265 /* Note: this may leave TCP-handling processes with the old file still open.
1266 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1267 we leave them logging to the old file. */
1268 if (daemon->log_file != NULL)
1269 log_reopen(daemon->log_file);
1270 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001271
1272 case EVENT_NEWADDR:
1273 newaddress(now);
1274 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001275
1276 case EVENT_NEWROUTE:
1277 resend_query();
1278 /* Force re-reading resolv file right now, for luck. */
1279 poll_resolv(0, 1, now);
1280 break;
1281
Simon Kelley5aabfc72007-08-29 11:24:47 +01001282 case EVENT_TERM:
1283 /* Knock all our children on the head. */
1284 for (i = 0; i < MAX_PROCS; i++)
1285 if (daemon->tcp_pids[i] != 0)
1286 kill(daemon->tcp_pids[i], SIGALRM);
1287
Simon Kelleyc72daea2012-01-05 21:33:27 +00001288#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001289 /* handle pending lease transitions */
1290 if (daemon->helperfd != -1)
1291 {
1292 /* block in writes until all done */
1293 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1294 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1295 do {
1296 helper_write();
1297 } while (!helper_buf_empty() || do_script_run(now));
1298 close(daemon->helperfd);
1299 }
1300#endif
1301
1302 if (daemon->lease_stream)
1303 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001304
1305 if (daemon->runfile)
1306 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001307
1308 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1309 flush_log();
1310 exit(EC_GOOD);
1311 }
1312}
1313
Simon Kelley47a95162014-07-08 22:22:02 +01001314static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001315{
1316 struct resolvc *res, *latest;
1317 struct stat statbuf;
1318 time_t last_change = 0;
1319 /* There may be more than one possible file.
1320 Go through and find the one which changed _last_.
1321 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001322
Simon Kelley28866e92011-02-14 20:19:14 +00001323 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001324 return;
1325
Simon Kelley5aabfc72007-08-29 11:24:47 +01001326 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1327 if (stat(res->name, &statbuf) == -1)
1328 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001329 if (force)
1330 {
1331 res->mtime = 0;
1332 continue;
1333 }
1334
Simon Kelley5aabfc72007-08-29 11:24:47 +01001335 if (!res->logged)
1336 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1337 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001338
1339 if (res->mtime != 0)
1340 {
1341 /* existing file evaporated, force selection of the latest
1342 file even if its mtime hasn't changed since we last looked */
1343 poll_resolv(1, do_reload, now);
1344 return;
1345 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001346 }
1347 else
1348 {
1349 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001350 if (force || (statbuf.st_mtime != res->mtime))
1351 {
1352 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001353 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1354 {
1355 last_change = statbuf.st_mtime;
1356 latest = res;
1357 }
1358 }
1359 }
1360
1361 if (latest)
1362 {
1363 static int warned = 0;
1364 if (reload_servers(latest->name))
1365 {
1366 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1367 warned = 0;
1368 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001369 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001370 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001371 }
1372 else
1373 {
1374 latest->mtime = 0;
1375 if (!warned)
1376 {
1377 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1378 warned = 1;
1379 }
1380 }
1381 }
1382}
1383
1384void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001385{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001386 (void)now;
1387
Simon Kelley824af852008-02-12 20:43:05 +00001388 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001389 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001390
Simon Kelley7622fc02009-06-04 20:32:05 +01001391#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001392 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001393 {
Simon Kelley28866e92011-02-14 20:19:14 +00001394 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001395 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001396 reread_dhcp();
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001397#ifdef HAVE_LINUX_NETWORK
1398 set_dhcp_inotify();
1399#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001400 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001401 lease_update_from_configs();
1402 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001403 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001404 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001405#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001406 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001407 /* Not doing DHCP, so no lease system, manage
1408 alarms for ra only */
1409 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001410#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001411#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001412}
1413
Simon Kelley5aabfc72007-08-29 11:24:47 +01001414static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
Simon Kelley3be34542004-09-11 19:12:13 +01001415{
1416 struct serverfd *serverfdp;
1417 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001418 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001419
1420#ifdef HAVE_TFTP
1421 int tftp = 0;
1422 struct tftp_transfer *transfer;
1423 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1424 {
1425 tftp++;
1426 FD_SET(transfer->sockfd, set);
1427 bump_maxfd(transfer->sockfd, maxfdp);
1428 }
1429#endif
1430
Simon Kelley16972692006-10-16 20:04:18 +01001431 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001432 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001433 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001434
Simon Kelley3be34542004-09-11 19:12:13 +01001435 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1436 {
1437 FD_SET(serverfdp->fd, set);
Simon Kelley16972692006-10-16 20:04:18 +01001438 bump_maxfd(serverfdp->fd, maxfdp);
Simon Kelley3be34542004-09-11 19:12:13 +01001439 }
Simon Kelley1a6bca82008-07-11 11:11:42 +01001440
1441 if (daemon->port != 0 && !daemon->osport)
1442 for (i = 0; i < RANDOM_SOCKS; i++)
1443 if (daemon->randomsocks[i].refcount != 0)
1444 {
1445 FD_SET(daemon->randomsocks[i].fd, set);
1446 bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
1447 }
1448
Simon Kelley3be34542004-09-11 19:12:13 +01001449 for (listener = daemon->listeners; listener; listener = listener->next)
1450 {
Simon Kelley16972692006-10-16 20:04:18 +01001451 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001452 if (listener->fd != -1 && wait == 0)
Simon Kelley16972692006-10-16 20:04:18 +01001453 {
1454 FD_SET(listener->fd, set);
1455 bump_maxfd(listener->fd, maxfdp);
1456 }
1457
1458 /* death of a child goes through the select loop, so
1459 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001460 if (listener->tcpfd != -1)
1461 for (i = 0; i < MAX_PROCS; i++)
1462 if (daemon->tcp_pids[i] == 0)
1463 {
1464 FD_SET(listener->tcpfd, set);
1465 bump_maxfd(listener->tcpfd, maxfdp);
1466 break;
1467 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001468
Simon Kelley832af0b2007-01-21 20:01:28 +00001469#ifdef HAVE_TFTP
1470 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
1471 {
1472 FD_SET(listener->tftpfd, set);
1473 bump_maxfd(listener->tftpfd, maxfdp);
1474 }
1475#endif
1476
1477 }
1478
Simon Kelley16972692006-10-16 20:04:18 +01001479 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001480}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001481
Simon Kelley5aabfc72007-08-29 11:24:47 +01001482static void check_dns_listeners(fd_set *set, time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001483{
1484 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001485 struct listener *listener;
1486 int i;
1487
Simon Kelley832af0b2007-01-21 20:01:28 +00001488 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
1489 if (FD_ISSET(serverfdp->fd, set))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001490 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1491
1492 if (daemon->port != 0 && !daemon->osport)
1493 for (i = 0; i < RANDOM_SOCKS; i++)
1494 if (daemon->randomsocks[i].refcount != 0 &&
1495 FD_ISSET(daemon->randomsocks[i].fd, set))
1496 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001497
1498 for (listener = daemon->listeners; listener; listener = listener->next)
1499 {
Simon Kelley824af852008-02-12 20:43:05 +00001500 if (listener->fd != -1 && FD_ISSET(listener->fd, set))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001501 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001502
Simon Kelley832af0b2007-01-21 20:01:28 +00001503#ifdef HAVE_TFTP
1504 if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001505 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001506#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001507
Simon Kelley824af852008-02-12 20:43:05 +00001508 if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
Simon Kelley832af0b2007-01-21 20:01:28 +00001509 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001510 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001511 struct irec *iface = NULL;
1512 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001513 union mysockaddr tcp_addr;
1514 socklen_t tcp_len = sizeof(union mysockaddr);
1515
1516 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001517
Simon Kelley46b06652013-02-04 21:47:59 +00001518 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001519 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001520
Simon Kelley46b06652013-02-04 21:47:59 +00001521 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1522 {
1523 close(confd);
1524 continue;
1525 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001526
1527 /* Make sure that the interface list is up-to-date.
1528
1529 We do this here as we may need the results below, and
1530 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001531
Simon Kelley76dd75d2013-05-23 10:04:25 +01001532 Multiple calls to enumerate_interfaces() per select loop are
1533 inhibited, so calls to it in the child process (which doesn't select())
1534 have no effect. This avoids two processes reading from the same
1535 netlink fd and screwing the pooch entirely.
1536 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001537
Simon Kelley76dd75d2013-05-23 10:04:25 +01001538 enumerate_interfaces(0);
1539
1540 if (option_bool(OPT_NOWILD))
1541 iface = listener->iface; /* May be NULL */
1542 else
1543 {
1544 int if_index;
1545 char intr_name[IF_NAMESIZE];
1546
1547 /* if we can find the arrival interface, check it's one that's allowed */
1548 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1549 indextoname(listener->tcpfd, if_index, intr_name))
1550 {
1551 struct all_addr addr;
1552 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001553#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001554 if (tcp_addr.sa.sa_family == AF_INET6)
1555 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001556#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001557
1558 for (iface = daemon->interfaces; iface; iface = iface->next)
1559 if (iface->index == if_index)
1560 break;
1561
1562 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1563 client_ok = 0;
1564 }
1565
1566 if (option_bool(OPT_CLEVERBIND))
1567 iface = listener->iface; /* May be NULL */
1568 else
1569 {
1570 /* Check for allowed interfaces when binding the wildcard address:
1571 we do this by looking for an interface with the same address as
1572 the local address of the TCP connection, then looking to see if that's
1573 an allowed interface. As a side effect, we get the netmask of the
1574 interface too, for localisation. */
1575
1576 for (iface = daemon->interfaces; iface; iface = iface->next)
1577 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1578 break;
1579
1580 if (!iface)
1581 client_ok = 0;
1582 }
1583 }
1584
Simon Kelley22ce5502013-01-22 13:53:04 +00001585 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001586 {
1587 shutdown(confd, SHUT_RDWR);
1588 close(confd);
1589 }
1590#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001591 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001592 {
1593 if (p != -1)
1594 {
1595 int i;
1596 for (i = 0; i < MAX_PROCS; i++)
1597 if (daemon->tcp_pids[i] == 0)
1598 {
1599 daemon->tcp_pids[i] = p;
1600 break;
1601 }
1602 }
1603 close(confd);
Simon Kelley25cf5e32015-01-09 15:53:03 +00001604
1605 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1606 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001607 }
1608#endif
1609 else
1610 {
1611 unsigned char *buff;
1612 struct server *s;
1613 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001614 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001615 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001616
1617 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001618 {
1619 netmask = iface->netmask;
1620 auth_dns = iface->dns_auth;
1621 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001622 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001623 {
1624 netmask.s_addr = 0;
1625 auth_dns = 0;
1626 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001627
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001628#ifndef NO_FORK
1629 /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
1630 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001631 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001632 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001633#endif
1634
Simon Kelley832af0b2007-01-21 20:01:28 +00001635 /* start with no upstream connections. */
1636 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001637 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001638
1639 /* The connected socket inherits non-blocking
1640 attribute from the listening socket.
1641 Reset that here. */
1642 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1643 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1644
Simon Kelley4f7b3042012-11-28 21:27:02 +00001645 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001646
Simon Kelley832af0b2007-01-21 20:01:28 +00001647 shutdown(confd, SHUT_RDWR);
1648 close(confd);
1649
1650 if (buff)
1651 free(buff);
1652
1653 for (s = daemon->servers; s; s = s->next)
1654 if (s->tcpfd != -1)
1655 {
1656 shutdown(s->tcpfd, SHUT_RDWR);
1657 close(s->tcpfd);
1658 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001659#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001660 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001661 {
1662 flush_log();
1663 _exit(0);
1664 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001665#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001666 }
1667 }
1668 }
Simon Kelley3be34542004-09-11 19:12:13 +01001669}
1670
Simon Kelley7622fc02009-06-04 20:32:05 +01001671#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001672int make_icmp_sock(void)
1673{
Simon Kelley7cebd202006-05-06 14:13:33 +01001674 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001675 int zeroopt = 0;
1676
1677 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1678 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001679 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001680 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1681 {
1682 close(fd);
1683 fd = -1;
1684 }
1685 }
1686
1687 return fd;
1688}
1689
Simon Kelley5aabfc72007-08-29 11:24:47 +01001690int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001691{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001692 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001693
1694 /* Note that whilst in the three second wait, we check for
Simon Kelley832af0b2007-01-21 20:01:28 +00001695 (and service) events on the DNS and TFTP sockets, (so doing that
Simon Kelley3be34542004-09-11 19:12:13 +01001696 better not use any resources our caller has in use...)
1697 but we remain deaf to signals or further DHCP packets. */
1698
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001699 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001700 struct sockaddr_in saddr;
1701 struct {
1702 struct ip ip;
1703 struct icmp icmp;
1704 } packet;
1705 unsigned short id = rand16();
1706 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001707 int gotreply = 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001708 time_t start, now;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001709
Simon Kelley824af852008-02-12 20:43:05 +00001710#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001711 if ((fd = make_icmp_sock()) == -1)
1712 return 0;
1713#else
1714 int opt = 2000;
1715 fd = daemon->dhcp_icmp_fd;
1716 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1717#endif
1718
Simon Kelley3be34542004-09-11 19:12:13 +01001719 saddr.sin_family = AF_INET;
1720 saddr.sin_port = 0;
1721 saddr.sin_addr = addr;
1722#ifdef HAVE_SOCKADDR_SA_LEN
1723 saddr.sin_len = sizeof(struct sockaddr_in);
1724#endif
1725
1726 memset(&packet.icmp, 0, sizeof(packet.icmp));
1727 packet.icmp.icmp_type = ICMP_ECHO;
1728 packet.icmp.icmp_id = id;
1729 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1730 j += ((u16 *)&packet.icmp)[i];
1731 while (j>>16)
1732 j = (j & 0xffff) + (j >> 16);
1733 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1734
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001735 while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001736 (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
1737 retry_send());
1738
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001739 for (now = start = dnsmasq_time();
1740 difftime(now, start) < (float)PING_WAIT;)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001741 {
1742 struct timeval tv;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001743 fd_set rset, wset;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001744 struct sockaddr_in faddr;
Simon Kelley16972692006-10-16 20:04:18 +01001745 int maxfd = fd;
Simon Kelley3d8df262005-08-29 12:19:27 +01001746 socklen_t len = sizeof(faddr);
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001747
1748 tv.tv_usec = 250000;
1749 tv.tv_sec = 0;
1750
1751 FD_ZERO(&rset);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001752 FD_ZERO(&wset);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001753 FD_SET(fd, &rset);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001754 set_dns_listeners(now, &rset, &maxfd);
Simon Kelleyf2621c72007-04-29 19:47:21 +01001755 set_log_writer(&wset, &maxfd);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001756
1757#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001758 if (daemon->doing_ra)
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001759 {
1760 FD_SET(daemon->icmp6fd, &rset);
1761 bump_maxfd(daemon->icmp6fd, &maxfd);
1762 }
1763#endif
1764
Simon Kelleyf2621c72007-04-29 19:47:21 +01001765 if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
1766 {
1767 FD_ZERO(&rset);
1768 FD_ZERO(&wset);
1769 }
1770
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001771 now = dnsmasq_time();
Simon Kelleyf2621c72007-04-29 19:47:21 +01001772
1773 check_log_writer(&wset);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001774 check_dns_listeners(&rset, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001775
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001776#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001777 if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
1778 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001779#endif
1780
Simon Kelley832af0b2007-01-21 20:01:28 +00001781#ifdef HAVE_TFTP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001782 check_tftp_listeners(&rset, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001783#endif
1784
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001785 if (FD_ISSET(fd, &rset) &&
1786 recvfrom(fd, &packet, sizeof(packet), 0,
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001787 (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1788 saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
1789 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1790 packet.icmp.icmp_seq == 0 &&
1791 packet.icmp.icmp_id == id)
1792 {
1793 gotreply = 1;
1794 break;
1795 }
1796 }
1797
Simon Kelley824af852008-02-12 20:43:05 +00001798#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001799 close(fd);
1800#else
Simon Kelley3be34542004-09-11 19:12:13 +01001801 opt = 1;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001802 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1803#endif
1804
Simon Kelley3be34542004-09-11 19:12:13 +01001805 return gotreply;
1806}
Simon Kelley7622fc02009-06-04 20:32:05 +01001807#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001808
1809