Home | History | Annotate | Download | only in src
      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 #ifdef __ANDROID__
     68 static int set_android_listeners(fd_set *set, int *maxfdp);
     69 static int check_android_listeners(fd_set *set);
     70 #endif
     71 
     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 #ifndef __ANDROID__
    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 #ifndef __ANDROID__
    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 #ifdef __ANDROID__
    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 #ifdef __ANDROID__
    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 
    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 
    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 
    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 
    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 
    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 
    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 #ifdef __ANDROID__
    985 
    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 
    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 
   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 
   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
   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 
   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