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