1*c2c26c8bSAndroid Build Coastguard Worker /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley
2*c2c26c8bSAndroid Build Coastguard Worker
3*c2c26c8bSAndroid Build Coastguard Worker This program is free software; you can redistribute it and/or modify
4*c2c26c8bSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
5*c2c26c8bSAndroid Build Coastguard Worker the Free Software Foundation; version 2 dated June, 1991, or
6*c2c26c8bSAndroid Build Coastguard Worker (at your option) version 3 dated 29 June, 2007.
7*c2c26c8bSAndroid Build Coastguard Worker
8*c2c26c8bSAndroid Build Coastguard Worker This program is distributed in the hope that it will be useful,
9*c2c26c8bSAndroid Build Coastguard Worker but WITHOUT ANY WARRANTY; without even the implied warranty of
10*c2c26c8bSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*c2c26c8bSAndroid Build Coastguard Worker GNU General Public License for more details.
12*c2c26c8bSAndroid Build Coastguard Worker
13*c2c26c8bSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
14*c2c26c8bSAndroid Build Coastguard Worker along with this program. If not, see <http://www.gnu.org/licenses/>.
15*c2c26c8bSAndroid Build Coastguard Worker */
16*c2c26c8bSAndroid Build Coastguard Worker
17*c2c26c8bSAndroid Build Coastguard Worker #include "dnsmasq.h"
18*c2c26c8bSAndroid Build Coastguard Worker
19*c2c26c8bSAndroid Build Coastguard Worker #include <sys/stat.h>
20*c2c26c8bSAndroid Build Coastguard Worker
21*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_BSD_NETWORK)
22*c2c26c8bSAndroid Build Coastguard Worker #error Should not HAVE_BSD_NETWORK
23*c2c26c8bSAndroid Build Coastguard Worker #endif
24*c2c26c8bSAndroid Build Coastguard Worker
25*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_SOCKADDR_SA_LEN)
26*c2c26c8bSAndroid Build Coastguard Worker #error Should not HAVE_SOCKADDR_SA_LEN
27*c2c26c8bSAndroid Build Coastguard Worker #endif
28*c2c26c8bSAndroid Build Coastguard Worker
29*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_SOLARIS_NETWORK)
30*c2c26c8bSAndroid Build Coastguard Worker #error Should not HAVE_SOLARIS_NETWORK
31*c2c26c8bSAndroid Build Coastguard Worker #endif
32*c2c26c8bSAndroid Build Coastguard Worker
33*c2c26c8bSAndroid Build Coastguard Worker #if !defined(HAVE_LINUX_NETWORK)
34*c2c26c8bSAndroid Build Coastguard Worker #error Should HAVE_LINUX_NETWORK
35*c2c26c8bSAndroid Build Coastguard Worker #endif
36*c2c26c8bSAndroid Build Coastguard Worker
37*c2c26c8bSAndroid Build Coastguard Worker struct daemon* daemon;
38*c2c26c8bSAndroid Build Coastguard Worker
39*c2c26c8bSAndroid Build Coastguard Worker static char* compile_opts =
40*c2c26c8bSAndroid Build Coastguard Worker #ifndef HAVE_IPV6
41*c2c26c8bSAndroid Build Coastguard Worker "no-"
42*c2c26c8bSAndroid Build Coastguard Worker #endif
43*c2c26c8bSAndroid Build Coastguard Worker "IPv6 "
44*c2c26c8bSAndroid Build Coastguard Worker #ifndef HAVE_GETOPT_LONG
45*c2c26c8bSAndroid Build Coastguard Worker "no-"
46*c2c26c8bSAndroid Build Coastguard Worker #endif
47*c2c26c8bSAndroid Build Coastguard Worker "GNU-getopt "
48*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_BROKEN_RTC
49*c2c26c8bSAndroid Build Coastguard Worker "no-RTC "
50*c2c26c8bSAndroid Build Coastguard Worker #endif
51*c2c26c8bSAndroid Build Coastguard Worker #ifdef NO_FORK
52*c2c26c8bSAndroid Build Coastguard Worker "no-MMU "
53*c2c26c8bSAndroid Build Coastguard Worker #endif
54*c2c26c8bSAndroid Build Coastguard Worker #ifndef LOCALEDIR
55*c2c26c8bSAndroid Build Coastguard Worker "no-"
56*c2c26c8bSAndroid Build Coastguard Worker #endif
57*c2c26c8bSAndroid Build Coastguard Worker "I18N "
58*c2c26c8bSAndroid Build Coastguard Worker #ifndef HAVE_DHCP
59*c2c26c8bSAndroid Build Coastguard Worker "no-"
60*c2c26c8bSAndroid Build Coastguard Worker #endif
61*c2c26c8bSAndroid Build Coastguard Worker "DHCP "
62*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_DHCP) && !defined(HAVE_SCRIPT)
63*c2c26c8bSAndroid Build Coastguard Worker "no-scripts"
64*c2c26c8bSAndroid Build Coastguard Worker #endif
65*c2c26c8bSAndroid Build Coastguard Worker "";
66*c2c26c8bSAndroid Build Coastguard Worker
67*c2c26c8bSAndroid Build Coastguard Worker static volatile pid_t pid = 0;
68*c2c26c8bSAndroid Build Coastguard Worker static volatile int pipewrite;
69*c2c26c8bSAndroid Build Coastguard Worker
70*c2c26c8bSAndroid Build Coastguard Worker static int set_dns_listeners(time_t now, fd_set* set, int* maxfdp);
71*c2c26c8bSAndroid Build Coastguard Worker static void check_dns_listeners(fd_set* set, time_t now);
72*c2c26c8bSAndroid Build Coastguard Worker static void sig_handler(int sig);
73*c2c26c8bSAndroid Build Coastguard Worker static void async_event(int pipe, time_t now);
74*c2c26c8bSAndroid Build Coastguard Worker static void fatal_event(struct event_desc* ev);
75*c2c26c8bSAndroid Build Coastguard Worker static void poll_resolv(void);
76*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
77*c2c26c8bSAndroid Build Coastguard Worker static int set_android_listeners(fd_set* set, int* maxfdp);
78*c2c26c8bSAndroid Build Coastguard Worker static int check_android_listeners(fd_set* set);
79*c2c26c8bSAndroid Build Coastguard Worker #endif
80*c2c26c8bSAndroid Build Coastguard Worker
setupSignalHandling()81*c2c26c8bSAndroid Build Coastguard Worker void setupSignalHandling() {
82*c2c26c8bSAndroid Build Coastguard Worker struct sigaction sigact;
83*c2c26c8bSAndroid Build Coastguard Worker
84*c2c26c8bSAndroid Build Coastguard Worker sigact.sa_handler = sig_handler;
85*c2c26c8bSAndroid Build Coastguard Worker sigact.sa_flags = 0;
86*c2c26c8bSAndroid Build Coastguard Worker sigemptyset(&sigact.sa_mask);
87*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGUSR1, &sigact, NULL);
88*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGUSR2, &sigact, NULL);
89*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGHUP, &sigact, NULL);
90*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGTERM, &sigact, NULL);
91*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGALRM, &sigact, NULL);
92*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGCHLD, &sigact, NULL);
93*c2c26c8bSAndroid Build Coastguard Worker
94*c2c26c8bSAndroid Build Coastguard Worker /* ignore SIGPIPE */
95*c2c26c8bSAndroid Build Coastguard Worker sigact.sa_handler = SIG_IGN;
96*c2c26c8bSAndroid Build Coastguard Worker sigaction(SIGPIPE, &sigact, NULL);
97*c2c26c8bSAndroid Build Coastguard Worker }
98*c2c26c8bSAndroid Build Coastguard Worker
closeUnwantedFileDescriptors()99*c2c26c8bSAndroid Build Coastguard Worker void closeUnwantedFileDescriptors() {
100*c2c26c8bSAndroid Build Coastguard Worker const long kMaxFd = sysconf(_SC_OPEN_MAX);
101*c2c26c8bSAndroid Build Coastguard Worker long i;
102*c2c26c8bSAndroid Build Coastguard Worker struct stat stat_buf;
103*c2c26c8bSAndroid Build Coastguard Worker
104*c2c26c8bSAndroid Build Coastguard Worker /* Close any file descriptors we inherited apart from std{in|out|err}. */
105*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < kMaxFd; i++) {
106*c2c26c8bSAndroid Build Coastguard Worker // TODO: Evaluate just skipping STDIN, since netd does not
107*c2c26c8bSAndroid Build Coastguard Worker // (intentionally) pass in any other file descriptors.
108*c2c26c8bSAndroid Build Coastguard Worker if (i == STDOUT_FILENO || i == STDERR_FILENO || i == STDIN_FILENO) {
109*c2c26c8bSAndroid Build Coastguard Worker continue;
110*c2c26c8bSAndroid Build Coastguard Worker }
111*c2c26c8bSAndroid Build Coastguard Worker
112*c2c26c8bSAndroid Build Coastguard Worker if (fstat(i, &stat_buf) != 0) {
113*c2c26c8bSAndroid Build Coastguard Worker if (errno == EBADF) continue;
114*c2c26c8bSAndroid Build Coastguard Worker if (errno == EACCES) continue; // Lessen the log spam.
115*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, "fstat(%d) error: %d/%s", i, errno, strerror(errno));
116*c2c26c8bSAndroid Build Coastguard Worker } else {
117*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, "Closing inherited file descriptor %d (%u:%u)", i, stat_buf.st_dev,
118*c2c26c8bSAndroid Build Coastguard Worker stat_buf.st_ino);
119*c2c26c8bSAndroid Build Coastguard Worker }
120*c2c26c8bSAndroid Build Coastguard Worker close(i);
121*c2c26c8bSAndroid Build Coastguard Worker }
122*c2c26c8bSAndroid Build Coastguard Worker }
123*c2c26c8bSAndroid Build Coastguard Worker
main(int argc,char ** argv)124*c2c26c8bSAndroid Build Coastguard Worker int main(int argc, char** argv) {
125*c2c26c8bSAndroid Build Coastguard Worker int bind_fallback = 0;
126*c2c26c8bSAndroid Build Coastguard Worker time_t now;
127*c2c26c8bSAndroid Build Coastguard Worker struct iname* if_tmp;
128*c2c26c8bSAndroid Build Coastguard Worker int piperead, pipefd[2], err_pipe[2];
129*c2c26c8bSAndroid Build Coastguard Worker struct passwd* ent_pw = NULL;
130*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
131*c2c26c8bSAndroid Build Coastguard Worker uid_t script_uid = 0;
132*c2c26c8bSAndroid Build Coastguard Worker gid_t script_gid = 0;
133*c2c26c8bSAndroid Build Coastguard Worker #endif
134*c2c26c8bSAndroid Build Coastguard Worker struct group* gp = NULL;
135*c2c26c8bSAndroid Build Coastguard Worker long i, max_fd = sysconf(_SC_OPEN_MAX);
136*c2c26c8bSAndroid Build Coastguard Worker char* baduser = NULL;
137*c2c26c8bSAndroid Build Coastguard Worker int log_err;
138*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_NETWORK)
139*c2c26c8bSAndroid Build Coastguard Worker cap_user_header_t hdr = NULL;
140*c2c26c8bSAndroid Build Coastguard Worker cap_user_data_t data = NULL;
141*c2c26c8bSAndroid Build Coastguard Worker #endif
142*c2c26c8bSAndroid Build Coastguard Worker
143*c2c26c8bSAndroid Build Coastguard Worker #ifdef LOCALEDIR
144*c2c26c8bSAndroid Build Coastguard Worker setlocale(LC_ALL, "");
145*c2c26c8bSAndroid Build Coastguard Worker bindtextdomain("dnsmasq", LOCALEDIR);
146*c2c26c8bSAndroid Build Coastguard Worker textdomain("dnsmasq");
147*c2c26c8bSAndroid Build Coastguard Worker #endif
148*c2c26c8bSAndroid Build Coastguard Worker
149*c2c26c8bSAndroid Build Coastguard Worker setupSignalHandling();
150*c2c26c8bSAndroid Build Coastguard Worker
151*c2c26c8bSAndroid Build Coastguard Worker umask(022); /* known umask, create leases and pid files as 0644 */
152*c2c26c8bSAndroid Build Coastguard Worker
153*c2c26c8bSAndroid Build Coastguard Worker read_opts(argc, argv, compile_opts);
154*c2c26c8bSAndroid Build Coastguard Worker
155*c2c26c8bSAndroid Build Coastguard Worker if (daemon->edns_pktsz < PACKETSZ) daemon->edns_pktsz = PACKETSZ;
156*c2c26c8bSAndroid Build Coastguard Worker daemon->packet_buff_sz =
157*c2c26c8bSAndroid Build Coastguard Worker daemon->edns_pktsz > DNSMASQ_PACKETSZ ? daemon->edns_pktsz : DNSMASQ_PACKETSZ;
158*c2c26c8bSAndroid Build Coastguard Worker daemon->packet = safe_malloc(daemon->packet_buff_sz);
159*c2c26c8bSAndroid Build Coastguard Worker
160*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
161*c2c26c8bSAndroid Build Coastguard Worker if (!daemon->lease_file) {
162*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) daemon->lease_file = LEASEFILE;
163*c2c26c8bSAndroid Build Coastguard Worker }
164*c2c26c8bSAndroid Build Coastguard Worker #endif
165*c2c26c8bSAndroid Build Coastguard Worker
166*c2c26c8bSAndroid Build Coastguard Worker closeUnwantedFileDescriptors();
167*c2c26c8bSAndroid Build Coastguard Worker
168*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETWORK
169*c2c26c8bSAndroid Build Coastguard Worker netlink_init();
170*c2c26c8bSAndroid Build Coastguard Worker #elif !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
171*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_NOWILD)) {
172*c2c26c8bSAndroid Build Coastguard Worker bind_fallback = 1;
173*c2c26c8bSAndroid Build Coastguard Worker daemon->options |= OPT_NOWILD;
174*c2c26c8bSAndroid Build Coastguard Worker }
175*c2c26c8bSAndroid Build Coastguard Worker #endif
176*c2c26c8bSAndroid Build Coastguard Worker
177*c2c26c8bSAndroid Build Coastguard Worker rand_init();
178*c2c26c8bSAndroid Build Coastguard Worker
179*c2c26c8bSAndroid Build Coastguard Worker now = dnsmasq_time();
180*c2c26c8bSAndroid Build Coastguard Worker
181*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
182*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) {
183*c2c26c8bSAndroid Build Coastguard Worker /* Note that order matters here, we must call lease_init before
184*c2c26c8bSAndroid Build Coastguard Worker creating any file descriptors which shouldn't be leaked
185*c2c26c8bSAndroid Build Coastguard Worker to the lease-script init process. */
186*c2c26c8bSAndroid Build Coastguard Worker lease_init(now);
187*c2c26c8bSAndroid Build Coastguard Worker dhcp_init();
188*c2c26c8bSAndroid Build Coastguard Worker }
189*c2c26c8bSAndroid Build Coastguard Worker #endif
190*c2c26c8bSAndroid Build Coastguard Worker
191*c2c26c8bSAndroid Build Coastguard Worker if (!enumerate_interfaces()) die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
192*c2c26c8bSAndroid Build Coastguard Worker
193*c2c26c8bSAndroid Build Coastguard Worker if (daemon->options & OPT_NOWILD) {
194*c2c26c8bSAndroid Build Coastguard Worker daemon->listeners = create_bound_listeners();
195*c2c26c8bSAndroid Build Coastguard Worker
196*c2c26c8bSAndroid Build Coastguard Worker for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
197*c2c26c8bSAndroid Build Coastguard Worker if (if_tmp->name && !if_tmp->used)
198*c2c26c8bSAndroid Build Coastguard Worker die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
199*c2c26c8bSAndroid Build Coastguard Worker
200*c2c26c8bSAndroid Build Coastguard Worker for (if_tmp = daemon->if_addrs; if_tmp; if_tmp = if_tmp->next)
201*c2c26c8bSAndroid Build Coastguard Worker if (!if_tmp->used) {
202*c2c26c8bSAndroid Build Coastguard Worker prettyprint_addr(&if_tmp->addr, daemon->namebuff);
203*c2c26c8bSAndroid Build Coastguard Worker die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
204*c2c26c8bSAndroid Build Coastguard Worker }
205*c2c26c8bSAndroid Build Coastguard Worker } else if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) &&
206*c2c26c8bSAndroid Build Coastguard Worker !(daemon->listeners = create_wildcard_listeners()))
207*c2c26c8bSAndroid Build Coastguard Worker die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
208*c2c26c8bSAndroid Build Coastguard Worker
209*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) cache_init();
210*c2c26c8bSAndroid Build Coastguard Worker
211*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) pre_allocate_sfds();
212*c2c26c8bSAndroid Build Coastguard Worker
213*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
214*c2c26c8bSAndroid Build Coastguard Worker /* Note getpwnam returns static storage */
215*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp && daemon->lease_change_command && daemon->scriptuser) {
216*c2c26c8bSAndroid Build Coastguard Worker if ((ent_pw = getpwnam(daemon->scriptuser))) {
217*c2c26c8bSAndroid Build Coastguard Worker script_uid = ent_pw->pw_uid;
218*c2c26c8bSAndroid Build Coastguard Worker script_gid = ent_pw->pw_gid;
219*c2c26c8bSAndroid Build Coastguard Worker } else
220*c2c26c8bSAndroid Build Coastguard Worker baduser = daemon->scriptuser;
221*c2c26c8bSAndroid Build Coastguard Worker }
222*c2c26c8bSAndroid Build Coastguard Worker #endif
223*c2c26c8bSAndroid Build Coastguard Worker
224*c2c26c8bSAndroid Build Coastguard Worker if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
225*c2c26c8bSAndroid Build Coastguard Worker baduser = daemon->username;
226*c2c26c8bSAndroid Build Coastguard Worker else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
227*c2c26c8bSAndroid Build Coastguard Worker baduser = daemon->groupname;
228*c2c26c8bSAndroid Build Coastguard Worker
229*c2c26c8bSAndroid Build Coastguard Worker if (baduser) die(_("unknown user or group: %s"), baduser, EC_BADCONF);
230*c2c26c8bSAndroid Build Coastguard Worker
231*c2c26c8bSAndroid Build Coastguard Worker /* implement group defaults, "dip" if available, or group associated with uid */
232*c2c26c8bSAndroid Build Coastguard Worker if (!daemon->group_set && !gp) {
233*c2c26c8bSAndroid Build Coastguard Worker if (!(gp = getgrnam(CHGRP)) && ent_pw) gp = getgrgid(ent_pw->pw_gid);
234*c2c26c8bSAndroid Build Coastguard Worker
235*c2c26c8bSAndroid Build Coastguard Worker /* for error message */
236*c2c26c8bSAndroid Build Coastguard Worker if (gp) daemon->groupname = gp->gr_name;
237*c2c26c8bSAndroid Build Coastguard Worker }
238*c2c26c8bSAndroid Build Coastguard Worker
239*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_NETWORK)
240*c2c26c8bSAndroid Build Coastguard Worker /* determine capability API version here, while we can still
241*c2c26c8bSAndroid Build Coastguard Worker call safe_malloc */
242*c2c26c8bSAndroid Build Coastguard Worker if (ent_pw && ent_pw->pw_uid != 0) {
243*c2c26c8bSAndroid Build Coastguard Worker int capsize = 1; /* for header version 1 */
244*c2c26c8bSAndroid Build Coastguard Worker hdr = safe_malloc(sizeof(*hdr));
245*c2c26c8bSAndroid Build Coastguard Worker
246*c2c26c8bSAndroid Build Coastguard Worker /* find version supported by kernel */
247*c2c26c8bSAndroid Build Coastguard Worker memset(hdr, 0, sizeof(*hdr));
248*c2c26c8bSAndroid Build Coastguard Worker capget(hdr, NULL);
249*c2c26c8bSAndroid Build Coastguard Worker
250*c2c26c8bSAndroid Build Coastguard Worker if (hdr->version != LINUX_CAPABILITY_VERSION_1) {
251*c2c26c8bSAndroid Build Coastguard Worker /* if unknown version, use largest supported version (3) */
252*c2c26c8bSAndroid Build Coastguard Worker if (hdr->version != LINUX_CAPABILITY_VERSION_2)
253*c2c26c8bSAndroid Build Coastguard Worker hdr->version = LINUX_CAPABILITY_VERSION_3;
254*c2c26c8bSAndroid Build Coastguard Worker capsize = 2;
255*c2c26c8bSAndroid Build Coastguard Worker }
256*c2c26c8bSAndroid Build Coastguard Worker
257*c2c26c8bSAndroid Build Coastguard Worker data = safe_malloc(sizeof(*data) * capsize);
258*c2c26c8bSAndroid Build Coastguard Worker memset(data, 0, sizeof(*data) * capsize);
259*c2c26c8bSAndroid Build Coastguard Worker }
260*c2c26c8bSAndroid Build Coastguard Worker #endif
261*c2c26c8bSAndroid Build Coastguard Worker
262*c2c26c8bSAndroid Build Coastguard Worker /* Use a pipe to carry signals and other events back to the event loop
263*c2c26c8bSAndroid Build Coastguard Worker in a race-free manner and another to carry errors to daemon-invoking process */
264*c2c26c8bSAndroid Build Coastguard Worker safe_pipe(pipefd, 1);
265*c2c26c8bSAndroid Build Coastguard Worker
266*c2c26c8bSAndroid Build Coastguard Worker piperead = pipefd[0];
267*c2c26c8bSAndroid Build Coastguard Worker pipewrite = pipefd[1];
268*c2c26c8bSAndroid Build Coastguard Worker /* prime the pipe to load stuff first time. */
269*c2c26c8bSAndroid Build Coastguard Worker send_event(pipewrite, EVENT_RELOAD, 0);
270*c2c26c8bSAndroid Build Coastguard Worker
271*c2c26c8bSAndroid Build Coastguard Worker err_pipe[1] = -1;
272*c2c26c8bSAndroid Build Coastguard Worker
273*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_DEBUG)) {
274*c2c26c8bSAndroid Build Coastguard Worker #ifndef __ANDROID__
275*c2c26c8bSAndroid Build Coastguard Worker int nullfd;
276*c2c26c8bSAndroid Build Coastguard Worker #endif
277*c2c26c8bSAndroid Build Coastguard Worker
278*c2c26c8bSAndroid Build Coastguard Worker /* The following code "daemonizes" the process.
279*c2c26c8bSAndroid Build Coastguard Worker See Stevens section 12.4 */
280*c2c26c8bSAndroid Build Coastguard Worker
281*c2c26c8bSAndroid Build Coastguard Worker if (chdir("/") != 0) die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
282*c2c26c8bSAndroid Build Coastguard Worker
283*c2c26c8bSAndroid Build Coastguard Worker #ifndef NO_FORK
284*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_NO_FORK)) {
285*c2c26c8bSAndroid Build Coastguard Worker pid_t pid;
286*c2c26c8bSAndroid Build Coastguard Worker
287*c2c26c8bSAndroid Build Coastguard Worker /* pipe to carry errors back to original process.
288*c2c26c8bSAndroid Build Coastguard Worker When startup is complete we close this and the process terminates. */
289*c2c26c8bSAndroid Build Coastguard Worker safe_pipe(err_pipe, 0);
290*c2c26c8bSAndroid Build Coastguard Worker
291*c2c26c8bSAndroid Build Coastguard Worker if ((pid = fork()) == -1) /* fd == -1 since we've not forked, never returns. */
292*c2c26c8bSAndroid Build Coastguard Worker send_event(-1, EVENT_FORK_ERR, errno);
293*c2c26c8bSAndroid Build Coastguard Worker
294*c2c26c8bSAndroid Build Coastguard Worker if (pid != 0) {
295*c2c26c8bSAndroid Build Coastguard Worker struct event_desc ev;
296*c2c26c8bSAndroid Build Coastguard Worker
297*c2c26c8bSAndroid Build Coastguard Worker /* close our copy of write-end */
298*c2c26c8bSAndroid Build Coastguard Worker close(err_pipe[1]);
299*c2c26c8bSAndroid Build Coastguard Worker
300*c2c26c8bSAndroid Build Coastguard Worker /* check for errors after the fork */
301*c2c26c8bSAndroid Build Coastguard Worker if (read_write(err_pipe[0], (unsigned char*) &ev, sizeof(ev), 1)) fatal_event(&ev);
302*c2c26c8bSAndroid Build Coastguard Worker
303*c2c26c8bSAndroid Build Coastguard Worker _exit(EC_GOOD);
304*c2c26c8bSAndroid Build Coastguard Worker }
305*c2c26c8bSAndroid Build Coastguard Worker
306*c2c26c8bSAndroid Build Coastguard Worker close(err_pipe[0]);
307*c2c26c8bSAndroid Build Coastguard Worker
308*c2c26c8bSAndroid Build Coastguard Worker /* NO calls to die() from here on. */
309*c2c26c8bSAndroid Build Coastguard Worker
310*c2c26c8bSAndroid Build Coastguard Worker setsid();
311*c2c26c8bSAndroid Build Coastguard Worker
312*c2c26c8bSAndroid Build Coastguard Worker if ((pid = fork()) == -1) send_event(err_pipe[1], EVENT_FORK_ERR, errno);
313*c2c26c8bSAndroid Build Coastguard Worker
314*c2c26c8bSAndroid Build Coastguard Worker if (pid != 0) _exit(0);
315*c2c26c8bSAndroid Build Coastguard Worker }
316*c2c26c8bSAndroid Build Coastguard Worker #endif
317*c2c26c8bSAndroid Build Coastguard Worker
318*c2c26c8bSAndroid Build Coastguard Worker /* write pidfile _after_ forking ! */
319*c2c26c8bSAndroid Build Coastguard Worker if (daemon->runfile) {
320*c2c26c8bSAndroid Build Coastguard Worker FILE* pidfile;
321*c2c26c8bSAndroid Build Coastguard Worker
322*c2c26c8bSAndroid Build Coastguard Worker /* only complain if started as root */
323*c2c26c8bSAndroid Build Coastguard Worker if ((pidfile = fopen(daemon->runfile, "w"))) {
324*c2c26c8bSAndroid Build Coastguard Worker fprintf(pidfile, "%d\n", (int) getpid());
325*c2c26c8bSAndroid Build Coastguard Worker fclose(pidfile);
326*c2c26c8bSAndroid Build Coastguard Worker } else if (getuid() == 0) {
327*c2c26c8bSAndroid Build Coastguard Worker send_event(err_pipe[1], EVENT_PIDFILE, errno);
328*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
329*c2c26c8bSAndroid Build Coastguard Worker }
330*c2c26c8bSAndroid Build Coastguard Worker }
331*c2c26c8bSAndroid Build Coastguard Worker
332*c2c26c8bSAndroid Build Coastguard Worker #ifndef __ANDROID__
333*c2c26c8bSAndroid Build Coastguard Worker /* open stdout etc to /dev/null */
334*c2c26c8bSAndroid Build Coastguard Worker nullfd = open("/dev/null", O_RDWR);
335*c2c26c8bSAndroid Build Coastguard Worker dup2(nullfd, STDOUT_FILENO);
336*c2c26c8bSAndroid Build Coastguard Worker dup2(nullfd, STDERR_FILENO);
337*c2c26c8bSAndroid Build Coastguard Worker dup2(nullfd, STDIN_FILENO);
338*c2c26c8bSAndroid Build Coastguard Worker close(nullfd);
339*c2c26c8bSAndroid Build Coastguard Worker #endif
340*c2c26c8bSAndroid Build Coastguard Worker }
341*c2c26c8bSAndroid Build Coastguard Worker
342*c2c26c8bSAndroid Build Coastguard Worker log_err = log_start(ent_pw, err_pipe[1]);
343*c2c26c8bSAndroid Build Coastguard Worker
344*c2c26c8bSAndroid Build Coastguard Worker /* if we are to run scripts, we need to fork a helper before dropping root. */
345*c2c26c8bSAndroid Build Coastguard Worker daemon->helperfd = -1;
346*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
347*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp && daemon->lease_change_command)
348*c2c26c8bSAndroid Build Coastguard Worker daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
349*c2c26c8bSAndroid Build Coastguard Worker #endif
350*c2c26c8bSAndroid Build Coastguard Worker
351*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_DEBUG) && getuid() == 0) {
352*c2c26c8bSAndroid Build Coastguard Worker int bad_capabilities = 0;
353*c2c26c8bSAndroid Build Coastguard Worker gid_t unused;
354*c2c26c8bSAndroid Build Coastguard Worker
355*c2c26c8bSAndroid Build Coastguard Worker /* remove all supplimentary groups */
356*c2c26c8bSAndroid Build Coastguard Worker if (gp && (setgroups(0, &unused) == -1 || setgid(gp->gr_gid) == -1)) {
357*c2c26c8bSAndroid Build Coastguard Worker send_event(err_pipe[1], EVENT_GROUP_ERR, errno);
358*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
359*c2c26c8bSAndroid Build Coastguard Worker }
360*c2c26c8bSAndroid Build Coastguard Worker
361*c2c26c8bSAndroid Build Coastguard Worker if (ent_pw && ent_pw->pw_uid != 0) {
362*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_NETWORK)
363*c2c26c8bSAndroid Build Coastguard Worker /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
364*c2c26c8bSAndroid Build Coastguard Worker CAP_NET_RAW (for icmp) if we're doing dhcp */
365*c2c26c8bSAndroid Build Coastguard Worker data->effective = data->permitted = data->inheritable =
366*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
367*c2c26c8bSAndroid Build Coastguard Worker (1 << CAP_NET_BIND_SERVICE) |
368*c2c26c8bSAndroid Build Coastguard Worker #endif
369*c2c26c8bSAndroid Build Coastguard Worker (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
370*c2c26c8bSAndroid Build Coastguard Worker
371*c2c26c8bSAndroid Build Coastguard Worker /* Tell kernel to not clear capabilities when dropping root */
372*c2c26c8bSAndroid Build Coastguard Worker if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
373*c2c26c8bSAndroid Build Coastguard Worker bad_capabilities = errno;
374*c2c26c8bSAndroid Build Coastguard Worker
375*c2c26c8bSAndroid Build Coastguard Worker #endif
376*c2c26c8bSAndroid Build Coastguard Worker
377*c2c26c8bSAndroid Build Coastguard Worker if (bad_capabilities != 0) {
378*c2c26c8bSAndroid Build Coastguard Worker send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities);
379*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
380*c2c26c8bSAndroid Build Coastguard Worker }
381*c2c26c8bSAndroid Build Coastguard Worker
382*c2c26c8bSAndroid Build Coastguard Worker /* finally drop root */
383*c2c26c8bSAndroid Build Coastguard Worker if (setuid(ent_pw->pw_uid) == -1) {
384*c2c26c8bSAndroid Build Coastguard Worker send_event(err_pipe[1], EVENT_USER_ERR, errno);
385*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
386*c2c26c8bSAndroid Build Coastguard Worker }
387*c2c26c8bSAndroid Build Coastguard Worker
388*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETWORK
389*c2c26c8bSAndroid Build Coastguard Worker data->effective = data->permitted =
390*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
391*c2c26c8bSAndroid Build Coastguard Worker (1 << CAP_NET_BIND_SERVICE) |
392*c2c26c8bSAndroid Build Coastguard Worker #endif
393*c2c26c8bSAndroid Build Coastguard Worker (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
394*c2c26c8bSAndroid Build Coastguard Worker data->inheritable = 0;
395*c2c26c8bSAndroid Build Coastguard Worker
396*c2c26c8bSAndroid Build Coastguard Worker /* lose the setuid and setgid capbilities */
397*c2c26c8bSAndroid Build Coastguard Worker if (capset(hdr, data) == -1) {
398*c2c26c8bSAndroid Build Coastguard Worker send_event(err_pipe[1], EVENT_CAP_ERR, errno);
399*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
400*c2c26c8bSAndroid Build Coastguard Worker }
401*c2c26c8bSAndroid Build Coastguard Worker #endif
402*c2c26c8bSAndroid Build Coastguard Worker }
403*c2c26c8bSAndroid Build Coastguard Worker }
404*c2c26c8bSAndroid Build Coastguard Worker
405*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETWORK
406*c2c26c8bSAndroid Build Coastguard Worker if (daemon->options & OPT_DEBUG) prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
407*c2c26c8bSAndroid Build Coastguard Worker #endif
408*c2c26c8bSAndroid Build Coastguard Worker
409*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port == 0)
410*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
411*c2c26c8bSAndroid Build Coastguard Worker else if (daemon->cachesize != 0)
412*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
413*c2c26c8bSAndroid Build Coastguard Worker else
414*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
415*c2c26c8bSAndroid Build Coastguard Worker
416*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
417*c2c26c8bSAndroid Build Coastguard Worker
418*c2c26c8bSAndroid Build Coastguard Worker if (log_err != 0)
419*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), daemon->log_file,
420*c2c26c8bSAndroid Build Coastguard Worker strerror(log_err));
421*c2c26c8bSAndroid Build Coastguard Worker
422*c2c26c8bSAndroid Build Coastguard Worker if (bind_fallback)
423*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
424*c2c26c8bSAndroid Build Coastguard Worker
425*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_NOWILD))
426*c2c26c8bSAndroid Build Coastguard Worker for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
427*c2c26c8bSAndroid Build Coastguard Worker if (if_tmp->name && !if_tmp->used)
428*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"),
429*c2c26c8bSAndroid Build Coastguard Worker if_tmp->name);
430*c2c26c8bSAndroid Build Coastguard Worker
431*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0 && (daemon->options & OPT_NO_RESOLV)) {
432*c2c26c8bSAndroid Build Coastguard Worker if (daemon->resolv_files && !daemon->resolv_files->is_default)
433*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING,
434*c2c26c8bSAndroid Build Coastguard Worker _("warning: ignoring resolv-file flag because no-resolv is set"));
435*c2c26c8bSAndroid Build Coastguard Worker daemon->resolv_files = NULL;
436*c2c26c8bSAndroid Build Coastguard Worker if (!daemon->servers) my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
437*c2c26c8bSAndroid Build Coastguard Worker }
438*c2c26c8bSAndroid Build Coastguard Worker
439*c2c26c8bSAndroid Build Coastguard Worker if (daemon->max_logs != 0)
440*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"),
441*c2c26c8bSAndroid Build Coastguard Worker daemon->max_logs);
442*c2c26c8bSAndroid Build Coastguard Worker
443*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
444*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) {
445*c2c26c8bSAndroid Build Coastguard Worker struct dhcp_context* dhcp_tmp;
446*c2c26c8bSAndroid Build Coastguard Worker
447*c2c26c8bSAndroid Build Coastguard Worker for (dhcp_tmp = daemon->dhcp; dhcp_tmp; dhcp_tmp = dhcp_tmp->next) {
448*c2c26c8bSAndroid Build Coastguard Worker prettyprint_time(daemon->dhcp_buff2, dhcp_tmp->lease_time);
449*c2c26c8bSAndroid Build Coastguard Worker strcpy(daemon->dhcp_buff, inet_ntoa(dhcp_tmp->start));
450*c2c26c8bSAndroid Build Coastguard Worker my_syslog(MS_DHCP | LOG_INFO,
451*c2c26c8bSAndroid Build Coastguard Worker (dhcp_tmp->flags & CONTEXT_STATIC)
452*c2c26c8bSAndroid Build Coastguard Worker ? _("DHCP, static leases only on %.0s%s, lease time %s")
453*c2c26c8bSAndroid Build Coastguard Worker : (dhcp_tmp->flags & CONTEXT_PROXY)
454*c2c26c8bSAndroid Build Coastguard Worker ? _("DHCP, proxy on subnet %.0s%s%.0s")
455*c2c26c8bSAndroid Build Coastguard Worker : _("DHCP, IP range %s -- %s, lease time %s"),
456*c2c26c8bSAndroid Build Coastguard Worker daemon->dhcp_buff, inet_ntoa(dhcp_tmp->end), daemon->dhcp_buff2);
457*c2c26c8bSAndroid Build Coastguard Worker }
458*c2c26c8bSAndroid Build Coastguard Worker }
459*c2c26c8bSAndroid Build Coastguard Worker #endif
460*c2c26c8bSAndroid Build Coastguard Worker
461*c2c26c8bSAndroid Build Coastguard Worker /* finished start-up - release original process */
462*c2c26c8bSAndroid Build Coastguard Worker if (err_pipe[1] != -1) close(err_pipe[1]);
463*c2c26c8bSAndroid Build Coastguard Worker
464*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) check_servers();
465*c2c26c8bSAndroid Build Coastguard Worker
466*c2c26c8bSAndroid Build Coastguard Worker pid = getpid();
467*c2c26c8bSAndroid Build Coastguard Worker
468*c2c26c8bSAndroid Build Coastguard Worker while (1) {
469*c2c26c8bSAndroid Build Coastguard Worker int maxfd = -1;
470*c2c26c8bSAndroid Build Coastguard Worker struct timeval t, *tp = NULL;
471*c2c26c8bSAndroid Build Coastguard Worker fd_set rset, wset, eset;
472*c2c26c8bSAndroid Build Coastguard Worker
473*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&rset);
474*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&wset);
475*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&eset);
476*c2c26c8bSAndroid Build Coastguard Worker
477*c2c26c8bSAndroid Build Coastguard Worker /* if we are out of resources, find how long we have to wait
478*c2c26c8bSAndroid Build Coastguard Worker for some to come free, we'll loop around then and restart
479*c2c26c8bSAndroid Build Coastguard Worker listening for queries */
480*c2c26c8bSAndroid Build Coastguard Worker if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0) {
481*c2c26c8bSAndroid Build Coastguard Worker t.tv_usec = 0;
482*c2c26c8bSAndroid Build Coastguard Worker tp = &t;
483*c2c26c8bSAndroid Build Coastguard Worker }
484*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
485*c2c26c8bSAndroid Build Coastguard Worker set_android_listeners(&rset, &maxfd);
486*c2c26c8bSAndroid Build Coastguard Worker #endif
487*c2c26c8bSAndroid Build Coastguard Worker
488*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
489*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) {
490*c2c26c8bSAndroid Build Coastguard Worker FD_SET(daemon->dhcpfd, &rset);
491*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(daemon->dhcpfd, &maxfd);
492*c2c26c8bSAndroid Build Coastguard Worker }
493*c2c26c8bSAndroid Build Coastguard Worker #endif
494*c2c26c8bSAndroid Build Coastguard Worker
495*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETWORK
496*c2c26c8bSAndroid Build Coastguard Worker FD_SET(daemon->netlinkfd, &rset);
497*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(daemon->netlinkfd, &maxfd);
498*c2c26c8bSAndroid Build Coastguard Worker #endif
499*c2c26c8bSAndroid Build Coastguard Worker
500*c2c26c8bSAndroid Build Coastguard Worker FD_SET(piperead, &rset);
501*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(piperead, &maxfd);
502*c2c26c8bSAndroid Build Coastguard Worker
503*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
504*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_SCRIPT
505*c2c26c8bSAndroid Build Coastguard Worker while (helper_buf_empty() && do_script_run(now))
506*c2c26c8bSAndroid Build Coastguard Worker ;
507*c2c26c8bSAndroid Build Coastguard Worker
508*c2c26c8bSAndroid Build Coastguard Worker if (!helper_buf_empty()) {
509*c2c26c8bSAndroid Build Coastguard Worker FD_SET(daemon->helperfd, &wset);
510*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(daemon->helperfd, &maxfd);
511*c2c26c8bSAndroid Build Coastguard Worker }
512*c2c26c8bSAndroid Build Coastguard Worker #else
513*c2c26c8bSAndroid Build Coastguard Worker /* need this for other side-effects */
514*c2c26c8bSAndroid Build Coastguard Worker while (do_script_run(now))
515*c2c26c8bSAndroid Build Coastguard Worker ;
516*c2c26c8bSAndroid Build Coastguard Worker #endif
517*c2c26c8bSAndroid Build Coastguard Worker #endif
518*c2c26c8bSAndroid Build Coastguard Worker
519*c2c26c8bSAndroid Build Coastguard Worker /* must do this just before select(), when we know no
520*c2c26c8bSAndroid Build Coastguard Worker more calls to my_syslog() can occur */
521*c2c26c8bSAndroid Build Coastguard Worker set_log_writer(&wset, &maxfd);
522*c2c26c8bSAndroid Build Coastguard Worker
523*c2c26c8bSAndroid Build Coastguard Worker if (select(maxfd + 1, &rset, &wset, &eset, tp) < 0) {
524*c2c26c8bSAndroid Build Coastguard Worker /* otherwise undefined after error */
525*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&rset);
526*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&wset);
527*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&eset);
528*c2c26c8bSAndroid Build Coastguard Worker }
529*c2c26c8bSAndroid Build Coastguard Worker
530*c2c26c8bSAndroid Build Coastguard Worker now = dnsmasq_time();
531*c2c26c8bSAndroid Build Coastguard Worker
532*c2c26c8bSAndroid Build Coastguard Worker check_log_writer(&wset);
533*c2c26c8bSAndroid Build Coastguard Worker
534*c2c26c8bSAndroid Build Coastguard Worker /* Check for changes to resolv files once per second max. */
535*c2c26c8bSAndroid Build Coastguard Worker /* Don't go silent for long periods if the clock goes backwards. */
536*c2c26c8bSAndroid Build Coastguard Worker if (daemon->last_resolv == 0 || difftime(now, daemon->last_resolv) > 1.0 ||
537*c2c26c8bSAndroid Build Coastguard Worker difftime(now, daemon->last_resolv) < -1.0) {
538*c2c26c8bSAndroid Build Coastguard Worker daemon->last_resolv = now;
539*c2c26c8bSAndroid Build Coastguard Worker
540*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL)) poll_resolv();
541*c2c26c8bSAndroid Build Coastguard Worker }
542*c2c26c8bSAndroid Build Coastguard Worker
543*c2c26c8bSAndroid Build Coastguard Worker if (FD_ISSET(piperead, &rset)) async_event(piperead, now);
544*c2c26c8bSAndroid Build Coastguard Worker
545*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_LINUX_NETWORK
546*c2c26c8bSAndroid Build Coastguard Worker if (FD_ISSET(daemon->netlinkfd, &rset)) netlink_multicast();
547*c2c26c8bSAndroid Build Coastguard Worker #endif
548*c2c26c8bSAndroid Build Coastguard Worker
549*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
550*c2c26c8bSAndroid Build Coastguard Worker check_android_listeners(&rset);
551*c2c26c8bSAndroid Build Coastguard Worker #endif
552*c2c26c8bSAndroid Build Coastguard Worker
553*c2c26c8bSAndroid Build Coastguard Worker check_dns_listeners(&rset, now);
554*c2c26c8bSAndroid Build Coastguard Worker
555*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
556*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp && FD_ISSET(daemon->dhcpfd, &rset)) dhcp_packet(now);
557*c2c26c8bSAndroid Build Coastguard Worker
558*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_SCRIPT
559*c2c26c8bSAndroid Build Coastguard Worker if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset)) helper_write();
560*c2c26c8bSAndroid Build Coastguard Worker #endif
561*c2c26c8bSAndroid Build Coastguard Worker #endif
562*c2c26c8bSAndroid Build Coastguard Worker }
563*c2c26c8bSAndroid Build Coastguard Worker }
564*c2c26c8bSAndroid Build Coastguard Worker
sig_handler(int sig)565*c2c26c8bSAndroid Build Coastguard Worker static void sig_handler(int sig) {
566*c2c26c8bSAndroid Build Coastguard Worker if (pid == 0) {
567*c2c26c8bSAndroid Build Coastguard Worker /* ignore anything other than TERM during startup
568*c2c26c8bSAndroid Build Coastguard Worker and in helper proc. (helper ignore TERM too) */
569*c2c26c8bSAndroid Build Coastguard Worker if (sig == SIGTERM) exit(EC_MISC);
570*c2c26c8bSAndroid Build Coastguard Worker } else if (pid != getpid()) {
571*c2c26c8bSAndroid Build Coastguard Worker /* alarm is used to kill TCP children after a fixed time. */
572*c2c26c8bSAndroid Build Coastguard Worker if (sig == SIGALRM) _exit(0);
573*c2c26c8bSAndroid Build Coastguard Worker } else {
574*c2c26c8bSAndroid Build Coastguard Worker /* main process */
575*c2c26c8bSAndroid Build Coastguard Worker const int errsave = errno;
576*c2c26c8bSAndroid Build Coastguard Worker int event;
577*c2c26c8bSAndroid Build Coastguard Worker
578*c2c26c8bSAndroid Build Coastguard Worker if (sig == SIGHUP)
579*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_RELOAD;
580*c2c26c8bSAndroid Build Coastguard Worker else if (sig == SIGCHLD)
581*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_CHILD;
582*c2c26c8bSAndroid Build Coastguard Worker else if (sig == SIGALRM)
583*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_ALARM;
584*c2c26c8bSAndroid Build Coastguard Worker else if (sig == SIGTERM)
585*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_TERM;
586*c2c26c8bSAndroid Build Coastguard Worker else if (sig == SIGUSR1)
587*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_DUMP;
588*c2c26c8bSAndroid Build Coastguard Worker else if (sig == SIGUSR2)
589*c2c26c8bSAndroid Build Coastguard Worker event = EVENT_REOPEN;
590*c2c26c8bSAndroid Build Coastguard Worker else
591*c2c26c8bSAndroid Build Coastguard Worker return;
592*c2c26c8bSAndroid Build Coastguard Worker
593*c2c26c8bSAndroid Build Coastguard Worker send_event(pipewrite, event, 0);
594*c2c26c8bSAndroid Build Coastguard Worker errno = errsave;
595*c2c26c8bSAndroid Build Coastguard Worker }
596*c2c26c8bSAndroid Build Coastguard Worker }
597*c2c26c8bSAndroid Build Coastguard Worker
send_event(int fd,int event,int data)598*c2c26c8bSAndroid Build Coastguard Worker void send_event(int fd, int event, int data) {
599*c2c26c8bSAndroid Build Coastguard Worker struct event_desc ev;
600*c2c26c8bSAndroid Build Coastguard Worker
601*c2c26c8bSAndroid Build Coastguard Worker ev.event = event;
602*c2c26c8bSAndroid Build Coastguard Worker ev.data = data;
603*c2c26c8bSAndroid Build Coastguard Worker
604*c2c26c8bSAndroid Build Coastguard Worker /* error pipe, debug mode. */
605*c2c26c8bSAndroid Build Coastguard Worker if (fd == -1)
606*c2c26c8bSAndroid Build Coastguard Worker fatal_event(&ev);
607*c2c26c8bSAndroid Build Coastguard Worker else
608*c2c26c8bSAndroid Build Coastguard Worker /* pipe is non-blocking and struct event_desc is smaller than
609*c2c26c8bSAndroid Build Coastguard Worker PIPE_BUF, so this either fails or writes everything */
610*c2c26c8bSAndroid Build Coastguard Worker while (write(fd, &ev, sizeof(ev)) == -1 && errno == EINTR)
611*c2c26c8bSAndroid Build Coastguard Worker ;
612*c2c26c8bSAndroid Build Coastguard Worker }
613*c2c26c8bSAndroid Build Coastguard Worker
fatal_event(struct event_desc * ev)614*c2c26c8bSAndroid Build Coastguard Worker static void fatal_event(struct event_desc* ev) {
615*c2c26c8bSAndroid Build Coastguard Worker errno = ev->data;
616*c2c26c8bSAndroid Build Coastguard Worker
617*c2c26c8bSAndroid Build Coastguard Worker switch (ev->event) {
618*c2c26c8bSAndroid Build Coastguard Worker case EVENT_DIE:
619*c2c26c8bSAndroid Build Coastguard Worker exit(0);
620*c2c26c8bSAndroid Build Coastguard Worker
621*c2c26c8bSAndroid Build Coastguard Worker case EVENT_FORK_ERR:
622*c2c26c8bSAndroid Build Coastguard Worker die(_("cannot fork into background: %s"), NULL, EC_MISC);
623*c2c26c8bSAndroid Build Coastguard Worker
624*c2c26c8bSAndroid Build Coastguard Worker case EVENT_PIPE_ERR:
625*c2c26c8bSAndroid Build Coastguard Worker die(_("failed to create helper: %s"), NULL, EC_MISC);
626*c2c26c8bSAndroid Build Coastguard Worker
627*c2c26c8bSAndroid Build Coastguard Worker case EVENT_CAP_ERR:
628*c2c26c8bSAndroid Build Coastguard Worker die(_("setting capabilities failed: %s"), NULL, EC_MISC);
629*c2c26c8bSAndroid Build Coastguard Worker
630*c2c26c8bSAndroid Build Coastguard Worker case EVENT_USER_ERR:
631*c2c26c8bSAndroid Build Coastguard Worker case EVENT_HUSER_ERR:
632*c2c26c8bSAndroid Build Coastguard Worker die(_("failed to change user-id to %s: %s"),
633*c2c26c8bSAndroid Build Coastguard Worker ev->event == EVENT_USER_ERR ? daemon->username : daemon->scriptuser, EC_MISC);
634*c2c26c8bSAndroid Build Coastguard Worker
635*c2c26c8bSAndroid Build Coastguard Worker case EVENT_GROUP_ERR:
636*c2c26c8bSAndroid Build Coastguard Worker die(_("failed to change group-id to %s: %s"), daemon->groupname, EC_MISC);
637*c2c26c8bSAndroid Build Coastguard Worker
638*c2c26c8bSAndroid Build Coastguard Worker case EVENT_PIDFILE:
639*c2c26c8bSAndroid Build Coastguard Worker die(_("failed to open pidfile %s: %s"), daemon->runfile, EC_FILE);
640*c2c26c8bSAndroid Build Coastguard Worker
641*c2c26c8bSAndroid Build Coastguard Worker case EVENT_LOG_ERR:
642*c2c26c8bSAndroid Build Coastguard Worker die(_("cannot open %s: %s"), daemon->log_file ? daemon->log_file : "log", EC_FILE);
643*c2c26c8bSAndroid Build Coastguard Worker }
644*c2c26c8bSAndroid Build Coastguard Worker }
645*c2c26c8bSAndroid Build Coastguard Worker
async_event(int pipe,time_t now)646*c2c26c8bSAndroid Build Coastguard Worker static void async_event(int pipe, time_t now) {
647*c2c26c8bSAndroid Build Coastguard Worker pid_t p;
648*c2c26c8bSAndroid Build Coastguard Worker struct event_desc ev;
649*c2c26c8bSAndroid Build Coastguard Worker int i;
650*c2c26c8bSAndroid Build Coastguard Worker
651*c2c26c8bSAndroid Build Coastguard Worker if (read_write(pipe, (unsigned char*) &ev, sizeof(ev), 1)) switch (ev.event) {
652*c2c26c8bSAndroid Build Coastguard Worker case EVENT_RELOAD:
653*c2c26c8bSAndroid Build Coastguard Worker clear_cache_and_reload(now);
654*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0 && daemon->resolv_files && (daemon->options & OPT_NO_POLL)) {
655*c2c26c8bSAndroid Build Coastguard Worker reload_servers(daemon->resolv_files->name);
656*c2c26c8bSAndroid Build Coastguard Worker check_servers();
657*c2c26c8bSAndroid Build Coastguard Worker }
658*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
659*c2c26c8bSAndroid Build Coastguard Worker rerun_scripts();
660*c2c26c8bSAndroid Build Coastguard Worker #endif
661*c2c26c8bSAndroid Build Coastguard Worker break;
662*c2c26c8bSAndroid Build Coastguard Worker
663*c2c26c8bSAndroid Build Coastguard Worker case EVENT_DUMP:
664*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) dump_cache(now);
665*c2c26c8bSAndroid Build Coastguard Worker break;
666*c2c26c8bSAndroid Build Coastguard Worker
667*c2c26c8bSAndroid Build Coastguard Worker case EVENT_ALARM:
668*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
669*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) {
670*c2c26c8bSAndroid Build Coastguard Worker lease_prune(NULL, now);
671*c2c26c8bSAndroid Build Coastguard Worker lease_update_file(now);
672*c2c26c8bSAndroid Build Coastguard Worker }
673*c2c26c8bSAndroid Build Coastguard Worker #endif
674*c2c26c8bSAndroid Build Coastguard Worker break;
675*c2c26c8bSAndroid Build Coastguard Worker
676*c2c26c8bSAndroid Build Coastguard Worker case EVENT_CHILD:
677*c2c26c8bSAndroid Build Coastguard Worker /* See Stevens 5.10 */
678*c2c26c8bSAndroid Build Coastguard Worker while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
679*c2c26c8bSAndroid Build Coastguard Worker if (p == -1) {
680*c2c26c8bSAndroid Build Coastguard Worker if (errno != EINTR) break;
681*c2c26c8bSAndroid Build Coastguard Worker } else
682*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < MAX_PROCS; i++)
683*c2c26c8bSAndroid Build Coastguard Worker if (daemon->tcp_pids[i] == p) daemon->tcp_pids[i] = 0;
684*c2c26c8bSAndroid Build Coastguard Worker break;
685*c2c26c8bSAndroid Build Coastguard Worker
686*c2c26c8bSAndroid Build Coastguard Worker case EVENT_KILLED:
687*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("child process killed by signal %d"), ev.data);
688*c2c26c8bSAndroid Build Coastguard Worker break;
689*c2c26c8bSAndroid Build Coastguard Worker
690*c2c26c8bSAndroid Build Coastguard Worker case EVENT_EXITED:
691*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("child process exited with status %d"), ev.data);
692*c2c26c8bSAndroid Build Coastguard Worker break;
693*c2c26c8bSAndroid Build Coastguard Worker
694*c2c26c8bSAndroid Build Coastguard Worker case EVENT_EXEC_ERR:
695*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, _("failed to execute %s: %s"), daemon->lease_change_command,
696*c2c26c8bSAndroid Build Coastguard Worker strerror(ev.data));
697*c2c26c8bSAndroid Build Coastguard Worker break;
698*c2c26c8bSAndroid Build Coastguard Worker
699*c2c26c8bSAndroid Build Coastguard Worker /* necessary for fatal errors in helper */
700*c2c26c8bSAndroid Build Coastguard Worker case EVENT_HUSER_ERR:
701*c2c26c8bSAndroid Build Coastguard Worker case EVENT_DIE:
702*c2c26c8bSAndroid Build Coastguard Worker fatal_event(&ev);
703*c2c26c8bSAndroid Build Coastguard Worker break;
704*c2c26c8bSAndroid Build Coastguard Worker
705*c2c26c8bSAndroid Build Coastguard Worker case EVENT_REOPEN:
706*c2c26c8bSAndroid Build Coastguard Worker /* Note: this may leave TCP-handling processes with the old file still open.
707*c2c26c8bSAndroid Build Coastguard Worker Since any such process will die in CHILD_LIFETIME or probably much sooner,
708*c2c26c8bSAndroid Build Coastguard Worker we leave them logging to the old file. */
709*c2c26c8bSAndroid Build Coastguard Worker if (daemon->log_file != NULL) log_reopen(daemon->log_file);
710*c2c26c8bSAndroid Build Coastguard Worker break;
711*c2c26c8bSAndroid Build Coastguard Worker
712*c2c26c8bSAndroid Build Coastguard Worker case EVENT_TERM:
713*c2c26c8bSAndroid Build Coastguard Worker /* Knock all our children on the head. */
714*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < MAX_PROCS; i++)
715*c2c26c8bSAndroid Build Coastguard Worker if (daemon->tcp_pids[i] != 0) kill(daemon->tcp_pids[i], SIGALRM);
716*c2c26c8bSAndroid Build Coastguard Worker
717*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_DHCP) && defined(HAVE_SCRIPT)
718*c2c26c8bSAndroid Build Coastguard Worker /* handle pending lease transitions */
719*c2c26c8bSAndroid Build Coastguard Worker if (daemon->helperfd != -1) {
720*c2c26c8bSAndroid Build Coastguard Worker /* block in writes until all done */
721*c2c26c8bSAndroid Build Coastguard Worker if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
722*c2c26c8bSAndroid Build Coastguard Worker fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK);
723*c2c26c8bSAndroid Build Coastguard Worker do {
724*c2c26c8bSAndroid Build Coastguard Worker helper_write();
725*c2c26c8bSAndroid Build Coastguard Worker } while (!helper_buf_empty() || do_script_run(now));
726*c2c26c8bSAndroid Build Coastguard Worker close(daemon->helperfd);
727*c2c26c8bSAndroid Build Coastguard Worker }
728*c2c26c8bSAndroid Build Coastguard Worker #endif
729*c2c26c8bSAndroid Build Coastguard Worker
730*c2c26c8bSAndroid Build Coastguard Worker if (daemon->lease_stream) fclose(daemon->lease_stream);
731*c2c26c8bSAndroid Build Coastguard Worker
732*c2c26c8bSAndroid Build Coastguard Worker if (daemon->runfile) unlink(daemon->runfile);
733*c2c26c8bSAndroid Build Coastguard Worker
734*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
735*c2c26c8bSAndroid Build Coastguard Worker flush_log();
736*c2c26c8bSAndroid Build Coastguard Worker exit(EC_GOOD);
737*c2c26c8bSAndroid Build Coastguard Worker }
738*c2c26c8bSAndroid Build Coastguard Worker }
739*c2c26c8bSAndroid Build Coastguard Worker
poll_resolv()740*c2c26c8bSAndroid Build Coastguard Worker static void poll_resolv() {
741*c2c26c8bSAndroid Build Coastguard Worker struct resolvc *res, *latest;
742*c2c26c8bSAndroid Build Coastguard Worker struct stat statbuf;
743*c2c26c8bSAndroid Build Coastguard Worker time_t last_change = 0;
744*c2c26c8bSAndroid Build Coastguard Worker /* There may be more than one possible file.
745*c2c26c8bSAndroid Build Coastguard Worker Go through and find the one which changed _last_.
746*c2c26c8bSAndroid Build Coastguard Worker Warn of any which can't be read. */
747*c2c26c8bSAndroid Build Coastguard Worker for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
748*c2c26c8bSAndroid Build Coastguard Worker if (stat(res->name, &statbuf) == -1) {
749*c2c26c8bSAndroid Build Coastguard Worker if (!res->logged)
750*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
751*c2c26c8bSAndroid Build Coastguard Worker res->logged = 1;
752*c2c26c8bSAndroid Build Coastguard Worker } else {
753*c2c26c8bSAndroid Build Coastguard Worker res->logged = 0;
754*c2c26c8bSAndroid Build Coastguard Worker if (statbuf.st_mtime != res->mtime) {
755*c2c26c8bSAndroid Build Coastguard Worker res->mtime = statbuf.st_mtime;
756*c2c26c8bSAndroid Build Coastguard Worker if (difftime(statbuf.st_mtime, last_change) > 0.0) {
757*c2c26c8bSAndroid Build Coastguard Worker last_change = statbuf.st_mtime;
758*c2c26c8bSAndroid Build Coastguard Worker latest = res;
759*c2c26c8bSAndroid Build Coastguard Worker }
760*c2c26c8bSAndroid Build Coastguard Worker }
761*c2c26c8bSAndroid Build Coastguard Worker }
762*c2c26c8bSAndroid Build Coastguard Worker
763*c2c26c8bSAndroid Build Coastguard Worker if (latest) {
764*c2c26c8bSAndroid Build Coastguard Worker static int warned = 0;
765*c2c26c8bSAndroid Build Coastguard Worker if (reload_servers(latest->name)) {
766*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_INFO, _("reading %s"), latest->name);
767*c2c26c8bSAndroid Build Coastguard Worker warned = 0;
768*c2c26c8bSAndroid Build Coastguard Worker check_servers();
769*c2c26c8bSAndroid Build Coastguard Worker if (daemon->options & OPT_RELOAD) cache_reload();
770*c2c26c8bSAndroid Build Coastguard Worker } else {
771*c2c26c8bSAndroid Build Coastguard Worker latest->mtime = 0;
772*c2c26c8bSAndroid Build Coastguard Worker if (!warned) {
773*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
774*c2c26c8bSAndroid Build Coastguard Worker warned = 1;
775*c2c26c8bSAndroid Build Coastguard Worker }
776*c2c26c8bSAndroid Build Coastguard Worker }
777*c2c26c8bSAndroid Build Coastguard Worker }
778*c2c26c8bSAndroid Build Coastguard Worker }
779*c2c26c8bSAndroid Build Coastguard Worker
clear_cache_and_reload(time_t now)780*c2c26c8bSAndroid Build Coastguard Worker void clear_cache_and_reload(time_t now) {
781*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) cache_reload();
782*c2c26c8bSAndroid Build Coastguard Worker
783*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
784*c2c26c8bSAndroid Build Coastguard Worker if (daemon->dhcp) {
785*c2c26c8bSAndroid Build Coastguard Worker reread_dhcp();
786*c2c26c8bSAndroid Build Coastguard Worker dhcp_update_configs(daemon->dhcp_conf);
787*c2c26c8bSAndroid Build Coastguard Worker check_dhcp_hosts(0);
788*c2c26c8bSAndroid Build Coastguard Worker lease_update_from_configs();
789*c2c26c8bSAndroid Build Coastguard Worker lease_update_file(now);
790*c2c26c8bSAndroid Build Coastguard Worker lease_update_dns();
791*c2c26c8bSAndroid Build Coastguard Worker }
792*c2c26c8bSAndroid Build Coastguard Worker #endif
793*c2c26c8bSAndroid Build Coastguard Worker }
794*c2c26c8bSAndroid Build Coastguard Worker
795*c2c26c8bSAndroid Build Coastguard Worker #ifdef __ANDROID__
796*c2c26c8bSAndroid Build Coastguard Worker
set_android_listeners(fd_set * set,int * maxfdp)797*c2c26c8bSAndroid Build Coastguard Worker static int set_android_listeners(fd_set* set, int* maxfdp) {
798*c2c26c8bSAndroid Build Coastguard Worker FD_SET(STDIN_FILENO, set);
799*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(STDIN_FILENO, maxfdp);
800*c2c26c8bSAndroid Build Coastguard Worker return 0;
801*c2c26c8bSAndroid Build Coastguard Worker }
802*c2c26c8bSAndroid Build Coastguard Worker
check_android_listeners(fd_set * set)803*c2c26c8bSAndroid Build Coastguard Worker static int check_android_listeners(fd_set* set) {
804*c2c26c8bSAndroid Build Coastguard Worker int retcode = 0;
805*c2c26c8bSAndroid Build Coastguard Worker if (FD_ISSET(STDIN_FILENO, set)) {
806*c2c26c8bSAndroid Build Coastguard Worker char buffer[1024];
807*c2c26c8bSAndroid Build Coastguard Worker int rc;
808*c2c26c8bSAndroid Build Coastguard Worker int consumed = 0;
809*c2c26c8bSAndroid Build Coastguard Worker
810*c2c26c8bSAndroid Build Coastguard Worker if ((rc = read(STDIN_FILENO, buffer, sizeof(buffer) - 1)) < 0) {
811*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, _("Error reading from stdin (%s)"), strerror(errno));
812*c2c26c8bSAndroid Build Coastguard Worker return -1;
813*c2c26c8bSAndroid Build Coastguard Worker }
814*c2c26c8bSAndroid Build Coastguard Worker buffer[rc] = '\0';
815*c2c26c8bSAndroid Build Coastguard Worker while (consumed < rc) {
816*c2c26c8bSAndroid Build Coastguard Worker char* cmd;
817*c2c26c8bSAndroid Build Coastguard Worker char* current_cmd = &buffer[consumed];
818*c2c26c8bSAndroid Build Coastguard Worker char* params = current_cmd;
819*c2c26c8bSAndroid Build Coastguard Worker int len = strlen(current_cmd);
820*c2c26c8bSAndroid Build Coastguard Worker
821*c2c26c8bSAndroid Build Coastguard Worker cmd = strsep(¶ms, "|");
822*c2c26c8bSAndroid Build Coastguard Worker if (!strcmp(cmd, "update_dns")) {
823*c2c26c8bSAndroid Build Coastguard Worker if (params != NULL) {
824*c2c26c8bSAndroid Build Coastguard Worker set_servers(params);
825*c2c26c8bSAndroid Build Coastguard Worker check_servers();
826*c2c26c8bSAndroid Build Coastguard Worker } else {
827*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, _("Misformatted msg '%s'"), current_cmd);
828*c2c26c8bSAndroid Build Coastguard Worker retcode = -1;
829*c2c26c8bSAndroid Build Coastguard Worker }
830*c2c26c8bSAndroid Build Coastguard Worker } else if (!strcmp(cmd, "update_ifaces")) {
831*c2c26c8bSAndroid Build Coastguard Worker if (params != NULL) {
832*c2c26c8bSAndroid Build Coastguard Worker set_interfaces(params);
833*c2c26c8bSAndroid Build Coastguard Worker } else {
834*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, _("Misformatted msg '%s'"), current_cmd);
835*c2c26c8bSAndroid Build Coastguard Worker retcode = -1;
836*c2c26c8bSAndroid Build Coastguard Worker }
837*c2c26c8bSAndroid Build Coastguard Worker } else {
838*c2c26c8bSAndroid Build Coastguard Worker my_syslog(LOG_ERR, _("Unknown cmd '%s'"), cmd);
839*c2c26c8bSAndroid Build Coastguard Worker retcode = -1;
840*c2c26c8bSAndroid Build Coastguard Worker }
841*c2c26c8bSAndroid Build Coastguard Worker consumed += len + 1;
842*c2c26c8bSAndroid Build Coastguard Worker }
843*c2c26c8bSAndroid Build Coastguard Worker }
844*c2c26c8bSAndroid Build Coastguard Worker return retcode;
845*c2c26c8bSAndroid Build Coastguard Worker }
846*c2c26c8bSAndroid Build Coastguard Worker #endif
847*c2c26c8bSAndroid Build Coastguard Worker
set_dns_listeners(time_t now,fd_set * set,int * maxfdp)848*c2c26c8bSAndroid Build Coastguard Worker static int set_dns_listeners(time_t now, fd_set* set, int* maxfdp) {
849*c2c26c8bSAndroid Build Coastguard Worker struct serverfd* serverfdp;
850*c2c26c8bSAndroid Build Coastguard Worker struct listener* listener;
851*c2c26c8bSAndroid Build Coastguard Worker int wait = 0, i;
852*c2c26c8bSAndroid Build Coastguard Worker
853*c2c26c8bSAndroid Build Coastguard Worker /* will we be able to get memory? */
854*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0) get_new_frec(now, &wait);
855*c2c26c8bSAndroid Build Coastguard Worker
856*c2c26c8bSAndroid Build Coastguard Worker for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) {
857*c2c26c8bSAndroid Build Coastguard Worker FD_SET(serverfdp->fd, set);
858*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(serverfdp->fd, maxfdp);
859*c2c26c8bSAndroid Build Coastguard Worker }
860*c2c26c8bSAndroid Build Coastguard Worker
861*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0 && !daemon->osport)
862*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < RANDOM_SOCKS; i++)
863*c2c26c8bSAndroid Build Coastguard Worker if (daemon->randomsocks[i].refcount != 0) {
864*c2c26c8bSAndroid Build Coastguard Worker FD_SET(daemon->randomsocks[i].fd, set);
865*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
866*c2c26c8bSAndroid Build Coastguard Worker }
867*c2c26c8bSAndroid Build Coastguard Worker
868*c2c26c8bSAndroid Build Coastguard Worker for (listener = daemon->listeners; listener; listener = listener->next) {
869*c2c26c8bSAndroid Build Coastguard Worker /* only listen for queries if we have resources */
870*c2c26c8bSAndroid Build Coastguard Worker if (listener->fd != -1 && wait == 0) {
871*c2c26c8bSAndroid Build Coastguard Worker FD_SET(listener->fd, set);
872*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(listener->fd, maxfdp);
873*c2c26c8bSAndroid Build Coastguard Worker }
874*c2c26c8bSAndroid Build Coastguard Worker
875*c2c26c8bSAndroid Build Coastguard Worker /* death of a child goes through the select loop, so
876*c2c26c8bSAndroid Build Coastguard Worker we don't need to explicitly arrange to wake up here */
877*c2c26c8bSAndroid Build Coastguard Worker if (listener->tcpfd != -1)
878*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < MAX_PROCS; i++)
879*c2c26c8bSAndroid Build Coastguard Worker if (daemon->tcp_pids[i] == 0) {
880*c2c26c8bSAndroid Build Coastguard Worker FD_SET(listener->tcpfd, set);
881*c2c26c8bSAndroid Build Coastguard Worker bump_maxfd(listener->tcpfd, maxfdp);
882*c2c26c8bSAndroid Build Coastguard Worker break;
883*c2c26c8bSAndroid Build Coastguard Worker }
884*c2c26c8bSAndroid Build Coastguard Worker }
885*c2c26c8bSAndroid Build Coastguard Worker
886*c2c26c8bSAndroid Build Coastguard Worker return wait;
887*c2c26c8bSAndroid Build Coastguard Worker }
888*c2c26c8bSAndroid Build Coastguard Worker
check_dns_listeners(fd_set * set,time_t now)889*c2c26c8bSAndroid Build Coastguard Worker static void check_dns_listeners(fd_set* set, time_t now) {
890*c2c26c8bSAndroid Build Coastguard Worker struct serverfd* serverfdp;
891*c2c26c8bSAndroid Build Coastguard Worker struct listener* listener;
892*c2c26c8bSAndroid Build Coastguard Worker int i;
893*c2c26c8bSAndroid Build Coastguard Worker
894*c2c26c8bSAndroid Build Coastguard Worker for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
895*c2c26c8bSAndroid Build Coastguard Worker if (FD_ISSET(serverfdp->fd, set))
896*c2c26c8bSAndroid Build Coastguard Worker reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
897*c2c26c8bSAndroid Build Coastguard Worker
898*c2c26c8bSAndroid Build Coastguard Worker if (daemon->port != 0 && !daemon->osport)
899*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < RANDOM_SOCKS; i++)
900*c2c26c8bSAndroid Build Coastguard Worker if (daemon->randomsocks[i].refcount != 0 && FD_ISSET(daemon->randomsocks[i].fd, set))
901*c2c26c8bSAndroid Build Coastguard Worker reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
902*c2c26c8bSAndroid Build Coastguard Worker
903*c2c26c8bSAndroid Build Coastguard Worker for (listener = daemon->listeners; listener; listener = listener->next) {
904*c2c26c8bSAndroid Build Coastguard Worker if (listener->fd != -1 && FD_ISSET(listener->fd, set)) receive_query(listener, now);
905*c2c26c8bSAndroid Build Coastguard Worker
906*c2c26c8bSAndroid Build Coastguard Worker if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set)) {
907*c2c26c8bSAndroid Build Coastguard Worker int confd;
908*c2c26c8bSAndroid Build Coastguard Worker struct irec* iface = NULL;
909*c2c26c8bSAndroid Build Coastguard Worker pid_t p;
910*c2c26c8bSAndroid Build Coastguard Worker
911*c2c26c8bSAndroid Build Coastguard Worker while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR)
912*c2c26c8bSAndroid Build Coastguard Worker ;
913*c2c26c8bSAndroid Build Coastguard Worker
914*c2c26c8bSAndroid Build Coastguard Worker if (confd == -1) continue;
915*c2c26c8bSAndroid Build Coastguard Worker
916*c2c26c8bSAndroid Build Coastguard Worker if (daemon->options & OPT_NOWILD)
917*c2c26c8bSAndroid Build Coastguard Worker iface = listener->iface;
918*c2c26c8bSAndroid Build Coastguard Worker else {
919*c2c26c8bSAndroid Build Coastguard Worker union mysockaddr tcp_addr;
920*c2c26c8bSAndroid Build Coastguard Worker socklen_t tcp_len = sizeof(union mysockaddr);
921*c2c26c8bSAndroid Build Coastguard Worker /* Check for allowed interfaces when binding the wildcard address:
922*c2c26c8bSAndroid Build Coastguard Worker we do this by looking for an interface with the same address as
923*c2c26c8bSAndroid Build Coastguard Worker the local address of the TCP connection, then looking to see if that's
924*c2c26c8bSAndroid Build Coastguard Worker an allowed interface. As a side effect, we get the netmask of the
925*c2c26c8bSAndroid Build Coastguard Worker interface too, for localisation. */
926*c2c26c8bSAndroid Build Coastguard Worker
927*c2c26c8bSAndroid Build Coastguard Worker /* interface may be new since startup */
928*c2c26c8bSAndroid Build Coastguard Worker if (enumerate_interfaces() &&
929*c2c26c8bSAndroid Build Coastguard Worker getsockname(confd, (struct sockaddr*) &tcp_addr, &tcp_len) != -1)
930*c2c26c8bSAndroid Build Coastguard Worker for (iface = daemon->interfaces; iface; iface = iface->next)
931*c2c26c8bSAndroid Build Coastguard Worker if (sockaddr_isequal(&iface->addr, &tcp_addr)) break;
932*c2c26c8bSAndroid Build Coastguard Worker }
933*c2c26c8bSAndroid Build Coastguard Worker
934*c2c26c8bSAndroid Build Coastguard Worker if (!iface) {
935*c2c26c8bSAndroid Build Coastguard Worker shutdown(confd, SHUT_RDWR);
936*c2c26c8bSAndroid Build Coastguard Worker close(confd);
937*c2c26c8bSAndroid Build Coastguard Worker }
938*c2c26c8bSAndroid Build Coastguard Worker #ifndef NO_FORK
939*c2c26c8bSAndroid Build Coastguard Worker else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0) {
940*c2c26c8bSAndroid Build Coastguard Worker if (p != -1) {
941*c2c26c8bSAndroid Build Coastguard Worker int i;
942*c2c26c8bSAndroid Build Coastguard Worker for (i = 0; i < MAX_PROCS; i++)
943*c2c26c8bSAndroid Build Coastguard Worker if (daemon->tcp_pids[i] == 0) {
944*c2c26c8bSAndroid Build Coastguard Worker daemon->tcp_pids[i] = p;
945*c2c26c8bSAndroid Build Coastguard Worker break;
946*c2c26c8bSAndroid Build Coastguard Worker }
947*c2c26c8bSAndroid Build Coastguard Worker }
948*c2c26c8bSAndroid Build Coastguard Worker close(confd);
949*c2c26c8bSAndroid Build Coastguard Worker }
950*c2c26c8bSAndroid Build Coastguard Worker #endif
951*c2c26c8bSAndroid Build Coastguard Worker else {
952*c2c26c8bSAndroid Build Coastguard Worker unsigned char* buff;
953*c2c26c8bSAndroid Build Coastguard Worker struct server* s;
954*c2c26c8bSAndroid Build Coastguard Worker int flags;
955*c2c26c8bSAndroid Build Coastguard Worker struct in_addr dst_addr_4;
956*c2c26c8bSAndroid Build Coastguard Worker
957*c2c26c8bSAndroid Build Coastguard Worker dst_addr_4.s_addr = 0;
958*c2c26c8bSAndroid Build Coastguard Worker
959*c2c26c8bSAndroid Build Coastguard Worker /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
960*c2c26c8bSAndroid Build Coastguard Worker terminate the process. */
961*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_DEBUG)) alarm(CHILD_LIFETIME);
962*c2c26c8bSAndroid Build Coastguard Worker
963*c2c26c8bSAndroid Build Coastguard Worker /* start with no upstream connections. */
964*c2c26c8bSAndroid Build Coastguard Worker for (s = daemon->servers; s; s = s->next) s->tcpfd = -1;
965*c2c26c8bSAndroid Build Coastguard Worker
966*c2c26c8bSAndroid Build Coastguard Worker /* The connected socket inherits non-blocking
967*c2c26c8bSAndroid Build Coastguard Worker attribute from the listening socket.
968*c2c26c8bSAndroid Build Coastguard Worker Reset that here. */
969*c2c26c8bSAndroid Build Coastguard Worker if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
970*c2c26c8bSAndroid Build Coastguard Worker fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
971*c2c26c8bSAndroid Build Coastguard Worker
972*c2c26c8bSAndroid Build Coastguard Worker if (listener->family == AF_INET) dst_addr_4 = iface->addr.in.sin_addr;
973*c2c26c8bSAndroid Build Coastguard Worker
974*c2c26c8bSAndroid Build Coastguard Worker buff = tcp_request(confd, now, dst_addr_4, iface->netmask);
975*c2c26c8bSAndroid Build Coastguard Worker
976*c2c26c8bSAndroid Build Coastguard Worker shutdown(confd, SHUT_RDWR);
977*c2c26c8bSAndroid Build Coastguard Worker close(confd);
978*c2c26c8bSAndroid Build Coastguard Worker
979*c2c26c8bSAndroid Build Coastguard Worker if (buff) free(buff);
980*c2c26c8bSAndroid Build Coastguard Worker
981*c2c26c8bSAndroid Build Coastguard Worker for (s = daemon->servers; s; s = s->next)
982*c2c26c8bSAndroid Build Coastguard Worker if (s->tcpfd != -1) {
983*c2c26c8bSAndroid Build Coastguard Worker shutdown(s->tcpfd, SHUT_RDWR);
984*c2c26c8bSAndroid Build Coastguard Worker close(s->tcpfd);
985*c2c26c8bSAndroid Build Coastguard Worker }
986*c2c26c8bSAndroid Build Coastguard Worker #ifndef NO_FORK
987*c2c26c8bSAndroid Build Coastguard Worker if (!(daemon->options & OPT_DEBUG)) {
988*c2c26c8bSAndroid Build Coastguard Worker flush_log();
989*c2c26c8bSAndroid Build Coastguard Worker _exit(0);
990*c2c26c8bSAndroid Build Coastguard Worker }
991*c2c26c8bSAndroid Build Coastguard Worker #endif
992*c2c26c8bSAndroid Build Coastguard Worker }
993*c2c26c8bSAndroid Build Coastguard Worker }
994*c2c26c8bSAndroid Build Coastguard Worker }
995*c2c26c8bSAndroid Build Coastguard Worker }
996*c2c26c8bSAndroid Build Coastguard Worker
997*c2c26c8bSAndroid Build Coastguard Worker #ifdef HAVE_DHCP
make_icmp_sock(void)998*c2c26c8bSAndroid Build Coastguard Worker int make_icmp_sock(void) {
999*c2c26c8bSAndroid Build Coastguard Worker int fd;
1000*c2c26c8bSAndroid Build Coastguard Worker int zeroopt = 0;
1001*c2c26c8bSAndroid Build Coastguard Worker
1002*c2c26c8bSAndroid Build Coastguard Worker if ((fd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1) {
1003*c2c26c8bSAndroid Build Coastguard Worker if (!fix_fd(fd) ||
1004*c2c26c8bSAndroid Build Coastguard Worker setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1) {
1005*c2c26c8bSAndroid Build Coastguard Worker close(fd);
1006*c2c26c8bSAndroid Build Coastguard Worker fd = -1;
1007*c2c26c8bSAndroid Build Coastguard Worker }
1008*c2c26c8bSAndroid Build Coastguard Worker }
1009*c2c26c8bSAndroid Build Coastguard Worker
1010*c2c26c8bSAndroid Build Coastguard Worker return fd;
1011*c2c26c8bSAndroid Build Coastguard Worker }
1012*c2c26c8bSAndroid Build Coastguard Worker
icmp_ping(struct in_addr addr)1013*c2c26c8bSAndroid Build Coastguard Worker int icmp_ping(struct in_addr addr) {
1014*c2c26c8bSAndroid Build Coastguard Worker /* Try and get an ICMP echo from a machine. */
1015*c2c26c8bSAndroid Build Coastguard Worker
1016*c2c26c8bSAndroid Build Coastguard Worker /* Note that whilst in the three second wait, we check for
1017*c2c26c8bSAndroid Build Coastguard Worker (and service) events on the DNS sockets, (so doing that
1018*c2c26c8bSAndroid Build Coastguard Worker better not use any resources our caller has in use...)
1019*c2c26c8bSAndroid Build Coastguard Worker but we remain deaf to signals or further DHCP packets. */
1020*c2c26c8bSAndroid Build Coastguard Worker
1021*c2c26c8bSAndroid Build Coastguard Worker int fd;
1022*c2c26c8bSAndroid Build Coastguard Worker struct sockaddr_in saddr;
1023*c2c26c8bSAndroid Build Coastguard Worker struct {
1024*c2c26c8bSAndroid Build Coastguard Worker struct ip ip;
1025*c2c26c8bSAndroid Build Coastguard Worker struct icmp icmp;
1026*c2c26c8bSAndroid Build Coastguard Worker } packet;
1027*c2c26c8bSAndroid Build Coastguard Worker unsigned short id = rand16();
1028*c2c26c8bSAndroid Build Coastguard Worker unsigned int i, j;
1029*c2c26c8bSAndroid Build Coastguard Worker int gotreply = 0;
1030*c2c26c8bSAndroid Build Coastguard Worker time_t start, now;
1031*c2c26c8bSAndroid Build Coastguard Worker
1032*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_NETWORK)
1033*c2c26c8bSAndroid Build Coastguard Worker if ((fd = make_icmp_sock()) == -1) return 0;
1034*c2c26c8bSAndroid Build Coastguard Worker #else
1035*c2c26c8bSAndroid Build Coastguard Worker int opt = 2000;
1036*c2c26c8bSAndroid Build Coastguard Worker fd = daemon->dhcp_icmp_fd;
1037*c2c26c8bSAndroid Build Coastguard Worker setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1038*c2c26c8bSAndroid Build Coastguard Worker #endif
1039*c2c26c8bSAndroid Build Coastguard Worker
1040*c2c26c8bSAndroid Build Coastguard Worker saddr.sin_family = AF_INET;
1041*c2c26c8bSAndroid Build Coastguard Worker saddr.sin_port = 0;
1042*c2c26c8bSAndroid Build Coastguard Worker saddr.sin_addr = addr;
1043*c2c26c8bSAndroid Build Coastguard Worker
1044*c2c26c8bSAndroid Build Coastguard Worker memset(&packet.icmp, 0, sizeof(packet.icmp));
1045*c2c26c8bSAndroid Build Coastguard Worker packet.icmp.icmp_type = ICMP_ECHO;
1046*c2c26c8bSAndroid Build Coastguard Worker packet.icmp.icmp_id = id;
1047*c2c26c8bSAndroid Build Coastguard Worker for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++) j += ((u16*) &packet.icmp)[i];
1048*c2c26c8bSAndroid Build Coastguard Worker while (j >> 16) j = (j & 0xffff) + (j >> 16);
1049*c2c26c8bSAndroid Build Coastguard Worker packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
1050*c2c26c8bSAndroid Build Coastguard Worker
1051*c2c26c8bSAndroid Build Coastguard Worker while (sendto(fd, (char*) &packet.icmp, sizeof(struct icmp), 0, (struct sockaddr*) &saddr,
1052*c2c26c8bSAndroid Build Coastguard Worker sizeof(saddr)) == -1 &&
1053*c2c26c8bSAndroid Build Coastguard Worker retry_send())
1054*c2c26c8bSAndroid Build Coastguard Worker ;
1055*c2c26c8bSAndroid Build Coastguard Worker
1056*c2c26c8bSAndroid Build Coastguard Worker for (now = start = dnsmasq_time(); difftime(now, start) < (float) PING_WAIT;) {
1057*c2c26c8bSAndroid Build Coastguard Worker struct timeval tv;
1058*c2c26c8bSAndroid Build Coastguard Worker fd_set rset, wset;
1059*c2c26c8bSAndroid Build Coastguard Worker struct sockaddr_in faddr;
1060*c2c26c8bSAndroid Build Coastguard Worker int maxfd = fd;
1061*c2c26c8bSAndroid Build Coastguard Worker socklen_t len = sizeof(faddr);
1062*c2c26c8bSAndroid Build Coastguard Worker
1063*c2c26c8bSAndroid Build Coastguard Worker tv.tv_usec = 250000;
1064*c2c26c8bSAndroid Build Coastguard Worker tv.tv_sec = 0;
1065*c2c26c8bSAndroid Build Coastguard Worker
1066*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&rset);
1067*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&wset);
1068*c2c26c8bSAndroid Build Coastguard Worker FD_SET(fd, &rset);
1069*c2c26c8bSAndroid Build Coastguard Worker set_dns_listeners(now, &rset, &maxfd);
1070*c2c26c8bSAndroid Build Coastguard Worker set_log_writer(&wset, &maxfd);
1071*c2c26c8bSAndroid Build Coastguard Worker
1072*c2c26c8bSAndroid Build Coastguard Worker if (select(maxfd + 1, &rset, &wset, NULL, &tv) < 0) {
1073*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&rset);
1074*c2c26c8bSAndroid Build Coastguard Worker FD_ZERO(&wset);
1075*c2c26c8bSAndroid Build Coastguard Worker }
1076*c2c26c8bSAndroid Build Coastguard Worker
1077*c2c26c8bSAndroid Build Coastguard Worker now = dnsmasq_time();
1078*c2c26c8bSAndroid Build Coastguard Worker
1079*c2c26c8bSAndroid Build Coastguard Worker check_log_writer(&wset);
1080*c2c26c8bSAndroid Build Coastguard Worker check_dns_listeners(&rset, now);
1081*c2c26c8bSAndroid Build Coastguard Worker
1082*c2c26c8bSAndroid Build Coastguard Worker if (FD_ISSET(fd, &rset) &&
1083*c2c26c8bSAndroid Build Coastguard Worker recvfrom(fd, &packet, sizeof(packet), 0, (struct sockaddr*) &faddr, &len) ==
1084*c2c26c8bSAndroid Build Coastguard Worker sizeof(packet) &&
1085*c2c26c8bSAndroid Build Coastguard Worker saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
1086*c2c26c8bSAndroid Build Coastguard Worker packet.icmp.icmp_type == ICMP_ECHOREPLY && packet.icmp.icmp_seq == 0 &&
1087*c2c26c8bSAndroid Build Coastguard Worker packet.icmp.icmp_id == id) {
1088*c2c26c8bSAndroid Build Coastguard Worker gotreply = 1;
1089*c2c26c8bSAndroid Build Coastguard Worker break;
1090*c2c26c8bSAndroid Build Coastguard Worker }
1091*c2c26c8bSAndroid Build Coastguard Worker }
1092*c2c26c8bSAndroid Build Coastguard Worker
1093*c2c26c8bSAndroid Build Coastguard Worker #if defined(HAVE_LINUX_NETWORK)
1094*c2c26c8bSAndroid Build Coastguard Worker close(fd);
1095*c2c26c8bSAndroid Build Coastguard Worker #else
1096*c2c26c8bSAndroid Build Coastguard Worker opt = 1;
1097*c2c26c8bSAndroid Build Coastguard Worker setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
1098*c2c26c8bSAndroid Build Coastguard Worker #endif
1099*c2c26c8bSAndroid Build Coastguard Worker
1100*c2c26c8bSAndroid Build Coastguard Worker return gotreply;
1101*c2c26c8bSAndroid Build Coastguard Worker }
1102*c2c26c8bSAndroid Build Coastguard Worker #endif
1103