blob: 045489fa5cd2c34108fa89561e12c361b93eb35f [file] [log] [blame]
Simon Kelleyc49778d2016-01-06 18:52:33 +00001/* dnsmasq is Copyright (c) 2000-2016 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 Kelleyd3a8b392015-12-23 12:27:37 +000094 /* Min buffer size: we check after adding each record, so there must be
95 memory for the largest packet, and the largest record so the
96 min for DNS is PACKETSZ+MAXDNAME+RRFIXEDSZ which is < 1000.
97 This might be increased is EDNS packet size if greater than the minimum. */
98 daemon->packet_buff_sz = daemon->edns_pktsz + MAXDNAME + RRFIXEDSZ;
Simon Kelley0a852542005-03-23 20:28:59 +000099 daemon->packet = safe_malloc(daemon->packet_buff_sz);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000100
Simon Kelleyc72daea2012-01-05 21:33:27 +0000101 daemon->addrbuff = safe_malloc(ADDRSTRLEN);
Simon Kelley25cf5e32015-01-09 15:53:03 +0000102 if (option_bool(OPT_EXTRALOG))
103 daemon->addrbuff2 = safe_malloc(ADDRSTRLEN);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000104
105#ifdef HAVE_DNSSEC
106 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelley5107ace2014-02-23 10:48:32 +0000107 {
Simon Kelleycbe379a2015-04-21 22:57:06 +0100108 /* Note that both /000 and '.' are allowed within labels. These get
109 represented in presentation format using NAME_ESCAPE as an escape
110 character when in DNSSEC mode.
111 In theory, if all the characters in a name were /000 or
112 '.' or NAME_ESCAPE then all would have to be escaped, so the
113 presentation format would be twice as long as the spec.
114
115 daemon->namebuff was previously allocated by the option-reading
116 code before we knew if we're in DNSSEC mode, so reallocate here. */
117 free(daemon->namebuff);
118 daemon->namebuff = safe_malloc(MAXDNAME * 2);
119 daemon->keyname = safe_malloc(MAXDNAME * 2);
120 daemon->workspacename = safe_malloc(MAXDNAME * 2);
Simon Kelley5107ace2014-02-23 10:48:32 +0000121 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000122#endif
Simon Kelley4f7b3042012-11-28 21:27:02 +0000123
Simon Kelley7622fc02009-06-04 20:32:05 +0100124#ifdef HAVE_DHCP
Simon Kelley3be34542004-09-11 19:12:13 +0100125 if (!daemon->lease_file)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000126 {
Simon Kelley52b92f42012-01-22 16:05:15 +0000127 if (daemon->dhcp || daemon->dhcp6)
Simon Kelley3be34542004-09-11 19:12:13 +0100128 daemon->lease_file = LEASEFILE;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000129 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100130#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000131
Simon Kelleya2761752012-01-18 16:07:21 +0000132 /* Close any file descriptors we inherited apart from std{in|out|err}
133
134 Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
135 otherwise file descriptors we create can end up being 0, 1, or 2
136 and then get accidentally closed later when we make 0, 1, and 2
137 open to /dev/null. Normally we'll be started with 0, 1 and 2 open,
138 but it's not guaranteed. By opening /dev/null three times, we
139 ensure that we're not using those fds for real stuff. */
Simon Kelley5aabfc72007-08-29 11:24:47 +0100140 for (i = 0; i < max_fd; i++)
141 if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
142 close(i);
Simon Kelleya2761752012-01-18 16:07:21 +0000143 else
144 open("/dev/null", O_RDWR);
Simon Kelley5aabfc72007-08-29 11:24:47 +0100145
Simon Kelley801ca9a2012-03-06 19:30:17 +0000146#ifndef HAVE_LINUX_NETWORK
147# if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
Simon Kelley28866e92011-02-14 20:19:14 +0000148 if (!option_bool(OPT_NOWILD))
Simon Kelleyde379512004-06-22 20:23:33 +0100149 {
150 bind_fallback = 1;
Simon Kelley28866e92011-02-14 20:19:14 +0000151 set_option_bool(OPT_NOWILD);
Simon Kelleyde379512004-06-22 20:23:33 +0100152 }
Simon Kelley801ca9a2012-03-06 19:30:17 +0000153# endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100154
155 /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
Simon Kelley54dd3932012-06-20 11:23:38 +0100156 if (option_bool(OPT_CLEVERBIND))
Simon Kelley2b5bae92012-06-26 16:55:23 +0100157 {
158 bind_fallback = 1;
159 set_option_bool(OPT_NOWILD);
Simon Kelley236e0722012-06-26 21:33:01 +0100160 reset_option_bool(OPT_CLEVERBIND);
Simon Kelley2b5bae92012-06-26 16:55:23 +0100161 }
Simon Kelley04918052015-01-26 11:23:43 +0000162#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000163
Simon Kelley04918052015-01-26 11:23:43 +0000164#ifndef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000165 if (daemon->dynamic_dirs)
166 die(_("dhcp-hostsdir, dhcp-optsdir and hostsdir are not supported on this platform"), NULL, EC_BADCONF);
Simon Kelley309331f2006-04-22 15:05:01 +0100167#endif
Simon Kelley2b5bae92012-06-26 16:55:23 +0100168
Simon Kelley0744ca62014-01-25 16:40:15 +0000169 if (option_bool(OPT_DNSSEC_VALID))
170 {
Simon Kelley3ddacb82014-01-08 14:32:03 +0000171#ifdef HAVE_DNSSEC
Simon Kelleya63b8b82016-01-12 11:28:58 +0000172 struct ds_config *ds;
173
174 /* Must have at least a root trust anchor, or the DNSSEC code
175 can loop forever. */
176 for (ds = daemon->ds; ds; ds = ds->next)
177 if (ds->name[0] == 0)
178 break;
179
180 if (!ds)
181 die(_("no root trust anchor provided for DNSSEC"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000182
183 if (daemon->cachesize < CACHESIZ)
Simon Kelley360f2512015-03-07 18:28:06 +0000184 die(_("cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
Simon Kelley0744ca62014-01-25 16:40:15 +0000185#else
186 die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3ddacb82014-01-08 14:32:03 +0000187#endif
Simon Kelley0744ca62014-01-25 16:40:15 +0000188 }
Simon Kelley3ddacb82014-01-08 14:32:03 +0000189
Simon Kelley832af0b2007-01-21 20:01:28 +0000190#ifndef HAVE_TFTP
Simon Kelley9b40cbf2012-07-13 19:58:26 +0100191 if (option_bool(OPT_TFTP))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100192 die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
Simon Kelley832af0b2007-01-21 20:01:28 +0000193#endif
194
Simon Kelley7de060b2011-08-26 17:24:52 +0100195#ifdef HAVE_CONNTRACK
196 if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
Simon Kelley360f2512015-03-07 18:28:06 +0000197 die (_("cannot use --conntrack AND --query-port"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100198#else
199 if (option_bool(OPT_CONNTRACK))
Simon Kelley360f2512015-03-07 18:28:06 +0000200 die(_("conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
Simon Kelley7de060b2011-08-26 17:24:52 +0100201#endif
202
Simon Kelley824af852008-02-12 20:43:05 +0000203#ifdef HAVE_SOLARIS_NETWORK
204 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000205 die(_("asynchronous logging is not available under Solaris"), NULL, EC_BADCONF);
Simon Kelley824af852008-02-12 20:43:05 +0000206#endif
207
Simon Kelley572b41e2011-02-18 18:11:18 +0000208#ifdef __ANDROID__
209 if (daemon->max_logs != 0)
Josh Soref730c6742017-02-06 16:14:04 +0000210 die(_("asynchronous logging is not available under Android"), NULL, EC_BADCONF);
Simon Kelley572b41e2011-02-18 18:11:18 +0000211#endif
212
Simon Kelley4820dce2012-12-18 18:30:30 +0000213#ifndef HAVE_AUTH
214 if (daemon->authserver)
215 die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
216#endif
217
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100218#ifndef HAVE_LOOP
219 if (option_bool(OPT_LOOP_DETECT))
Simon Kelley360f2512015-03-07 18:28:06 +0000220 die(_("loop detection not available: set HAVE_LOOP in src/config.h"), NULL, EC_BADCONF);
Simon Kelleyb5ea1cc2014-07-29 16:34:14 +0100221#endif
Hans Dedecker926332a2016-01-23 10:48:12 +0000222
223 if (daemon->max_port != MAX_PORT && daemon->min_port == 0)
224 daemon->min_port = 1024u;
225
226 if (daemon->max_port < daemon->min_port)
227 die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
228
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100229 now = dnsmasq_time();
Simon Kelley4f7b3042012-11-28 21:27:02 +0000230
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000231 /* Create a serial at startup if not configured. */
Simon Kelley4f7b3042012-11-28 21:27:02 +0000232 if (daemon->authinterface && daemon->soa_sn == 0)
233#ifdef HAVE_BROKEN_RTC
Simon Kelleyb0ff8582013-02-06 09:57:47 +0000234 die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
Simon Kelley4f7b3042012-11-28 21:27:02 +0000235#else
236 daemon->soa_sn = now;
237#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000238
Simon Kelleyff7eea22013-09-04 18:01:38 +0100239#ifdef HAVE_DHCP6
240 if (daemon->dhcp6)
241 {
242 daemon->doing_ra = option_bool(OPT_RA);
Simon Kelley1f776932012-12-16 19:46:08 +0000243
Simon Kelleyff7eea22013-09-04 18:01:38 +0100244 for (context = daemon->dhcp6; context; context = context->next)
Simon Kelley1f776932012-12-16 19:46:08 +0000245 {
Simon Kelleyff7eea22013-09-04 18:01:38 +0100246 if (context->flags & CONTEXT_DHCP)
247 daemon->doing_dhcp6 = 1;
248 if (context->flags & CONTEXT_RA)
249 daemon->doing_ra = 1;
Simon Kelley1ee9be42013-12-09 16:50:19 +0000250#if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100251 if (context->flags & CONTEXT_TEMPLATE)
252 die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
Simon Kelleybb86e852012-12-17 22:00:53 +0000253#endif
Simon Kelley1f776932012-12-16 19:46:08 +0000254 }
Simon Kelley1f776932012-12-16 19:46:08 +0000255 }
Simon Kelleyff7eea22013-09-04 18:01:38 +0100256#endif
257
258#ifdef HAVE_DHCP
259 /* Note that order matters here, we must call lease_init before
260 creating any file descriptors which shouldn't be leaked
261 to the lease-script init process. We need to call common_init
Simon Kelley33702ab2015-12-28 23:17:15 +0000262 before lease_init to allocate buffers it uses.
Simon Kelley1e505122016-01-25 21:29:23 +0000263 The script subsystem relies on DHCP buffers, hence the last two
Simon Kelley33702ab2015-12-28 23:17:15 +0000264 conditions below. */
265 if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 ||
Simon Kelley1e505122016-01-25 21:29:23 +0000266 daemon->relay6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP))
Simon Kelleyff7eea22013-09-04 18:01:38 +0100267 {
268 dhcp_common_init();
269 if (daemon->dhcp || daemon->doing_dhcp6)
270 lease_init(now);
271 }
272
273 if (daemon->dhcp || daemon->relay4)
274 dhcp_init();
275
276# ifdef HAVE_DHCP6
Simon Kelley89500e32013-09-20 16:29:20 +0100277 if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyff7eea22013-09-04 18:01:38 +0100278 ra_init(now);
279
280 if (daemon->doing_dhcp6 || daemon->relay6)
281 dhcp6_init();
282# endif
Simon Kelley843c96b2012-02-27 17:42:38 +0000283
Simon Kelley7622fc02009-06-04 20:32:05 +0100284#endif
Simon Kelleyfeba5c12004-07-27 20:28:58 +0100285
Jason A. Donenfeld13d86c72013-02-22 18:20:53 +0000286#ifdef HAVE_IPSET
287 if (daemon->ipsets)
288 ipset_init();
289#endif
290
Simon Kelley1ee9be42013-12-09 16:50:19 +0000291#if defined(HAVE_LINUX_NETWORK)
Simon Kelley801ca9a2012-03-06 19:30:17 +0000292 netlink_init();
Simon Kelley1ee9be42013-12-09 16:50:19 +0000293#elif defined(HAVE_BSD_NETWORK)
294 route_init();
Simon Kelley801ca9a2012-03-06 19:30:17 +0000295#endif
296
Simon Kelley1ee9be42013-12-09 16:50:19 +0000297 if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
298 die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
299
Simon Kelley115ac3e2013-05-20 11:28:32 +0100300 if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100301 die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
Simon Kelley843c96b2012-02-27 17:42:38 +0000302
Simon Kelley54dd3932012-06-20 11:23:38 +0100303 if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
Simon Kelley5aabfc72007-08-29 11:24:47 +0100304 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100305 create_bound_listeners(1);
Simon Kelley54dd3932012-06-20 11:23:38 +0100306
307 if (!option_bool(OPT_CLEVERBIND))
308 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
309 if (if_tmp->name && !if_tmp->used)
310 die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
Simon Kelley9380ba72012-04-16 14:41:56 +0100311
312#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
313 /* after enumerate_interfaces() */
Simon Kelley3b3f4412013-10-11 16:33:28 +0100314 bound_device = whichdevice();
315
Simon Kelley9380ba72012-04-16 14:41:56 +0100316 if (daemon->dhcp)
317 {
Simon Kelley3b3f4412013-10-11 16:33:28 +0100318 if (!daemon->relay4 && bound_device)
319 {
320 bindtodevice(bound_device, daemon->dhcpfd);
321 did_bind = 1;
322 }
323 if (daemon->enable_pxe && bound_device)
324 {
325 bindtodevice(bound_device, daemon->pxefd);
326 did_bind = 1;
327 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100328 }
329#endif
330
331#if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
Simon Kelley3b3f4412013-10-11 16:33:28 +0100332 if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
333 {
334 bindtodevice(bound_device, daemon->dhcp6fd);
335 did_bind = 1;
336 }
Simon Kelley9380ba72012-04-16 14:41:56 +0100337#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100338 }
Simon Kelley28866e92011-02-14 20:19:14 +0000339 else
Simon Kelley74c95c22011-10-19 09:33:39 +0100340 create_wildcard_listeners();
Simon Kelley5d162f22012-12-20 14:55:46 +0000341
342#ifdef HAVE_DHCP6
343 /* after enumerate_interfaces() */
Simon Kelleyff7eea22013-09-04 18:01:38 +0100344 if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
Simon Kelley5d162f22012-12-20 14:55:46 +0000345 join_multicast(1);
Simon Kelley3511a922013-11-07 10:28:11 +0000346
347 /* After netlink_init() and before create_helper() */
348 lease_make_duid(now);
Simon Kelley5d162f22012-12-20 14:55:46 +0000349#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100350
Simon Kelley824af852008-02-12 20:43:05 +0000351 if (daemon->port != 0)
Simon Kelley82e3f452014-01-31 21:05:48 +0000352 {
353 cache_init();
Simon Kelley193de4a2014-12-10 17:32:16 +0000354
Simon Kelley82e3f452014-01-31 21:05:48 +0000355#ifdef HAVE_DNSSEC
356 blockdata_init();
357#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000358 }
Simon Kelley193de4a2014-12-10 17:32:16 +0000359
Simon Kelley04918052015-01-26 11:23:43 +0000360#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +0000361 if (daemon->port != 0 || daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000362 inotify_dnsmasq_init();
363 else
364 daemon->inotifyfd = -1;
Simon Kelley193de4a2014-12-10 17:32:16 +0000365#endif
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000366
Simon Kelley28866e92011-02-14 20:19:14 +0000367 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100368#ifdef HAVE_DBUS
369 {
370 char *err;
371 daemon->dbus = NULL;
372 daemon->watches = NULL;
Simon Kelley5aabfc72007-08-29 11:24:47 +0100373 if ((err = dbus_init()))
374 die(_("DBus error: %s"), err, EC_MISC);
Simon Kelley3d8df262005-08-29 12:19:27 +0100375 }
376#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100377 die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
Simon Kelley3d8df262005-08-29 12:19:27 +0100378#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100379
Simon Kelley824af852008-02-12 20:43:05 +0000380 if (daemon->port != 0)
381 pre_allocate_sfds();
Simon Kelley1a6bca82008-07-11 11:11:42 +0100382
Simon Kelleyc72daea2012-01-05 21:33:27 +0000383#if defined(HAVE_SCRIPT)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100384 /* Note getpwnam returns static storage */
Simon Kelley843c96b2012-02-27 17:42:38 +0000385 if ((daemon->dhcp || daemon->dhcp6) &&
386 daemon->scriptuser &&
Simon Kelleyc72daea2012-01-05 21:33:27 +0000387 (daemon->lease_change_command || daemon->luascript))
Simon Kelley1a6bca82008-07-11 11:11:42 +0100388 {
389 if ((ent_pw = getpwnam(daemon->scriptuser)))
390 {
391 script_uid = ent_pw->pw_uid;
392 script_gid = ent_pw->pw_gid;
393 }
394 else
395 baduser = daemon->scriptuser;
396 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100397#endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000398
Simon Kelley1a6bca82008-07-11 11:11:42 +0100399 if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
400 baduser = daemon->username;
401 else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
402 baduser = daemon->groupname;
403
404 if (baduser)
405 die(_("unknown user or group: %s"), baduser, EC_BADCONF);
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000406
Simon Kelley1a6bca82008-07-11 11:11:42 +0100407 /* implement group defaults, "dip" if available, or group associated with uid */
408 if (!daemon->group_set && !gp)
409 {
410 if (!(gp = getgrnam(CHGRP)) && ent_pw)
411 gp = getgrgid(ent_pw->pw_gid);
412
413 /* for error message */
414 if (gp)
415 daemon->groupname = gp->gr_name;
416 }
417
418#if defined(HAVE_LINUX_NETWORK)
419 /* determine capability API version here, while we can still
420 call safe_malloc */
421 if (ent_pw && ent_pw->pw_uid != 0)
422 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100423 int capsize = 1; /* for header version 1 */
Simon Kelley3927da42008-07-20 15:10:39 +0100424 hdr = safe_malloc(sizeof(*hdr));
425
Simon Kelley1a6bca82008-07-11 11:11:42 +0100426 /* find version supported by kernel */
427 memset(hdr, 0, sizeof(*hdr));
428 capget(hdr, NULL);
429
430 if (hdr->version != LINUX_CAPABILITY_VERSION_1)
431 {
432 /* if unknown version, use largest supported version (3) */
433 if (hdr->version != LINUX_CAPABILITY_VERSION_2)
434 hdr->version = LINUX_CAPABILITY_VERSION_3;
435 capsize = 2;
436 }
437
438 data = safe_malloc(sizeof(*data) * capsize);
439 memset(data, 0, sizeof(*data) * capsize);
440 }
441#endif
442
Simon Kelley5aabfc72007-08-29 11:24:47 +0100443 /* Use a pipe to carry signals and other events back to the event loop
Simon Kelley1a6bca82008-07-11 11:11:42 +0100444 in a race-free manner and another to carry errors to daemon-invoking process */
445 safe_pipe(pipefd, 1);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100446
447 piperead = pipefd[0];
448 pipewrite = pipefd[1];
449 /* prime the pipe to load stuff first time. */
Simon Kelleye98bd522014-03-28 20:41:23 +0000450 send_event(pipewrite, EVENT_INIT, 0, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100451
452 err_pipe[1] = -1;
Simon Kelley16972692006-10-16 20:04:18 +0100453
Simon Kelley28866e92011-02-14 20:19:14 +0000454 if (!option_bool(OPT_DEBUG))
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000455 {
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000456 /* The following code "daemonizes" the process.
457 See Stevens section 12.4 */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100458
Simon Kelley9e038942008-05-30 20:06:34 +0100459 if (chdir("/") != 0)
460 die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
461
Simon Kelley16972692006-10-16 20:04:18 +0100462#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +0000463 if (!option_bool(OPT_NO_FORK))
Simon Kelley3be34542004-09-11 19:12:13 +0100464 {
Simon Kelley5aabfc72007-08-29 11:24:47 +0100465 pid_t pid;
466
Simon Kelley1a6bca82008-07-11 11:11:42 +0100467 /* pipe to carry errors back to original process.
468 When startup is complete we close this and the process terminates. */
469 safe_pipe(err_pipe, 0);
470
Simon Kelley7622fc02009-06-04 20:32:05 +0100471 if ((pid = fork()) == -1)
472 /* fd == -1 since we've not forked, never returns. */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000473 send_event(-1, EVENT_FORK_ERR, errno, NULL);
Simon Kelley9e038942008-05-30 20:06:34 +0100474
Simon Kelley5aabfc72007-08-29 11:24:47 +0100475 if (pid != 0)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100476 {
477 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000478 char *msg;
479
Simon Kelley1a6bca82008-07-11 11:11:42 +0100480 /* close our copy of write-end */
Simon Kelleyff841eb2015-03-11 21:36:30 +0000481 while (retry_send(close(err_pipe[1])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100482
483 /* check for errors after the fork */
Simon Kelleyc72daea2012-01-05 21:33:27 +0000484 if (read_event(err_pipe[0], &ev, &msg))
485 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100486
487 _exit(EC_GOOD);
488 }
489
Simon Kelleyff841eb2015-03-11 21:36:30 +0000490 while (retry_send(close(err_pipe[0])));
Simon Kelley1a6bca82008-07-11 11:11:42 +0100491
492 /* NO calls to die() from here on. */
Simon Kelley3be34542004-09-11 19:12:13 +0100493
494 setsid();
Simon Kelley7622fc02009-06-04 20:32:05 +0100495
496 if ((pid = fork()) == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +0000497 send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
Simon Kelley7622fc02009-06-04 20:32:05 +0100498
499 if (pid != 0)
Simon Kelley7cebd202006-05-06 14:13:33 +0100500 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +0100501 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000502#endif
Simon Kelley9e038942008-05-30 20:06:34 +0100503
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000504 /* write pidfile _after_ forking ! */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100505 if (daemon->runfile)
506 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100507 int fd, err = 0;
508
509 sprintf(daemon->namebuff, "%d\n", (int) getpid());
510
511 /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
512 in a directory which is writable by the non-privileged user that dnsmasq runs as. This
513 allows the daemon to delete the file as part of its shutdown. This is a security hole to the
514 extent that an attacker running as the unprivileged user could replace the pidfile with a
515 symlink, and have the target of that symlink overwritten as root next time dnsmasq starts.
516
Josh Soref730c6742017-02-06 16:14:04 +0000517 The following code first deletes any existing file, and then opens it with the O_EXCL flag,
Simon Kelley79cfefd2012-09-02 13:29:51 +0100518 ensuring that the open() fails should there be any existing file (because the unlink() failed,
519 or an attacker exploited the race between unlink() and open()). This ensures that no symlink
520 attack can succeed.
521
522 Any compromise of the non-privileged user still theoretically allows the pid-file to be
523 replaced whilst dnsmasq is running. The worst that could allow is that the usual
524 "shutdown dnsmasq" shell command could be tricked into stopping any other process.
525
526 Note that if dnsmasq is started as non-root (eg for testing) it silently ignores
527 failure to write the pid-file.
528 */
529
530 unlink(daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100531
Simon Kelley79cfefd2012-09-02 13:29:51 +0100532 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 +0100533 {
Simon Kelley79cfefd2012-09-02 13:29:51 +0100534 /* only complain if started as root */
535 if (getuid() == 0)
536 err = 1;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100537 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100538 else
539 {
540 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
541 err = 1;
Simon Kelleyff841eb2015-03-11 21:36:30 +0000542 else
543 {
544 while (retry_send(close(fd)));
545 if (errno != 0)
546 err = 1;
547 }
Simon Kelley79cfefd2012-09-02 13:29:51 +0100548 }
549
550 if (err)
Simon Kelley1a6bca82008-07-11 11:11:42 +0100551 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000552 send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100553 _exit(0);
554 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000555 }
Simon Kelley16972692006-10-16 20:04:18 +0100556 }
557
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100558 log_err = log_start(ent_pw, err_pipe[1]);
559
Simon Kelley28866e92011-02-14 20:19:14 +0000560 if (!option_bool(OPT_DEBUG))
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100561 {
562 /* open stdout etc to /dev/null */
563 int nullfd = open("/dev/null", O_RDWR);
Simon Kelleyf7cf7492016-03-01 16:19:23 +0000564 if (nullfd != -1)
565 {
566 dup2(nullfd, STDOUT_FILENO);
567 dup2(nullfd, STDERR_FILENO);
568 dup2(nullfd, STDIN_FILENO);
569 close(nullfd);
570 }
Simon Kelley8ef5ada2010-06-03 19:42:45 +0100571 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100572
Simon Kelley1a6bca82008-07-11 11:11:42 +0100573 /* if we are to run scripts, we need to fork a helper before dropping root. */
574 daemon->helperfd = -1;
Simon Kelleyc72daea2012-01-05 21:33:27 +0000575#ifdef HAVE_SCRIPT
Simon Kelley1e505122016-01-25 21:29:23 +0000576 if ((daemon->dhcp || daemon->dhcp6 || option_bool(OPT_TFTP) || option_bool(OPT_SCRIPT_ARP)) &&
Simon Kelley33702ab2015-12-28 23:17:15 +0000577 (daemon->lease_change_command || daemon->luascript))
578 daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100579#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +0100580
Simon Kelley28866e92011-02-14 20:19:14 +0000581 if (!option_bool(OPT_DEBUG) && getuid() == 0)
Simon Kelley16972692006-10-16 20:04:18 +0100582 {
Simon Kelley1a6bca82008-07-11 11:11:42 +0100583 int bad_capabilities = 0;
584 gid_t dummy;
Simon Kelley16972692006-10-16 20:04:18 +0100585
Josh Soref730c6742017-02-06 16:14:04 +0000586 /* remove all supplementary groups */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100587 if (gp &&
588 (setgroups(0, &dummy) == -1 ||
589 setgid(gp->gr_gid) == -1))
590 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000591 send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100592 _exit(0);
593 }
594
Simon Kelley7cebd202006-05-06 14:13:33 +0100595 if (ent_pw && ent_pw->pw_uid != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100596 {
Simon Kelley74c95c22011-10-19 09:33:39 +0100597#if defined(HAVE_LINUX_NETWORK)
Simon Kelley16972692006-10-16 20:04:18 +0100598 /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
Simon Kelley74c95c22011-10-19 09:33:39 +0100599 CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind
Simon Kelley54dd3932012-06-20 11:23:38 +0100600 ports because of DAD, or we're doing it dynamically,
601 we need CAP_NET_BIND_SERVICE too. */
602 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100603 data->effective = data->permitted = data->inheritable =
604 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) |
605 (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
606 else
607 data->effective = data->permitted = data->inheritable =
608 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100609
Simon Kelley16972692006-10-16 20:04:18 +0100610 /* Tell kernel to not clear capabilities when dropping root */
Simon Kelley572b41e2011-02-18 18:11:18 +0000611 if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
Simon Kelley16972692006-10-16 20:04:18 +0100612 bad_capabilities = errno;
Simon Kelley1a6bca82008-07-11 11:11:42 +0100613
Simon Kelley7622fc02009-06-04 20:32:05 +0100614#elif defined(HAVE_SOLARIS_NETWORK)
Simon Kelley824af852008-02-12 20:43:05 +0000615 /* http://developers.sun.com/solaris/articles/program_privileges.html */
616 priv_set_t *priv_set;
617
618 if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
619 priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
620 priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
621 bad_capabilities = errno;
622
623 if (priv_set && bad_capabilities == 0)
624 {
625 priv_inverse(priv_set);
626
627 if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
628 bad_capabilities = errno;
629 }
630
631 if (priv_set)
632 priv_freeset(priv_set);
633
Simon Kelley824af852008-02-12 20:43:05 +0000634#endif
635
Simon Kelley1a6bca82008-07-11 11:11:42 +0100636 if (bad_capabilities != 0)
Simon Kelley16972692006-10-16 20:04:18 +0100637 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000638 send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100639 _exit(0);
Simon Kelley16972692006-10-16 20:04:18 +0100640 }
Simon Kelley1a6bca82008-07-11 11:11:42 +0100641
642 /* finally drop root */
643 if (setuid(ent_pw->pw_uid) == -1)
644 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000645 send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100646 _exit(0);
647 }
648
649#ifdef HAVE_LINUX_NETWORK
Simon Kelley54dd3932012-06-20 11:23:38 +0100650 if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
Simon Kelley74c95c22011-10-19 09:33:39 +0100651 data->effective = data->permitted =
652 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
653 else
654 data->effective = data->permitted =
655 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100656 data->inheritable = 0;
657
Josh Soref730c6742017-02-06 16:14:04 +0000658 /* lose the setuid and setgid capabilities */
Simon Kelley1a6bca82008-07-11 11:11:42 +0100659 if (capset(hdr, data) == -1)
660 {
Simon Kelleyc72daea2012-01-05 21:33:27 +0000661 send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
Simon Kelley1a6bca82008-07-11 11:11:42 +0100662 _exit(0);
663 }
664#endif
665
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000666 }
Simon Kelley849a8352006-06-09 21:02:31 +0100667 }
Simon Kelley16972692006-10-16 20:04:18 +0100668
Simon Kelley16972692006-10-16 20:04:18 +0100669#ifdef HAVE_LINUX_NETWORK
Chen Wei28b879a2015-02-17 22:07:35 +0000670 free(hdr);
671 free(data);
Simon Kelley28866e92011-02-14 20:19:14 +0000672 if (option_bool(OPT_DEBUG))
Simon Kelley572b41e2011-02-18 18:11:18 +0000673 prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
Simon Kelley16972692006-10-16 20:04:18 +0100674#endif
Simon Kelley849a8352006-06-09 21:02:31 +0100675
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100676#ifdef HAVE_TFTP
Stefan Tomanek30d08792015-03-31 22:32:11 +0100677 if (option_bool(OPT_TFTP))
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100678 {
679 DIR *dir;
680 struct tftp_prefix *p;
681
682 if (daemon->tftp_prefix)
683 {
684 if (!((dir = opendir(daemon->tftp_prefix))))
685 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100686 tftp_prefix_missing = 1;
687 if (!option_bool(OPT_TFTP_NO_FAIL))
688 {
689 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
690 _exit(0);
691 }
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100692 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100693 else
694 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100695 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100696
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100697 for (p = daemon->if_prefix; p; p = p->next)
698 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100699 p->missing = 0;
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100700 if (!((dir = opendir(p->prefix))))
Stefan Tomanek30d08792015-03-31 22:32:11 +0100701 {
702 p->missing = 1;
703 if (!option_bool(OPT_TFTP_NO_FAIL))
704 {
705 send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
706 _exit(0);
707 }
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100708 }
Stefan Tomanekb4c0f092015-04-16 15:20:59 +0100709 else
710 closedir(dir);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +0100711 }
712 }
713#endif
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100714
Simon Kelley824af852008-02-12 20:43:05 +0000715 if (daemon->port == 0)
716 my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
Simon Kelley0ef13342017-01-15 16:42:39 +0000717 else
718 {
719 if (daemon->cachesize != 0)
720 my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
721 else
722 my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
723
724 if (option_bool(OPT_LOCAL_SERVICE))
725 my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
726 }
Simon Kelley16972692006-10-16 20:04:18 +0100727
Simon Kelleyf2621c72007-04-29 19:47:21 +0100728 my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
Simon Kelley16972692006-10-16 20:04:18 +0100729
Simon Kelley3d8df262005-08-29 12:19:27 +0100730#ifdef HAVE_DBUS
Simon Kelley28866e92011-02-14 20:19:14 +0000731 if (option_bool(OPT_DBUS))
Simon Kelley3d8df262005-08-29 12:19:27 +0100732 {
733 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100734 my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100735 else
Simon Kelleyf2621c72007-04-29 19:47:21 +0100736 my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
Simon Kelley3d8df262005-08-29 12:19:27 +0100737 }
738#endif
Simon Kelley1a9a3482014-03-05 15:01:08 +0000739
Simon Kelley1d97ac42014-01-31 11:12:27 +0000740#ifdef HAVE_DNSSEC
Simon Kelleydb737462014-01-31 10:32:45 +0000741 if (option_bool(OPT_DNSSEC_VALID))
Simon Kelleye98bd522014-03-28 20:41:23 +0000742 {
Simon Kelley360f2512015-03-07 18:28:06 +0000743 int rc;
744
745 /* Delay creating the timestamp file until here, after we've changed user, so that
746 it has the correct owner to allow updating the mtime later.
747 This means we have to report fatal errors via the pipe. */
748 if ((rc = setup_timestamp()) == -1)
749 {
750 send_event(err_pipe[1], EVENT_TIME_ERR, errno, daemon->timestamp_file);
751 _exit(0);
752 }
753
Simon Kelleye98bd522014-03-28 20:41:23 +0000754 my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
Simon Kelley360f2512015-03-07 18:28:06 +0000755
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +0100756 daemon->dnssec_no_time_check = option_bool(OPT_DNSSEC_TIME);
757 if (option_bool(OPT_DNSSEC_TIME) && !daemon->back_to_the_future)
Simon Kelleye98bd522014-03-28 20:41:23 +0000758 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
Simon Kelley360f2512015-03-07 18:28:06 +0000759
760 if (rc == 1)
Simon Kelleyf6e62e22015-03-01 18:17:54 +0000761 my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until system time valid"));
Simon Kelleye98bd522014-03-28 20:41:23 +0000762 }
Simon Kelleydb737462014-01-31 10:32:45 +0000763#endif
Simon Kelley3d8df262005-08-29 12:19:27 +0100764
Simon Kelley1a6bca82008-07-11 11:11:42 +0100765 if (log_err != 0)
766 my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"),
767 daemon->log_file, strerror(log_err));
Simon Kelleydb737462014-01-31 10:32:45 +0000768
Simon Kelleyde379512004-06-22 20:23:33 +0100769 if (bind_fallback)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100770 my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
Simon Kelleydc27e142013-10-16 13:09:53 +0100771
Simon Kelleyf7029f52013-11-21 15:09:09 +0000772 if (option_bool(OPT_NOWILD))
773 warn_bound_listeners();
Petr Menšíkad59f272017-03-17 17:22:19 +0000774 else if (!option_bool(OPT_CLEVERBIND))
775 warn_wild_labels();
Simon Kelleyf7029f52013-11-21 15:09:09 +0000776
777 warn_int_names();
Simon Kelleyde379512004-06-22 20:23:33 +0100778
Simon Kelley28866e92011-02-14 20:19:14 +0000779 if (!option_bool(OPT_NOWILD))
Simon Kelley26128d22004-11-14 16:43:54 +0000780 for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
781 if (if_tmp->name && !if_tmp->used)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100782 my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100783
Simon Kelley28866e92011-02-14 20:19:14 +0000784 if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
Simon Kelley208b65c2006-08-05 21:41:37 +0100785 {
786 if (daemon->resolv_files && !daemon->resolv_files->is_default)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100787 my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100788 daemon->resolv_files = NULL;
Simon Kelley1b7ecd12007-02-05 14:57:57 +0000789 if (!daemon->servers)
Simon Kelleyf2621c72007-04-29 19:47:21 +0100790 my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
Simon Kelley208b65c2006-08-05 21:41:37 +0100791 }
792
Simon Kelleyf2621c72007-04-29 19:47:21 +0100793 if (daemon->max_logs != 0)
794 my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
Simon Kelley1f776932012-12-16 19:46:08 +0000795
Simon Kelleyf2621c72007-04-29 19:47:21 +0100796
Simon Kelley7622fc02009-06-04 20:32:05 +0100797#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +0000798 for (context = daemon->dhcp; context; context = context->next)
799 log_context(AF_INET, context);
Simon Kelleyc8257542012-03-28 21:15:41 +0100800
Simon Kelleyff7eea22013-09-04 18:01:38 +0100801 for (relay = daemon->relay4; relay; relay = relay->next)
802 log_relay(AF_INET, relay);
803
Simon Kelley1f776932012-12-16 19:46:08 +0000804# ifdef HAVE_DHCP6
805 for (context = daemon->dhcp6; context; context = context->next)
806 log_context(AF_INET6, context);
Simon Kelley52b92f42012-01-22 16:05:15 +0000807
Simon Kelleyff7eea22013-09-04 18:01:38 +0100808 for (relay = daemon->relay6; relay; relay = relay->next)
809 log_relay(AF_INET6, relay);
810
Simon Kelley1f776932012-12-16 19:46:08 +0000811 if (daemon->doing_dhcp6 || daemon->doing_ra)
812 dhcp_construct_contexts(now);
813
814 if (option_bool(OPT_RA))
815 my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
816# endif
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000817
Simon Kelley3b3f4412013-10-11 16:33:28 +0100818# ifdef HAVE_LINUX_NETWORK
819 if (did_bind)
820 my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
821# endif
822
Josh Soref730c6742017-02-06 16:14:04 +0000823 /* after dhcp_construct_contexts */
Simon Kelley8445f5d2012-12-17 21:54:08 +0000824 if (daemon->dhcp || daemon->doing_dhcp6)
825 lease_find_interfaces(now);
Simon Kelley1f776932012-12-16 19:46:08 +0000826#endif
Simon Kelley52b92f42012-01-22 16:05:15 +0000827
Simon Kelley832af0b2007-01-21 20:01:28 +0000828#ifdef HAVE_TFTP
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000829 if (option_bool(OPT_TFTP))
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100830 {
Stefan Tomanek30d08792015-03-31 22:32:11 +0100831 struct tftp_prefix *p;
Simon Kelley832af0b2007-01-21 20:01:28 +0000832
Simon Kelley7622fc02009-06-04 20:32:05 +0100833 my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
Simon Kelleyf2621c72007-04-29 19:47:21 +0100834 daemon->tftp_prefix ? _("root is ") : _("enabled"),
835 daemon->tftp_prefix ? daemon->tftp_prefix: "",
Simon Kelley28866e92011-02-14 20:19:14 +0000836 option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100837
Stefan Tomanek30d08792015-03-31 22:32:11 +0100838 if (tftp_prefix_missing)
839 my_syslog(MS_TFTP | LOG_WARNING, _("warning: %s inaccessible"), daemon->tftp_prefix);
Stefan Tomanek7aa970e2015-04-01 17:55:07 +0100840
Stefan Tomanek30d08792015-03-31 22:32:11 +0100841 for (p = daemon->if_prefix; p; p = p->next)
842 if (p->missing)
843 my_syslog(MS_TFTP | LOG_WARNING, _("warning: TFTP directory %s inaccessible"), p->prefix);
844
Simon Kelley832af0b2007-01-21 20:01:28 +0000845 /* This is a guess, it assumes that for small limits,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100846 disjoint files might be served, but for large limits,
Simon Kelley832af0b2007-01-21 20:01:28 +0000847 a single file will be sent to may clients (the file only needs
848 one fd). */
849
850 max_fd -= 30; /* use other than TFTP */
851
852 if (max_fd < 0)
853 max_fd = 5;
854 else if (max_fd < 100)
855 max_fd = max_fd/2;
856 else
857 max_fd = max_fd - 20;
Simon Kelley824af852008-02-12 20:43:05 +0000858
859 /* if we have to use a limited range of ports,
860 that will limit the number of transfers */
861 if (daemon->start_tftp_port != 0 &&
862 daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
863 max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
Simon Kelley832af0b2007-01-21 20:01:28 +0000864
865 if (daemon->tftp_max > max_fd)
866 {
867 daemon->tftp_max = max_fd;
Simon Kelley7622fc02009-06-04 20:32:05 +0100868 my_syslog(MS_TFTP | LOG_WARNING,
Simon Kelleyf2621c72007-04-29 19:47:21 +0100869 _("restricting maximum simultaneous TFTP transfers to %d"),
870 daemon->tftp_max);
Simon Kelley832af0b2007-01-21 20:01:28 +0000871 }
872 }
873#endif
874
Simon Kelley1a6bca82008-07-11 11:11:42 +0100875 /* finished start-up - release original process */
876 if (err_pipe[1] != -1)
Simon Kelleyff841eb2015-03-11 21:36:30 +0000877 while (retry_send(close(err_pipe[1])));
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000878
Simon Kelley824af852008-02-12 20:43:05 +0000879 if (daemon->port != 0)
880 check_servers();
881
Simon Kelley7cebd202006-05-06 14:13:33 +0100882 pid = getpid();
883
Simon Kelley04918052015-01-26 11:23:43 +0000884#ifdef HAVE_INOTIFY
Simon Kelley193de4a2014-12-10 17:32:16 +0000885 /* Using inotify, have to select a resolv file at startup */
886 poll_resolv(1, 0, now);
887#endif
888
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100889 while (1)
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000890 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100891 int t, timeout = -1;
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000892
Simon Kelleyb842bc92015-07-12 21:09:11 +0100893 poll_reset();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000894
Simon Kelley16972692006-10-16 20:04:18 +0100895 /* if we are out of resources, find how long we have to wait
896 for some to come free, we'll loop around then and restart
897 listening for queries */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100898 if ((t = set_dns_listeners(now)) != 0)
899 timeout = t * 1000;
Simon Kelley16972692006-10-16 20:04:18 +0100900
Simon Kelley832af0b2007-01-21 20:01:28 +0000901 /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
902 if (daemon->tftp_trans ||
Simon Kelley28866e92011-02-14 20:19:14 +0000903 (option_bool(OPT_DBUS) && !daemon->dbus))
Simon Kelleyb842bc92015-07-12 21:09:11 +0100904 timeout = 250;
905
Simon Kelley74c95c22011-10-19 09:33:39 +0100906 /* Wake every second whilst waiting for DAD to complete */
907 else if (is_dad_listeners())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100908 timeout = 1000;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100909
Simon Kelley832af0b2007-01-21 20:01:28 +0000910#ifdef HAVE_DBUS
Simon Kelleyb842bc92015-07-12 21:09:11 +0100911 set_dbus_listeners();
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100912#endif
913
Simon Kelley7622fc02009-06-04 20:32:05 +0100914#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +0100915 if (daemon->dhcp || daemon->relay4)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100916 {
Simon Kelleyb842bc92015-07-12 21:09:11 +0100917 poll_listen(daemon->dhcpfd, POLLIN);
Simon Kelley316e2732010-01-22 20:16:09 +0000918 if (daemon->pxefd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100919 poll_listen(daemon->pxefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100920 }
Simon Kelley7622fc02009-06-04 20:32:05 +0100921#endif
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100922
Simon Kelley52b92f42012-01-22 16:05:15 +0000923#ifdef HAVE_DHCP6
Simon Kelleyff7eea22013-09-04 18:01:38 +0100924 if (daemon->doing_dhcp6 || daemon->relay6)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100925 poll_listen(daemon->dhcp6fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +0100926
Simon Kelley1f776932012-12-16 19:46:08 +0000927 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100928 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelley52b92f42012-01-22 16:05:15 +0000929#endif
Simon Kelley04918052015-01-26 11:23:43 +0000930
931#ifdef HAVE_INOTIFY
Simon Kelley5f4dc5c2015-01-20 20:51:02 +0000932 if (daemon->inotifyfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100933 poll_listen(daemon->inotifyfd, POLLIN);
Simon Kelley04918052015-01-26 11:23:43 +0000934#endif
935
936#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100937 poll_listen(daemon->netlinkfd, POLLIN);
Simon Kelley1ee9be42013-12-09 16:50:19 +0000938#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +0100939 poll_listen(daemon->routefd, POLLIN);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100940#endif
Simon Kelley193de4a2014-12-10 17:32:16 +0000941
Simon Kelleyb842bc92015-07-12 21:09:11 +0100942 poll_listen(piperead, POLLIN);
Simon Kelley16972692006-10-16 20:04:18 +0100943
Simon Kelley33702ab2015-12-28 23:17:15 +0000944#ifdef HAVE_SCRIPT
Simon Kelley53a91732016-01-06 17:59:13 +0000945# ifdef HAVE_DHCP
Simon Kelley33702ab2015-12-28 23:17:15 +0000946 while (helper_buf_empty() && do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000947# endif
948
Simon Kelley1e505122016-01-25 21:29:23 +0000949 /* Refresh cache */
950 if (option_bool(OPT_SCRIPT_ARP))
951 find_mac(NULL, NULL, 0, now);
Simon Kelley33702ab2015-12-28 23:17:15 +0000952 while (helper_buf_empty() && do_arp_script_run());
Simon Kelley16972692006-10-16 20:04:18 +0100953
Simon Kelleya9530962012-03-20 22:07:35 +0000954# ifdef HAVE_TFTP
955 while (helper_buf_empty() && do_tftp_script_run());
956# endif
957
Simon Kelley16972692006-10-16 20:04:18 +0100958 if (!helper_buf_empty())
Simon Kelleyb842bc92015-07-12 21:09:11 +0100959 poll_listen(daemon->helperfd, POLLOUT);
Simon Kelley33702ab2015-12-28 23:17:15 +0000960#else
Simon Kelley5aabfc72007-08-29 11:24:47 +0100961 /* need this for other side-effects */
Simon Kelley53a91732016-01-06 17:59:13 +0000962# ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +0100963 while (do_script_run(now));
Simon Kelley53a91732016-01-06 17:59:13 +0000964# endif
965
Simon Kelleyb633de92016-01-06 22:51:17 +0000966 while (do_arp_script_run());
Simon Kelleya9530962012-03-20 22:07:35 +0000967
968# ifdef HAVE_TFTP
969 while (do_tftp_script_run());
970# endif
971
Simon Kelley5aabfc72007-08-29 11:24:47 +0100972#endif
Simon Kelley33702ab2015-12-28 23:17:15 +0000973
Simon Kelley7622fc02009-06-04 20:32:05 +0100974
Simon Kelleyf2621c72007-04-29 19:47:21 +0100975 /* must do this just before select(), when we know no
976 more calls to my_syslog() can occur */
Simon Kelleyb842bc92015-07-12 21:09:11 +0100977 set_log_writer();
Simon Kelleyf2621c72007-04-29 19:47:21 +0100978
Simon Kelleyb842bc92015-07-12 21:09:11 +0100979 if (do_poll(timeout) < 0)
980 continue;
981
Simon Kelley5e9e0ef2006-04-17 14:24:29 +0100982 now = dnsmasq_time();
Simon Kelley9e4abcb2004-01-22 19:47:41 +0000983
Simon Kelleyb842bc92015-07-12 21:09:11 +0100984 check_log_writer(0);
Simon Kelley115ac3e2013-05-20 11:28:32 +0100985
986 /* prime. */
987 enumerate_interfaces(1);
988
Simon Kelley74c95c22011-10-19 09:33:39 +0100989 /* Check the interfaces to see if any have exited DAD state
990 and if so, bind the address. */
991 if (is_dad_listeners())
992 {
Simon Kelley115ac3e2013-05-20 11:28:32 +0100993 enumerate_interfaces(0);
Simon Kelley74c95c22011-10-19 09:33:39 +0100994 /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
995 create_bound_listeners(0);
Simon Kelleydc27e142013-10-16 13:09:53 +0100996 warn_bound_listeners();
Simon Kelley74c95c22011-10-19 09:33:39 +0100997 }
Simon Kelleyf2621c72007-04-29 19:47:21 +0100998
Simon Kelley1ee9be42013-12-09 16:50:19 +0000999#if defined(HAVE_LINUX_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001000 if (poll_check(daemon->netlinkfd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001001 netlink_multicast();
Simon Kelley1ee9be42013-12-09 16:50:19 +00001002#elif defined(HAVE_BSD_NETWORK)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001003 if (poll_check(daemon->routefd, POLLIN))
Simon Kelleya0358e52014-06-07 13:38:48 +01001004 route_sock();
Simon Kelleyc52e1892010-06-07 22:01:39 +01001005#endif
1006
Simon Kelley04918052015-01-26 11:23:43 +00001007#ifdef HAVE_INOTIFY
Simon Kelleyb842bc92015-07-12 21:09:11 +01001008 if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001009 {
1010 if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
1011 poll_resolv(1, 1, now);
1012 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001013#else
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001014 /* Check for changes to resolv files once per second max. */
Simon Kelley3d8df262005-08-29 12:19:27 +01001015 /* Don't go silent for long periods if the clock goes backwards. */
Simon Kelley9009d742008-11-14 20:04:27 +00001016 if (daemon->last_resolv == 0 ||
1017 difftime(now, daemon->last_resolv) > 1.0 ||
1018 difftime(now, daemon->last_resolv) < -1.0)
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001019 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001020 /* poll_resolv doesn't need to reload first time through, since
1021 that's queued anyway. */
Simon Kelley33820b72004-04-03 21:10:00 +01001022
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001023 poll_resolv(0, daemon->last_resolv != 0, now);
1024 daemon->last_resolv = now;
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001025 }
Simon Kelley193de4a2014-12-10 17:32:16 +00001026#endif
1027
Simon Kelleyb842bc92015-07-12 21:09:11 +01001028 if (poll_check(piperead, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001029 async_event(piperead, now);
Simon Kelley7cebd202006-05-06 14:13:33 +01001030
Simon Kelley3d8df262005-08-29 12:19:27 +01001031#ifdef HAVE_DBUS
1032 /* if we didn't create a DBus connection, retry now. */
Simon Kelley28866e92011-02-14 20:19:14 +00001033 if (option_bool(OPT_DBUS) && !daemon->dbus)
Simon Kelley3d8df262005-08-29 12:19:27 +01001034 {
1035 char *err;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001036 if ((err = dbus_init()))
Simon Kelleyf2621c72007-04-29 19:47:21 +01001037 my_syslog(LOG_WARNING, _("DBus error: %s"), err);
Simon Kelley3d8df262005-08-29 12:19:27 +01001038 if (daemon->dbus)
Simon Kelleyf2621c72007-04-29 19:47:21 +01001039 my_syslog(LOG_INFO, _("connected to system DBus"));
Simon Kelley3d8df262005-08-29 12:19:27 +01001040 }
Simon Kelleyb842bc92015-07-12 21:09:11 +01001041 check_dbus_listeners();
Simon Kelley3d8df262005-08-29 12:19:27 +01001042#endif
Simon Kelley824af852008-02-12 20:43:05 +00001043
Simon Kelleyb842bc92015-07-12 21:09:11 +01001044 check_dns_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001045
1046#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001047 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001048#endif
1049
Simon Kelley7622fc02009-06-04 20:32:05 +01001050#ifdef HAVE_DHCP
Simon Kelleyff7eea22013-09-04 18:01:38 +01001051 if (daemon->dhcp || daemon->relay4)
Simon Kelley316e2732010-01-22 20:16:09 +00001052 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001053 if (poll_check(daemon->dhcpfd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001054 dhcp_packet(now, 0);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001055 if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
Simon Kelley316e2732010-01-22 20:16:09 +00001056 dhcp_packet(now, 1);
1057 }
Simon Kelley16972692006-10-16 20:04:18 +01001058
Simon Kelley52b92f42012-01-22 16:05:15 +00001059#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001060 if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
Simon Kelley18c63ef2012-05-21 14:34:15 +01001061 dhcp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001062
Simon Kelleyb842bc92015-07-12 21:09:11 +01001063 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001064 icmp6_packet(now);
Simon Kelley52b92f42012-01-22 16:05:15 +00001065#endif
1066
Simon Kelley1f15b812009-10-13 17:49:32 +01001067# ifdef HAVE_SCRIPT
Simon Kelley63ec5d12015-07-30 20:59:07 +01001068 if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLOUT))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001069 helper_write();
Simon Kelley7622fc02009-06-04 20:32:05 +01001070# endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001071#endif
1072
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001073 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001074}
1075
Simon Kelley3be34542004-09-11 19:12:13 +01001076static void sig_handler(int sig)
1077{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001078 if (pid == 0)
1079 {
Simon Kelley16972692006-10-16 20:04:18 +01001080 /* ignore anything other than TERM during startup
1081 and in helper proc. (helper ignore TERM too) */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001082 if (sig == SIGTERM)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001083 exit(EC_MISC);
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001084 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001085 else if (pid != getpid())
Simon Kelley3be34542004-09-11 19:12:13 +01001086 {
Simon Kelley16972692006-10-16 20:04:18 +01001087 /* alarm is used to kill TCP children after a fixed time. */
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001088 if (sig == SIGALRM)
Simon Kelley7cebd202006-05-06 14:13:33 +01001089 _exit(0);
Simon Kelley3be34542004-09-11 19:12:13 +01001090 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001091 else
1092 {
1093 /* master process */
1094 int event, errsave = errno;
1095
1096 if (sig == SIGHUP)
1097 event = EVENT_RELOAD;
1098 else if (sig == SIGCHLD)
1099 event = EVENT_CHILD;
1100 else if (sig == SIGALRM)
1101 event = EVENT_ALARM;
1102 else if (sig == SIGTERM)
1103 event = EVENT_TERM;
1104 else if (sig == SIGUSR1)
1105 event = EVENT_DUMP;
1106 else if (sig == SIGUSR2)
1107 event = EVENT_REOPEN;
1108 else
1109 return;
1110
Simon Kelleyc72daea2012-01-05 21:33:27 +00001111 send_event(pipewrite, event, 0, NULL);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001112 errno = errsave;
1113 }
Simon Kelley3be34542004-09-11 19:12:13 +01001114}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001115
Simon Kelley353ae4d2012-03-19 20:07:51 +00001116/* now == 0 -> queue immediate callback */
1117void send_alarm(time_t event, time_t now)
Simon Kelley741c2952012-02-25 13:09:18 +00001118{
Simon Kelley884a6df2012-03-20 16:20:22 +00001119 if (now == 0 || event != 0)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001120 {
Simon Kelley884a6df2012-03-20 16:20:22 +00001121 /* alarm(0) or alarm(-ve) doesn't do what we want.... */
1122 if ((now == 0 || difftime(event, now) <= 0.0))
1123 send_event(pipewrite, EVENT_ALARM, 0, NULL);
1124 else
1125 alarm((unsigned)difftime(event, now));
Simon Kelley353ae4d2012-03-19 20:07:51 +00001126 }
Simon Kelley741c2952012-02-25 13:09:18 +00001127}
1128
Simon Kelley47a95162014-07-08 22:22:02 +01001129void queue_event(int event)
Simon Kelleya0358e52014-06-07 13:38:48 +01001130{
Simon Kelley47a95162014-07-08 22:22:02 +01001131 send_event(pipewrite, event, 0, NULL);
Simon Kelleya0358e52014-06-07 13:38:48 +01001132}
1133
Simon Kelleyc72daea2012-01-05 21:33:27 +00001134void send_event(int fd, int event, int data, char *msg)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001135{
1136 struct event_desc ev;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001137 struct iovec iov[2];
1138
Simon Kelley5aabfc72007-08-29 11:24:47 +01001139 ev.event = event;
1140 ev.data = data;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001141 ev.msg_sz = msg ? strlen(msg) : 0;
1142
1143 iov[0].iov_base = &ev;
1144 iov[0].iov_len = sizeof(ev);
1145 iov[1].iov_base = msg;
1146 iov[1].iov_len = ev.msg_sz;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001147
1148 /* error pipe, debug mode. */
1149 if (fd == -1)
Simon Kelleyc72daea2012-01-05 21:33:27 +00001150 fatal_event(&ev, msg);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001151 else
1152 /* pipe is non-blocking and struct event_desc is smaller than
1153 PIPE_BUF, so this either fails or writes everything */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001154 while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001155}
Simon Kelley3d8df262005-08-29 12:19:27 +01001156
Simon Kelleyc72daea2012-01-05 21:33:27 +00001157/* NOTE: the memory used to return msg is leaked: use msgs in events only
1158 to describe fatal errors. */
1159static int read_event(int fd, struct event_desc *evp, char **msg)
1160{
1161 char *buf;
1162
1163 if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
1164 return 0;
1165
1166 *msg = NULL;
1167
1168 if (evp->msg_sz != 0 &&
1169 (buf = malloc(evp->msg_sz + 1)) &&
1170 read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
1171 {
1172 buf[evp->msg_sz] = 0;
1173 *msg = buf;
1174 }
1175
1176 return 1;
1177}
1178
1179static void fatal_event(struct event_desc *ev, char *msg)
Simon Kelley1a6bca82008-07-11 11:11:42 +01001180{
1181 errno = ev->data;
1182
1183 switch (ev->event)
1184 {
1185 case EVENT_DIE:
1186 exit(0);
Simon Kelley7622fc02009-06-04 20:32:05 +01001187
1188 case EVENT_FORK_ERR:
1189 die(_("cannot fork into background: %s"), NULL, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001190
1191 case EVENT_PIPE_ERR:
1192 die(_("failed to create helper: %s"), NULL, EC_MISC);
1193
1194 case EVENT_CAP_ERR:
1195 die(_("setting capabilities failed: %s"), NULL, EC_MISC);
1196
1197 case EVENT_USER_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001198 die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001199
1200 case EVENT_GROUP_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001201 die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001202
1203 case EVENT_PIDFILE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001204 die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001205
1206 case EVENT_LOG_ERR:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001207 die(_("cannot open log %s: %s"), msg, EC_FILE);
1208
1209 case EVENT_LUA_ERR:
1210 die(_("failed to load Lua script: %s"), msg, EC_MISC);
Simon Kelley8b3ae2f2012-06-13 13:43:49 +01001211
1212 case EVENT_TFTP_ERR:
1213 die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
Simon Kelley360f2512015-03-07 18:28:06 +00001214
1215 case EVENT_TIME_ERR:
1216 die(_("cannot create timestamp file %s: %s" ), msg, EC_BADCONF);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001217 }
1218}
1219
Simon Kelley5aabfc72007-08-29 11:24:47 +01001220static void async_event(int pipe, time_t now)
1221{
1222 pid_t p;
1223 struct event_desc ev;
Simon Kelley7b1eae42014-02-20 13:43:28 +00001224 int i, check = 0;
Simon Kelleyc72daea2012-01-05 21:33:27 +00001225 char *msg;
1226
1227 /* NOTE: the memory used to return msg is leaked: use msgs in events only
1228 to describe fatal errors. */
1229
1230 if (read_event(pipe, &ev, &msg))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001231 switch (ev.event)
1232 {
1233 case EVENT_RELOAD:
Simon Kelleyc8328ec2016-08-05 16:54:58 +01001234 daemon->soa_sn++; /* Bump zone serial, as it may have changed. */
1235
Simon Kelleye98bd522014-03-28 20:41:23 +00001236#ifdef HAVE_DNSSEC
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +01001237 if (daemon->dnssec_no_time_check && option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
Simon Kelleye98bd522014-03-28 20:41:23 +00001238 {
1239 my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
Kevin Darbyshire-Bryant06093a92016-07-11 21:03:27 +01001240 daemon->dnssec_no_time_check = 0;
Simon Kelleye98bd522014-03-28 20:41:23 +00001241 }
1242#endif
1243 /* fall through */
1244
1245 case EVENT_INIT:
Simon Kelley5aabfc72007-08-29 11:24:47 +01001246 clear_cache_and_reload(now);
Simon Kelleye98bd522014-03-28 20:41:23 +00001247
Simon Kelley7b1eae42014-02-20 13:43:28 +00001248 if (daemon->port != 0)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001249 {
Simon Kelley7b1eae42014-02-20 13:43:28 +00001250 if (daemon->resolv_files && option_bool(OPT_NO_POLL))
1251 {
1252 reload_servers(daemon->resolv_files->name);
1253 check = 1;
1254 }
1255
1256 if (daemon->servers_file)
1257 {
1258 read_servers_file();
1259 check = 1;
1260 }
1261
1262 if (check)
1263 check_servers();
Simon Kelley5aabfc72007-08-29 11:24:47 +01001264 }
Simon Kelley7b1eae42014-02-20 13:43:28 +00001265
Simon Kelley7622fc02009-06-04 20:32:05 +01001266#ifdef HAVE_DHCP
Simon Kelley5aabfc72007-08-29 11:24:47 +01001267 rerun_scripts();
Simon Kelley7622fc02009-06-04 20:32:05 +01001268#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001269 break;
1270
1271 case EVENT_DUMP:
Simon Kelley824af852008-02-12 20:43:05 +00001272 if (daemon->port != 0)
1273 dump_cache(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001274 break;
1275
1276 case EVENT_ALARM:
Simon Kelley7622fc02009-06-04 20:32:05 +01001277#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001278 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001279 {
1280 lease_prune(NULL, now);
1281 lease_update_file(now);
1282 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001283#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001284 else if (daemon->doing_ra)
Simon Kelley353ae4d2012-03-19 20:07:51 +00001285 /* Not doing DHCP, so no lease system, manage alarms for ra only */
1286 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001287#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001288#endif
Simon Kelley5aabfc72007-08-29 11:24:47 +01001289 break;
1290
1291 case EVENT_CHILD:
1292 /* See Stevens 5.10 */
1293 while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
1294 if (p == -1)
1295 {
1296 if (errno != EINTR)
1297 break;
1298 }
1299 else
1300 for (i = 0 ; i < MAX_PROCS; i++)
1301 if (daemon->tcp_pids[i] == p)
1302 daemon->tcp_pids[i] = 0;
1303 break;
1304
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001305#if defined(HAVE_SCRIPT)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001306 case EVENT_KILLED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001307 my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001308 break;
1309
1310 case EVENT_EXITED:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001311 my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001312 break;
1313
1314 case EVENT_EXEC_ERR:
Simon Kelley9e038942008-05-30 20:06:34 +01001315 my_syslog(LOG_ERR, _("failed to execute %s: %s"),
1316 daemon->lease_change_command, strerror(ev.data));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001317 break;
1318
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001319 case EVENT_SCRIPT_LOG:
1320 my_syslog(MS_SCRIPT | LOG_DEBUG, "%s", msg ? msg : "");
1321 free(msg);
1322 msg = NULL;
1323 break;
1324
Simon Kelley1a6bca82008-07-11 11:11:42 +01001325 /* necessary for fatal errors in helper */
Simon Kelleyc72daea2012-01-05 21:33:27 +00001326 case EVENT_USER_ERR:
Simon Kelley1a6bca82008-07-11 11:11:42 +01001327 case EVENT_DIE:
Simon Kelleyc72daea2012-01-05 21:33:27 +00001328 case EVENT_LUA_ERR:
1329 fatal_event(&ev, msg);
Simon Kelley9e038942008-05-30 20:06:34 +01001330 break;
Petr Menšíkc77fb9d2017-04-16 20:20:08 +01001331#endif
Simon Kelley9e038942008-05-30 20:06:34 +01001332
Simon Kelley5aabfc72007-08-29 11:24:47 +01001333 case EVENT_REOPEN:
1334 /* Note: this may leave TCP-handling processes with the old file still open.
1335 Since any such process will die in CHILD_LIFETIME or probably much sooner,
1336 we leave them logging to the old file. */
1337 if (daemon->log_file != NULL)
1338 log_reopen(daemon->log_file);
1339 break;
Simon Kelleya0358e52014-06-07 13:38:48 +01001340
1341 case EVENT_NEWADDR:
1342 newaddress(now);
1343 break;
Simon Kelley47a95162014-07-08 22:22:02 +01001344
1345 case EVENT_NEWROUTE:
1346 resend_query();
1347 /* Force re-reading resolv file right now, for luck. */
1348 poll_resolv(0, 1, now);
1349 break;
1350
Simon Kelley5aabfc72007-08-29 11:24:47 +01001351 case EVENT_TERM:
1352 /* Knock all our children on the head. */
1353 for (i = 0; i < MAX_PROCS; i++)
1354 if (daemon->tcp_pids[i] != 0)
1355 kill(daemon->tcp_pids[i], SIGALRM);
1356
Simon Kelley53a91732016-01-06 17:59:13 +00001357#if defined(HAVE_SCRIPT) && defined(HAVE_DHCP)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001358 /* handle pending lease transitions */
1359 if (daemon->helperfd != -1)
1360 {
1361 /* block in writes until all done */
1362 if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
1363 fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
1364 do {
1365 helper_write();
1366 } while (!helper_buf_empty() || do_script_run(now));
Simon Kelleyff841eb2015-03-11 21:36:30 +00001367 while (retry_send(close(daemon->helperfd)));
Simon Kelley5aabfc72007-08-29 11:24:47 +01001368 }
1369#endif
1370
1371 if (daemon->lease_stream)
1372 fclose(daemon->lease_stream);
Simon Kelley73a08a22009-02-05 20:28:08 +00001373
Kevin Darbyshire-Bryant34b5d192015-07-27 19:34:23 +01001374#ifdef HAVE_DNSSEC
1375 /* update timestamp file on TERM if time is considered valid */
1376 if (daemon->back_to_the_future)
1377 {
1378 if (utime(daemon->timestamp_file, NULL) == -1)
1379 my_syslog(LOG_ERR, _("failed to update mtime on %s: %s"), daemon->timestamp_file, strerror(errno));
1380 }
1381#endif
1382
Simon Kelley73a08a22009-02-05 20:28:08 +00001383 if (daemon->runfile)
1384 unlink(daemon->runfile);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001385
1386 my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
1387 flush_log();
1388 exit(EC_GOOD);
1389 }
1390}
1391
Simon Kelley47a95162014-07-08 22:22:02 +01001392static void poll_resolv(int force, int do_reload, time_t now)
Simon Kelley5aabfc72007-08-29 11:24:47 +01001393{
1394 struct resolvc *res, *latest;
1395 struct stat statbuf;
1396 time_t last_change = 0;
1397 /* There may be more than one possible file.
1398 Go through and find the one which changed _last_.
1399 Warn of any which can't be read. */
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001400
Simon Kelley28866e92011-02-14 20:19:14 +00001401 if (daemon->port == 0 || option_bool(OPT_NO_POLL))
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001402 return;
1403
Simon Kelley5aabfc72007-08-29 11:24:47 +01001404 for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
1405 if (stat(res->name, &statbuf) == -1)
1406 {
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001407 if (force)
1408 {
1409 res->mtime = 0;
1410 continue;
1411 }
1412
Simon Kelley5aabfc72007-08-29 11:24:47 +01001413 if (!res->logged)
1414 my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
1415 res->logged = 1;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001416
1417 if (res->mtime != 0)
1418 {
1419 /* existing file evaporated, force selection of the latest
1420 file even if its mtime hasn't changed since we last looked */
1421 poll_resolv(1, do_reload, now);
1422 return;
1423 }
Simon Kelley5aabfc72007-08-29 11:24:47 +01001424 }
1425 else
1426 {
1427 res->logged = 0;
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001428 if (force || (statbuf.st_mtime != res->mtime))
1429 {
1430 res->mtime = statbuf.st_mtime;
Simon Kelley5aabfc72007-08-29 11:24:47 +01001431 if (difftime(statbuf.st_mtime, last_change) > 0.0)
1432 {
1433 last_change = statbuf.st_mtime;
1434 latest = res;
1435 }
1436 }
1437 }
1438
1439 if (latest)
1440 {
1441 static int warned = 0;
1442 if (reload_servers(latest->name))
1443 {
1444 my_syslog(LOG_INFO, _("reading %s"), latest->name);
1445 warned = 0;
1446 check_servers();
Simon Kelley28866e92011-02-14 20:19:14 +00001447 if (option_bool(OPT_RELOAD) && do_reload)
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001448 clear_cache_and_reload(now);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001449 }
1450 else
1451 {
1452 latest->mtime = 0;
1453 if (!warned)
1454 {
1455 my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
1456 warned = 1;
1457 }
1458 }
1459 }
1460}
1461
1462void clear_cache_and_reload(time_t now)
Simon Kelley3d8df262005-08-29 12:19:27 +01001463{
Vladislav Grishenko408c3682013-09-24 16:18:49 +01001464 (void)now;
1465
Simon Kelley824af852008-02-12 20:43:05 +00001466 if (daemon->port != 0)
Simon Kelley7622fc02009-06-04 20:32:05 +01001467 cache_reload();
Simon Kelley824af852008-02-12 20:43:05 +00001468
Simon Kelley7622fc02009-06-04 20:32:05 +01001469#ifdef HAVE_DHCP
Simon Kelley1f776932012-12-16 19:46:08 +00001470 if (daemon->dhcp || daemon->doing_dhcp6)
Simon Kelley3d8df262005-08-29 12:19:27 +01001471 {
Simon Kelley28866e92011-02-14 20:19:14 +00001472 if (option_bool(OPT_ETHERS))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001473 dhcp_read_ethers();
Simon Kelley824af852008-02-12 20:43:05 +00001474 reread_dhcp();
Simon Kelley04918052015-01-26 11:23:43 +00001475#ifdef HAVE_INOTIFY
Simon Kelley70d18732015-01-31 19:59:29 +00001476 set_dynamic_inotify(AH_DHCP_HST | AH_DHCP_OPT, 0, NULL, 0);
Simon Kelley5f4dc5c2015-01-20 20:51:02 +00001477#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001478 dhcp_update_configs(daemon->dhcp_conf);
Simon Kelley5aabfc72007-08-29 11:24:47 +01001479 lease_update_from_configs();
1480 lease_update_file(now);
Simon Kelley353ae4d2012-03-19 20:07:51 +00001481 lease_update_dns(1);
Simon Kelley3d8df262005-08-29 12:19:27 +01001482 }
Simon Kelley843c96b2012-02-27 17:42:38 +00001483#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001484 else if (daemon->doing_ra)
Simon Kelley2021c662012-05-07 16:43:21 +01001485 /* Not doing DHCP, so no lease system, manage
1486 alarms for ra only */
1487 send_alarm(periodic_ra(now), now);
Simon Kelley843c96b2012-02-27 17:42:38 +00001488#endif
Simon Kelley7622fc02009-06-04 20:32:05 +01001489#endif
Simon Kelley3d8df262005-08-29 12:19:27 +01001490}
1491
Simon Kelleyb842bc92015-07-12 21:09:11 +01001492static int set_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001493{
1494 struct serverfd *serverfdp;
1495 struct listener *listener;
Simon Kelley824af852008-02-12 20:43:05 +00001496 int wait = 0, i;
Simon Kelley832af0b2007-01-21 20:01:28 +00001497
1498#ifdef HAVE_TFTP
1499 int tftp = 0;
1500 struct tftp_transfer *transfer;
1501 for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
1502 {
1503 tftp++;
Simon Kelleyb842bc92015-07-12 21:09:11 +01001504 poll_listen(transfer->sockfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001505 }
1506#endif
1507
Simon Kelley16972692006-10-16 20:04:18 +01001508 /* will we be able to get memory? */
Simon Kelley824af852008-02-12 20:43:05 +00001509 if (daemon->port != 0)
Simon Kelley3a237152013-12-12 12:15:50 +00001510 get_new_frec(now, &wait, 0);
Simon Kelley16972692006-10-16 20:04:18 +01001511
Simon Kelley3be34542004-09-11 19:12:13 +01001512 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001513 poll_listen(serverfdp->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001514
Simon Kelley1a6bca82008-07-11 11:11:42 +01001515 if (daemon->port != 0 && !daemon->osport)
1516 for (i = 0; i < RANDOM_SOCKS; i++)
1517 if (daemon->randomsocks[i].refcount != 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001518 poll_listen(daemon->randomsocks[i].fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001519
Simon Kelley3be34542004-09-11 19:12:13 +01001520 for (listener = daemon->listeners; listener; listener = listener->next)
1521 {
Simon Kelley16972692006-10-16 20:04:18 +01001522 /* only listen for queries if we have resources */
Simon Kelley824af852008-02-12 20:43:05 +00001523 if (listener->fd != -1 && wait == 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001524 poll_listen(listener->fd, POLLIN);
Simon Kelleyf6d69562015-07-08 22:38:13 +01001525
Simon Kelley16972692006-10-16 20:04:18 +01001526 /* death of a child goes through the select loop, so
1527 we don't need to explicitly arrange to wake up here */
Simon Kelley824af852008-02-12 20:43:05 +00001528 if (listener->tcpfd != -1)
1529 for (i = 0; i < MAX_PROCS; i++)
1530 if (daemon->tcp_pids[i] == 0)
1531 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001532 poll_listen(listener->tcpfd, POLLIN);
Simon Kelley824af852008-02-12 20:43:05 +00001533 break;
1534 }
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001535
Simon Kelley832af0b2007-01-21 20:01:28 +00001536#ifdef HAVE_TFTP
1537 if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001538 poll_listen(listener->tftpfd, POLLIN);
Simon Kelley832af0b2007-01-21 20:01:28 +00001539#endif
1540
1541 }
1542
Simon Kelley16972692006-10-16 20:04:18 +01001543 return wait;
Simon Kelley3be34542004-09-11 19:12:13 +01001544}
Simon Kelley9e4abcb2004-01-22 19:47:41 +00001545
Simon Kelleyb842bc92015-07-12 21:09:11 +01001546static void check_dns_listeners(time_t now)
Simon Kelley3be34542004-09-11 19:12:13 +01001547{
1548 struct serverfd *serverfdp;
Simon Kelley1a6bca82008-07-11 11:11:42 +01001549 struct listener *listener;
1550 int i;
1551
Simon Kelley832af0b2007-01-21 20:01:28 +00001552 for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001553 if (poll_check(serverfdp->fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001554 reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
1555
1556 if (daemon->port != 0 && !daemon->osport)
1557 for (i = 0; i < RANDOM_SOCKS; i++)
1558 if (daemon->randomsocks[i].refcount != 0 &&
Simon Kelleyb842bc92015-07-12 21:09:11 +01001559 poll_check(daemon->randomsocks[i].fd, POLLIN))
Simon Kelley1a6bca82008-07-11 11:11:42 +01001560 reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001561
1562 for (listener = daemon->listeners; listener; listener = listener->next)
1563 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001564 if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001565 receive_query(listener, now);
Simon Kelley1a6bca82008-07-11 11:11:42 +01001566
Simon Kelley832af0b2007-01-21 20:01:28 +00001567#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001568 if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001569 tftp_request(listener, now);
Simon Kelley59353a62004-11-21 19:34:28 +00001570#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001571
Simon Kelleyb842bc92015-07-12 21:09:11 +01001572 if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
Simon Kelley832af0b2007-01-21 20:01:28 +00001573 {
Simon Kelley22ce5502013-01-22 13:53:04 +00001574 int confd, client_ok = 1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001575 struct irec *iface = NULL;
1576 pid_t p;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001577 union mysockaddr tcp_addr;
1578 socklen_t tcp_len = sizeof(union mysockaddr);
1579
1580 while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
Simon Kelley832af0b2007-01-21 20:01:28 +00001581
Simon Kelley46b06652013-02-04 21:47:59 +00001582 if (confd == -1)
Simon Kelley832af0b2007-01-21 20:01:28 +00001583 continue;
Simon Kelley76dd75d2013-05-23 10:04:25 +01001584
Simon Kelley46b06652013-02-04 21:47:59 +00001585 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
1586 {
Simon Kelleyff841eb2015-03-11 21:36:30 +00001587 while (retry_send(close(confd)));
Simon Kelley46b06652013-02-04 21:47:59 +00001588 continue;
1589 }
Simon Kelley76dd75d2013-05-23 10:04:25 +01001590
1591 /* Make sure that the interface list is up-to-date.
1592
1593 We do this here as we may need the results below, and
1594 the DNS code needs them for --interface-name stuff.
Simon Kelley46b06652013-02-04 21:47:59 +00001595
Simon Kelley76dd75d2013-05-23 10:04:25 +01001596 Multiple calls to enumerate_interfaces() per select loop are
1597 inhibited, so calls to it in the child process (which doesn't select())
1598 have no effect. This avoids two processes reading from the same
1599 netlink fd and screwing the pooch entirely.
1600 */
Simon Kelleye25db1f2013-01-29 22:10:26 +00001601
Simon Kelley76dd75d2013-05-23 10:04:25 +01001602 enumerate_interfaces(0);
1603
1604 if (option_bool(OPT_NOWILD))
1605 iface = listener->iface; /* May be NULL */
1606 else
1607 {
1608 int if_index;
1609 char intr_name[IF_NAMESIZE];
1610
1611 /* if we can find the arrival interface, check it's one that's allowed */
1612 if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
1613 indextoname(listener->tcpfd, if_index, intr_name))
1614 {
1615 struct all_addr addr;
1616 addr.addr.addr4 = tcp_addr.in.sin_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001617#ifdef HAVE_IPV6
Simon Kelley76dd75d2013-05-23 10:04:25 +01001618 if (tcp_addr.sa.sa_family == AF_INET6)
1619 addr.addr.addr6 = tcp_addr.in6.sin6_addr;
Simon Kelleye25db1f2013-01-29 22:10:26 +00001620#endif
Simon Kelley76dd75d2013-05-23 10:04:25 +01001621
1622 for (iface = daemon->interfaces; iface; iface = iface->next)
1623 if (iface->index == if_index)
1624 break;
1625
1626 if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
1627 client_ok = 0;
1628 }
1629
1630 if (option_bool(OPT_CLEVERBIND))
1631 iface = listener->iface; /* May be NULL */
1632 else
1633 {
1634 /* Check for allowed interfaces when binding the wildcard address:
1635 we do this by looking for an interface with the same address as
1636 the local address of the TCP connection, then looking to see if that's
1637 an allowed interface. As a side effect, we get the netmask of the
1638 interface too, for localisation. */
1639
1640 for (iface = daemon->interfaces; iface; iface = iface->next)
1641 if (sockaddr_isequal(&iface->addr, &tcp_addr))
1642 break;
1643
1644 if (!iface)
1645 client_ok = 0;
1646 }
1647 }
1648
Simon Kelley22ce5502013-01-22 13:53:04 +00001649 if (!client_ok)
Simon Kelley832af0b2007-01-21 20:01:28 +00001650 {
1651 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001652 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001653 }
1654#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001655 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
Simon Kelley832af0b2007-01-21 20:01:28 +00001656 {
1657 if (p != -1)
1658 {
1659 int i;
1660 for (i = 0; i < MAX_PROCS; i++)
1661 if (daemon->tcp_pids[i] == 0)
1662 {
1663 daemon->tcp_pids[i] = p;
1664 break;
1665 }
1666 }
Simon Kelleyff841eb2015-03-11 21:36:30 +00001667 while (retry_send(close(confd)));
Simon Kelley25cf5e32015-01-09 15:53:03 +00001668
1669 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
1670 daemon->log_id += TCP_MAX_QUERIES;
Simon Kelley832af0b2007-01-21 20:01:28 +00001671 }
1672#endif
1673 else
1674 {
1675 unsigned char *buff;
1676 struct server *s;
1677 int flags;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001678 struct in_addr netmask;
Simon Kelley4f7b3042012-11-28 21:27:02 +00001679 int auth_dns;
Simon Kelley52d4abf2012-03-21 21:39:48 +00001680
1681 if (iface)
Simon Kelley4f7b3042012-11-28 21:27:02 +00001682 {
1683 netmask = iface->netmask;
1684 auth_dns = iface->dns_auth;
1685 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001686 else
Simon Kelley4f7b3042012-11-28 21:27:02 +00001687 {
1688 netmask.s_addr = 0;
1689 auth_dns = 0;
1690 }
Simon Kelley52d4abf2012-03-21 21:39:48 +00001691
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001692#ifndef NO_FORK
Josh Soref730c6742017-02-06 16:14:04 +00001693 /* Arrange for SIGALRM after CHILD_LIFETIME seconds to
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001694 terminate the process. */
Simon Kelley28866e92011-02-14 20:19:14 +00001695 if (!option_bool(OPT_DEBUG))
Simon Kelley832af0b2007-01-21 20:01:28 +00001696 alarm(CHILD_LIFETIME);
Simon Kelley8ef5ada2010-06-03 19:42:45 +01001697#endif
1698
Simon Kelley832af0b2007-01-21 20:01:28 +00001699 /* start with no upstream connections. */
1700 for (s = daemon->servers; s; s = s->next)
Simon Kelley7cebd202006-05-06 14:13:33 +01001701 s->tcpfd = -1;
Simon Kelley832af0b2007-01-21 20:01:28 +00001702
1703 /* The connected socket inherits non-blocking
1704 attribute from the listening socket.
1705 Reset that here. */
1706 if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
1707 fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
1708
Simon Kelley4f7b3042012-11-28 21:27:02 +00001709 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
Simon Kelley7cebd202006-05-06 14:13:33 +01001710
Simon Kelley832af0b2007-01-21 20:01:28 +00001711 shutdown(confd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001712 while (retry_send(close(confd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001713
1714 if (buff)
1715 free(buff);
1716
1717 for (s = daemon->servers; s; s = s->next)
1718 if (s->tcpfd != -1)
1719 {
1720 shutdown(s->tcpfd, SHUT_RDWR);
Simon Kelleyff841eb2015-03-11 21:36:30 +00001721 while (retry_send(close(s->tcpfd)));
Simon Kelley832af0b2007-01-21 20:01:28 +00001722 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001723#ifndef NO_FORK
Simon Kelley28866e92011-02-14 20:19:14 +00001724 if (!option_bool(OPT_DEBUG))
Simon Kelley5aabfc72007-08-29 11:24:47 +01001725 {
1726 flush_log();
1727 _exit(0);
1728 }
Simon Kelley7cebd202006-05-06 14:13:33 +01001729#endif
Simon Kelley832af0b2007-01-21 20:01:28 +00001730 }
1731 }
1732 }
Simon Kelley3be34542004-09-11 19:12:13 +01001733}
1734
Simon Kelley7622fc02009-06-04 20:32:05 +01001735#ifdef HAVE_DHCP
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001736int make_icmp_sock(void)
1737{
Simon Kelley7cebd202006-05-06 14:13:33 +01001738 int fd;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001739 int zeroopt = 0;
1740
1741 if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
1742 {
Simon Kelley7cebd202006-05-06 14:13:33 +01001743 if (!fix_fd(fd) ||
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001744 setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
1745 {
1746 close(fd);
1747 fd = -1;
1748 }
1749 }
1750
1751 return fd;
1752}
1753
Simon Kelley5aabfc72007-08-29 11:24:47 +01001754int icmp_ping(struct in_addr addr)
Simon Kelley3be34542004-09-11 19:12:13 +01001755{
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001756 /* Try and get an ICMP echo from a machine. */
Simon Kelley3be34542004-09-11 19:12:13 +01001757
Floris Bos503c6092017-04-09 23:07:13 +01001758 int fd;
Simon Kelley3be34542004-09-11 19:12:13 +01001759 struct sockaddr_in saddr;
1760 struct {
1761 struct ip ip;
1762 struct icmp icmp;
1763 } packet;
1764 unsigned short id = rand16();
Floris Bos503c6092017-04-09 23:07:13 +01001765 unsigned int i, j;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001766 int gotreply = 0;
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001767
Simon Kelley824af852008-02-12 20:43:05 +00001768#if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001769 if ((fd = make_icmp_sock()) == -1)
1770 return 0;
1771#else
1772 int opt = 2000;
1773 fd = daemon->dhcp_icmp_fd;
1774 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1775#endif
1776
Simon Kelley3be34542004-09-11 19:12:13 +01001777 saddr.sin_family = AF_INET;
1778 saddr.sin_port = 0;
1779 saddr.sin_addr = addr;
1780#ifdef HAVE_SOCKADDR_SA_LEN
1781 saddr.sin_len = sizeof(struct sockaddr_in);
1782#endif
1783
1784 memset(&packet.icmp, 0, sizeof(packet.icmp));
1785 packet.icmp.icmp_type = ICMP_ECHO;
1786 packet.icmp.icmp_id = id;
1787 for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
1788 j += ((u16 *)&packet.icmp)[i];
1789 while (j>>16)
1790 j = (j & 0xffff) + (j >> 16);
1791 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1792
Simon Kelleyff841eb2015-03-11 21:36:30 +00001793 while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
1794 (struct sockaddr *)&saddr, sizeof(saddr))));
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001795
Floris Bos503c6092017-04-09 23:07:13 +01001796 gotreply = delay_dhcp(dnsmasq_time(), PING_WAIT, fd, addr.s_addr, id);
1797
1798#if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
1799 while (retry_send(close(fd)));
1800#else
1801 opt = 1;
1802 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1803#endif
1804
1805 return gotreply;
1806}
1807
1808int delay_dhcp(time_t start, int sec, int fd, uint32_t addr, unsigned short id)
1809{
1810 /* Delay processing DHCP packets for "sec" seconds counting from "start".
1811 If "fd" is not -1 it will stop waiting if an ICMP echo reply is received
1812 from "addr" with ICMP ID "id" and return 1 */
1813
1814 /* Note that whilst waiting, we check for
1815 (and service) events on the DNS and TFTP sockets, (so doing that
1816 better not use any resources our caller has in use...)
1817 but we remain deaf to signals or further DHCP packets. */
1818
1819 /* There can be a problem using dnsmasq_time() to end the loop, since
1820 it's not monotonic, and can go backwards if the system clock is
1821 tweaked, leading to the code getting stuck in this loop and
1822 ignoring DHCP requests. To fix this, we check to see if select returned
1823 as a result of a timeout rather than a socket becoming available. We
1824 only allow this to happen as many times as it takes to get to the wait time
1825 in quarter-second chunks. This provides a fallback way to end loop. */
1826
1827 int rc, timeout_count;
1828 time_t now;
1829
1830 for (now = dnsmasq_time(), timeout_count = 0;
1831 (difftime(now, start) <= (float)sec) && (timeout_count < sec * 4);)
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001832 {
Simon Kelleyb842bc92015-07-12 21:09:11 +01001833 poll_reset();
Floris Bos503c6092017-04-09 23:07:13 +01001834 if (fd != -1)
1835 poll_listen(fd, POLLIN);
Simon Kelleyb842bc92015-07-12 21:09:11 +01001836 set_dns_listeners(now);
1837 set_log_writer();
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001838
1839#ifdef HAVE_DHCP6
Simon Kelley1f776932012-12-16 19:46:08 +00001840 if (daemon->doing_ra)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001841 poll_listen(daemon->icmp6fd, POLLIN);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001842#endif
1843
Simon Kelleyb842bc92015-07-12 21:09:11 +01001844 rc = do_poll(250);
Simon Kelley5e95a552015-07-05 22:31:30 +01001845
1846 if (rc < 0)
Simon Kelleyb842bc92015-07-12 21:09:11 +01001847 continue;
Simon Kelley5e95a552015-07-05 22:31:30 +01001848 else if (rc == 0)
1849 timeout_count++;
Simon Kelleyf2621c72007-04-29 19:47:21 +01001850
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001851 now = dnsmasq_time();
Floris Bos503c6092017-04-09 23:07:13 +01001852
Simon Kelleyb842bc92015-07-12 21:09:11 +01001853 check_log_writer(0);
1854 check_dns_listeners(now);
Floris Bos503c6092017-04-09 23:07:13 +01001855
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001856#ifdef HAVE_DHCP6
Simon Kelleyb842bc92015-07-12 21:09:11 +01001857 if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
Simon Kelley1f776932012-12-16 19:46:08 +00001858 icmp6_packet(now);
Simon Kelleyc5ad4e72012-02-24 16:06:20 +00001859#endif
1860
Simon Kelley832af0b2007-01-21 20:01:28 +00001861#ifdef HAVE_TFTP
Simon Kelleyb842bc92015-07-12 21:09:11 +01001862 check_tftp_listeners(now);
Simon Kelley832af0b2007-01-21 20:01:28 +00001863#endif
1864
Floris Bos503c6092017-04-09 23:07:13 +01001865 if (fd != -1)
1866 {
1867 struct {
1868 struct ip ip;
1869 struct icmp icmp;
1870 } packet;
1871 struct sockaddr_in faddr;
1872 socklen_t len = sizeof(faddr);
1873
1874 if (poll_check(fd, POLLIN) &&
1875 recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
1876 addr == faddr.sin_addr.s_addr &&
1877 packet.icmp.icmp_type == ICMP_ECHOREPLY &&
1878 packet.icmp.icmp_seq == 0 &&
1879 packet.icmp.icmp_id == id)
1880 return 1;
Simon Kelleyfd9fa482004-10-21 20:24:00 +01001881 }
1882 }
Simon Kelley5e9e0ef2006-04-17 14:24:29 +01001883
Floris Bos503c6092017-04-09 23:07:13 +01001884 return 0;
Simon Kelley3be34542004-09-11 19:12:13 +01001885}
Simon Kelley7622fc02009-06-04 20:32:05 +01001886#endif
Simon Kelley0a852542005-03-23 20:28:59 +00001887
1888