Annotation of embedaddon/dnsmasq/src/dnsmasq.c, revision 1.1.1.2

1.1.1.2 ! misho       1: /* dnsmasq is Copyright (c) 2000-2014 Simon Kelley
1.1       misho       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: /* Declare static char *compiler_opts  in config.h */
                     18: #define DNSMASQ_COMPILE_OPTS
                     19: 
                     20: #include "dnsmasq.h"
                     21: 
                     22: struct daemon *daemon;
                     23: 
                     24: static volatile pid_t pid = 0;
                     25: static volatile int pipewrite;
                     26: 
                     27: static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp);
                     28: static void check_dns_listeners(fd_set *set, time_t now);
                     29: static void sig_handler(int sig);
                     30: static void async_event(int pipe, time_t now);
                     31: static void fatal_event(struct event_desc *ev, char *msg);
                     32: static int read_event(int fd, struct event_desc *evp, char **msg);
                     33: 
                     34: int main (int argc, char **argv)
                     35: {
                     36:   int bind_fallback = 0;
                     37:   time_t now;
                     38:   struct sigaction sigact;
                     39:   struct iname *if_tmp;
                     40:   int piperead, pipefd[2], err_pipe[2];
                     41:   struct passwd *ent_pw = NULL;
                     42: #if defined(HAVE_SCRIPT)
                     43:   uid_t script_uid = 0;
                     44:   gid_t script_gid = 0;
                     45: #endif
                     46:   struct group *gp = NULL;
                     47:   long i, max_fd = sysconf(_SC_OPEN_MAX);
                     48:   char *baduser = NULL;
                     49:   int log_err;
                     50: #if defined(HAVE_LINUX_NETWORK)
                     51:   cap_user_header_t hdr = NULL;
                     52:   cap_user_data_t data = NULL;
1.1.1.2 ! misho      53:   char *bound_device = NULL;
        !            54:   int did_bind = 0;
1.1       misho      55: #endif 
1.1.1.2 ! misho      56: #if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
1.1       misho      57:   struct dhcp_context *context;
1.1.1.2 ! misho      58:   struct dhcp_relay *relay;
        !            59: #endif
1.1       misho      60: 
                     61: #ifdef LOCALEDIR
                     62:   setlocale(LC_ALL, "");
                     63:   bindtextdomain("dnsmasq", LOCALEDIR); 
                     64:   textdomain("dnsmasq");
                     65: #endif
                     66: 
                     67:   sigact.sa_handler = sig_handler;
                     68:   sigact.sa_flags = 0;
                     69:   sigemptyset(&sigact.sa_mask);
                     70:   sigaction(SIGUSR1, &sigact, NULL);
                     71:   sigaction(SIGUSR2, &sigact, NULL);
                     72:   sigaction(SIGHUP, &sigact, NULL);
                     73:   sigaction(SIGTERM, &sigact, NULL);
                     74:   sigaction(SIGALRM, &sigact, NULL);
                     75:   sigaction(SIGCHLD, &sigact, NULL);
                     76: 
                     77:   /* ignore SIGPIPE */
                     78:   sigact.sa_handler = SIG_IGN;
                     79:   sigaction(SIGPIPE, &sigact, NULL);
                     80: 
                     81:   umask(022); /* known umask, create leases and pid files as 0644 */
                     82: 
                     83:   read_opts(argc, argv, compile_opts);
1.1.1.2 ! misho      84:  
1.1       misho      85:   if (daemon->edns_pktsz < PACKETSZ)
                     86:     daemon->edns_pktsz = PACKETSZ;
1.1.1.2 ! misho      87: #ifdef HAVE_DNSSEC
        !            88:   /* Enforce min packet big enough for DNSSEC */
        !            89:   if (option_bool(OPT_DNSSEC_VALID) && daemon->edns_pktsz < EDNS_PKTSZ)
        !            90:     daemon->edns_pktsz = EDNS_PKTSZ;
        !            91: #endif
        !            92: 
1.1       misho      93:   daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ? 
                     94:     daemon->edns_pktsz : DNSMASQ_PACKETSZ;
                     95:   daemon->packet = safe_malloc(daemon->packet_buff_sz);
1.1.1.2 ! misho      96:   
1.1       misho      97:   daemon->addrbuff = safe_malloc(ADDRSTRLEN);
1.1.1.2 ! misho      98:   
        !            99: #ifdef HAVE_DNSSEC
        !           100:   if (option_bool(OPT_DNSSEC_VALID))
        !           101:     {
        !           102:       daemon->keyname = safe_malloc(MAXDNAME);
        !           103:       daemon->workspacename = safe_malloc(MAXDNAME);
        !           104:     }
        !           105: #endif
1.1       misho     106: 
                    107: #ifdef HAVE_DHCP
                    108:   if (!daemon->lease_file)
                    109:     {
                    110:       if (daemon->dhcp || daemon->dhcp6)
                    111:        daemon->lease_file = LEASEFILE;
                    112:     }
                    113: #endif
                    114:   
                    115:   /* Close any file descriptors we inherited apart from std{in|out|err} 
                    116:      
                    117:      Ensure that at least stdin, stdout and stderr (fd 0, 1, 2) exist,
                    118:      otherwise file descriptors we create can end up being 0, 1, or 2 
                    119:      and then get accidentally closed later when we make 0, 1, and 2 
                    120:      open to /dev/null. Normally we'll be started with 0, 1 and 2 open, 
                    121:      but it's not guaranteed. By opening /dev/null three times, we 
                    122:      ensure that we're not using those fds for real stuff. */
                    123:   for (i = 0; i < max_fd; i++)
                    124:     if (i != STDOUT_FILENO && i != STDERR_FILENO && i != STDIN_FILENO)
                    125:       close(i);
                    126:     else
                    127:       open("/dev/null", O_RDWR); 
                    128: 
                    129: #ifndef HAVE_LINUX_NETWORK
                    130: #  if !(defined(IP_RECVDSTADDR) && defined(IP_RECVIF) && defined(IP_SENDSRCADDR))
                    131:   if (!option_bool(OPT_NOWILD))
                    132:     {
                    133:       bind_fallback = 1;
                    134:       set_option_bool(OPT_NOWILD);
                    135:     }
                    136: #  endif
                    137:   
                    138:   /* -- bind-dynamic not supported on !Linux, fall back to --bind-interfaces */
                    139:   if (option_bool(OPT_CLEVERBIND))
                    140:     {
                    141:       bind_fallback = 1;
                    142:       set_option_bool(OPT_NOWILD);
                    143:       reset_option_bool(OPT_CLEVERBIND);
                    144:     }
                    145: #endif
                    146:   
1.1.1.2 ! misho     147:   if (option_bool(OPT_DNSSEC_VALID))
        !           148:     {
        !           149: #ifdef HAVE_DNSSEC
        !           150:       if (!daemon->ds)
        !           151:        die(_("No trust anchors provided for DNSSEC"), NULL, EC_BADCONF);
        !           152:       
        !           153:       if (daemon->cachesize < CACHESIZ)
        !           154:        die(_("Cannot reduce cache size from default when DNSSEC enabled"), NULL, EC_BADCONF);
        !           155: #else 
        !           156:       die(_("DNSSEC not available: set HAVE_DNSSEC in src/config.h"), NULL, EC_BADCONF);
        !           157: #endif
        !           158:     }
        !           159: 
1.1       misho     160: #ifndef HAVE_TFTP
                    161:   if (option_bool(OPT_TFTP))
                    162:     die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
                    163: #endif
                    164: 
                    165: #ifdef HAVE_CONNTRACK
                    166:   if (option_bool(OPT_CONNTRACK) && (daemon->query_port != 0 || daemon->osport))
                    167:     die (_("Cannot use --conntrack AND --query-port"), NULL, EC_BADCONF); 
                    168: #else
                    169:   if (option_bool(OPT_CONNTRACK))
                    170:     die(_("Conntrack support not available: set HAVE_CONNTRACK in src/config.h"), NULL, EC_BADCONF);
                    171: #endif
                    172: 
                    173: #ifdef HAVE_SOLARIS_NETWORK
                    174:   if (daemon->max_logs != 0)
                    175:     die(_("asychronous logging is not available under Solaris"), NULL, EC_BADCONF);
                    176: #endif
                    177:   
                    178: #ifdef __ANDROID__
                    179:   if (daemon->max_logs != 0)
                    180:     die(_("asychronous logging is not available under Android"), NULL, EC_BADCONF);
                    181: #endif
                    182: 
                    183: #ifndef HAVE_AUTH
                    184:   if (daemon->authserver)
                    185:     die(_("authoritative DNS not available: set HAVE_AUTH in src/config.h"), NULL, EC_BADCONF);
                    186: #endif
                    187: 
                    188:   rand_init();
                    189:   
                    190:   now = dnsmasq_time();
                    191: 
                    192:   /* Create a serial at startup if not configured. */
                    193:   if (daemon->authinterface && daemon->soa_sn == 0)
                    194: #ifdef HAVE_BROKEN_RTC
                    195:     die(_("zone serial must be configured in --auth-soa"), NULL, EC_BADCONF);
                    196: #else
                    197:   daemon->soa_sn = now;
                    198: #endif
                    199:   
1.1.1.2 ! misho     200: #ifdef HAVE_DHCP6
        !           201:   if (daemon->dhcp6)
        !           202:     {
        !           203:       daemon->doing_ra = option_bool(OPT_RA);
1.1       misho     204:       
1.1.1.2 ! misho     205:       for (context = daemon->dhcp6; context; context = context->next)
1.1       misho     206:        {
1.1.1.2 ! misho     207:          if (context->flags & CONTEXT_DHCP)
        !           208:            daemon->doing_dhcp6 = 1;
        !           209:          if (context->flags & CONTEXT_RA)
        !           210:            daemon->doing_ra = 1;
        !           211: #if !defined(HAVE_LINUX_NETWORK) && !defined(HAVE_BSD_NETWORK)
        !           212:          if (context->flags & CONTEXT_TEMPLATE)
        !           213:            die (_("dhcp-range constructor not available on this platform"), NULL, EC_BADCONF);
1.1       misho     214: #endif 
                    215:        }
1.1.1.2 ! misho     216:     }
        !           217: #endif
        !           218:   
        !           219: #ifdef HAVE_DHCP
        !           220:   /* Note that order matters here, we must call lease_init before
        !           221:      creating any file descriptors which shouldn't be leaked
        !           222:      to the lease-script init process. We need to call common_init
        !           223:      before lease_init to allocate buffers it uses.*/
        !           224:   if (daemon->dhcp || daemon->doing_dhcp6 || daemon->relay4 || daemon->relay6)
        !           225:     {
        !           226:       dhcp_common_init();
1.1       misho     227:       if (daemon->dhcp || daemon->doing_dhcp6)
1.1.1.2 ! misho     228:        lease_init(now);
        !           229:     }
        !           230:   
        !           231:   if (daemon->dhcp || daemon->relay4)
        !           232:     dhcp_init();
        !           233:   
1.1       misho     234: #  ifdef HAVE_DHCP6
1.1.1.2 ! misho     235:   if (daemon->doing_ra || daemon->doing_dhcp6 || daemon->relay6)
        !           236:     ra_init(now);
        !           237:   
        !           238:   if (daemon->doing_dhcp6 || daemon->relay6)
        !           239:     dhcp6_init();
1.1       misho     240: #  endif
                    241: 
                    242: #endif
                    243: 
                    244: #ifdef HAVE_IPSET
                    245:   if (daemon->ipsets)
                    246:     ipset_init();
                    247: #endif
                    248: 
1.1.1.2 ! misho     249: #if  defined(HAVE_LINUX_NETWORK)
1.1       misho     250:   netlink_init();
1.1.1.2 ! misho     251: #elif defined(HAVE_BSD_NETWORK)
        !           252:   route_init();
1.1       misho     253: #endif
                    254: 
1.1.1.2 ! misho     255:   if (option_bool(OPT_NOWILD) && option_bool(OPT_CLEVERBIND))
        !           256:     die(_("cannot set --bind-interfaces and --bind-dynamic"), NULL, EC_BADCONF);
        !           257:   
        !           258:   if (!enumerate_interfaces(1) || !enumerate_interfaces(0))
1.1       misho     259:     die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
                    260:   
                    261:   if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND)) 
                    262:     {
                    263:       create_bound_listeners(1);
                    264:       
                    265:       if (!option_bool(OPT_CLEVERBIND))
                    266:        for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
                    267:          if (if_tmp->name && !if_tmp->used)
                    268:            die(_("unknown interface %s"), if_tmp->name, EC_BADNET);
                    269: 
                    270: #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP)
                    271:       /* after enumerate_interfaces()  */
1.1.1.2 ! misho     272:       bound_device = whichdevice();
        !           273:       
1.1       misho     274:       if (daemon->dhcp)
                    275:        {
1.1.1.2 ! misho     276:          if (!daemon->relay4 && bound_device)
        !           277:            {
        !           278:              bindtodevice(bound_device, daemon->dhcpfd);
        !           279:              did_bind = 1;
        !           280:            }
        !           281:          if (daemon->enable_pxe && bound_device)
        !           282:            {
        !           283:              bindtodevice(bound_device, daemon->pxefd);
        !           284:              did_bind = 1;
        !           285:            }
1.1       misho     286:        }
                    287: #endif
                    288: 
                    289: #if defined(HAVE_LINUX_NETWORK) && defined(HAVE_DHCP6)
1.1.1.2 ! misho     290:       if (daemon->doing_dhcp6 && !daemon->relay6 && bound_device)
        !           291:        {
        !           292:          bindtodevice(bound_device, daemon->dhcp6fd);
        !           293:          did_bind = 1;
        !           294:        }
1.1       misho     295: #endif
                    296:     }
                    297:   else 
                    298:     create_wildcard_listeners();
                    299:  
                    300: #ifdef HAVE_DHCP6
                    301:   /* after enumerate_interfaces() */
1.1.1.2 ! misho     302:   if (daemon->doing_dhcp6 || daemon->relay6 || daemon->doing_ra)
1.1       misho     303:     join_multicast(1);
1.1.1.2 ! misho     304: 
        !           305:   /* After netlink_init() and before create_helper() */
        !           306:   lease_make_duid(now);
1.1       misho     307: #endif
                    308:   
                    309:   if (daemon->port != 0)
1.1.1.2 ! misho     310:     {
        !           311:       cache_init();
        !           312: #ifdef HAVE_DNSSEC
        !           313:       blockdata_init();
        !           314: #endif
        !           315:     }
1.1       misho     316:     
                    317:   if (option_bool(OPT_DBUS))
                    318: #ifdef HAVE_DBUS
                    319:     {
                    320:       char *err;
                    321:       daemon->dbus = NULL;
                    322:       daemon->watches = NULL;
                    323:       if ((err = dbus_init()))
                    324:        die(_("DBus error: %s"), err, EC_MISC);
                    325:     }
                    326: #else
                    327:   die(_("DBus not available: set HAVE_DBUS in src/config.h"), NULL, EC_BADCONF);
                    328: #endif
                    329:   
                    330:   if (daemon->port != 0)
                    331:     pre_allocate_sfds();
                    332: 
                    333: #if defined(HAVE_SCRIPT)
                    334:   /* Note getpwnam returns static storage */
                    335:   if ((daemon->dhcp || daemon->dhcp6) && 
                    336:       daemon->scriptuser && 
                    337:       (daemon->lease_change_command || daemon->luascript))
                    338:     {
                    339:       if ((ent_pw = getpwnam(daemon->scriptuser)))
                    340:        {
                    341:          script_uid = ent_pw->pw_uid;
                    342:          script_gid = ent_pw->pw_gid;
                    343:         }
                    344:       else
                    345:        baduser = daemon->scriptuser;
                    346:     }
                    347: #endif
                    348:   
                    349:   if (daemon->username && !(ent_pw = getpwnam(daemon->username)))
                    350:     baduser = daemon->username;
                    351:   else if (daemon->groupname && !(gp = getgrnam(daemon->groupname)))
                    352:     baduser = daemon->groupname;
                    353: 
                    354:   if (baduser)
                    355:     die(_("unknown user or group: %s"), baduser, EC_BADCONF);
                    356:    
                    357:   /* implement group defaults, "dip" if available, or group associated with uid */
                    358:   if (!daemon->group_set && !gp)
                    359:     {
                    360:       if (!(gp = getgrnam(CHGRP)) && ent_pw)
                    361:        gp = getgrgid(ent_pw->pw_gid);
                    362:       
                    363:       /* for error message */
                    364:       if (gp)
                    365:        daemon->groupname = gp->gr_name; 
                    366:     }
                    367: 
                    368: #if defined(HAVE_LINUX_NETWORK)
                    369:   /* determine capability API version here, while we can still
                    370:      call safe_malloc */
                    371:   if (ent_pw && ent_pw->pw_uid != 0)
                    372:     {
                    373:       int capsize = 1; /* for header version 1 */
                    374:       hdr = safe_malloc(sizeof(*hdr));
                    375: 
                    376:       /* find version supported by kernel */
                    377:       memset(hdr, 0, sizeof(*hdr));
                    378:       capget(hdr, NULL);
                    379:       
                    380:       if (hdr->version != LINUX_CAPABILITY_VERSION_1)
                    381:        {
                    382:          /* if unknown version, use largest supported version (3) */
                    383:          if (hdr->version != LINUX_CAPABILITY_VERSION_2)
                    384:            hdr->version = LINUX_CAPABILITY_VERSION_3;
                    385:          capsize = 2;
                    386:        }
                    387:       
                    388:       data = safe_malloc(sizeof(*data) * capsize);
                    389:       memset(data, 0, sizeof(*data) * capsize);
                    390:     }
                    391: #endif
                    392: 
                    393:   /* Use a pipe to carry signals and other events back to the event loop 
                    394:      in a race-free manner and another to carry errors to daemon-invoking process */
                    395:   safe_pipe(pipefd, 1);
                    396:   
                    397:   piperead = pipefd[0];
                    398:   pipewrite = pipefd[1];
                    399:   /* prime the pipe to load stuff first time. */
1.1.1.2 ! misho     400:   send_event(pipewrite, EVENT_INIT, 0, NULL); 
1.1       misho     401: 
                    402:   err_pipe[1] = -1;
                    403:   
                    404:   if (!option_bool(OPT_DEBUG))   
                    405:     {
                    406:       /* The following code "daemonizes" the process. 
                    407:         See Stevens section 12.4 */
                    408:       
                    409:       if (chdir("/") != 0)
                    410:        die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC); 
                    411: 
                    412: #ifndef NO_FORK      
                    413:       if (!option_bool(OPT_NO_FORK))
                    414:        {
                    415:          pid_t pid;
                    416:          
                    417:          /* pipe to carry errors back to original process.
                    418:             When startup is complete we close this and the process terminates. */
                    419:          safe_pipe(err_pipe, 0);
                    420:          
                    421:          if ((pid = fork()) == -1)
                    422:            /* fd == -1 since we've not forked, never returns. */
                    423:            send_event(-1, EVENT_FORK_ERR, errno, NULL);
                    424:           
                    425:          if (pid != 0)
                    426:            {
                    427:              struct event_desc ev;
                    428:              char *msg;
                    429: 
                    430:              /* close our copy of write-end */
                    431:              close(err_pipe[1]);
                    432:              
                    433:              /* check for errors after the fork */
                    434:              if (read_event(err_pipe[0], &ev, &msg))
                    435:                fatal_event(&ev, msg);
                    436:              
                    437:              _exit(EC_GOOD);
                    438:            } 
                    439:          
                    440:          close(err_pipe[0]);
                    441: 
                    442:          /* NO calls to die() from here on. */
                    443:          
                    444:          setsid();
                    445:         
                    446:          if ((pid = fork()) == -1)
                    447:            send_event(err_pipe[1], EVENT_FORK_ERR, errno, NULL);
                    448:         
                    449:          if (pid != 0)
                    450:            _exit(0);
                    451:        }
                    452: #endif
                    453:             
                    454:       /* write pidfile _after_ forking ! */
                    455:       if (daemon->runfile)
                    456:        {
                    457:          int fd, err = 0;
                    458: 
                    459:          sprintf(daemon->namebuff, "%d\n", (int) getpid());
                    460: 
                    461:          /* Explanation: Some installations of dnsmasq (eg Debian/Ubuntu) locate the pid-file
                    462:             in a directory which is writable by the non-privileged user that dnsmasq runs as. This
                    463:             allows the daemon to delete the file as part of its shutdown. This is a security hole to the 
                    464:             extent that an attacker running as the unprivileged  user could replace the pidfile with a 
                    465:             symlink, and have the target of that symlink overwritten as root next time dnsmasq starts. 
                    466: 
                    467:             The folowing code first deletes any existing file, and then opens it with the O_EXCL flag,
                    468:             ensuring that the open() fails should there be any existing file (because the unlink() failed, 
                    469:             or an attacker exploited the race between unlink() and open()). This ensures that no symlink
                    470:             attack can succeed. 
                    471: 
                    472:             Any compromise of the non-privileged user still theoretically allows the pid-file to be
                    473:             replaced whilst dnsmasq is running. The worst that could allow is that the usual 
                    474:             "shutdown dnsmasq" shell command could be tricked into stopping any other process.
                    475: 
                    476:             Note that if dnsmasq is started as non-root (eg for testing) it silently ignores 
                    477:             failure to write the pid-file.
                    478:          */
                    479: 
                    480:          unlink(daemon->runfile); 
                    481:          
                    482:          if ((fd = open(daemon->runfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH)) == -1)
                    483:            {
                    484:              /* only complain if started as root */
                    485:              if (getuid() == 0)
                    486:                err = 1;
                    487:            }
                    488:          else
                    489:            {
                    490:              if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
                    491:                err = 1;
                    492:              
                    493:              while (!err && close(fd) == -1)
                    494:                if (!retry_send())
                    495:                  err = 1;
                    496:            }
                    497: 
                    498:          if (err)
                    499:            {
                    500:              send_event(err_pipe[1], EVENT_PIDFILE, errno, daemon->runfile);
                    501:              _exit(0);
                    502:            }
                    503:        }
                    504:     }
                    505:   
                    506:    log_err = log_start(ent_pw, err_pipe[1]);
                    507: 
                    508:    if (!option_bool(OPT_DEBUG)) 
                    509:      {       
                    510:        /* open  stdout etc to /dev/null */
                    511:        int nullfd = open("/dev/null", O_RDWR);
                    512:        dup2(nullfd, STDOUT_FILENO);
                    513:        dup2(nullfd, STDERR_FILENO);
                    514:        dup2(nullfd, STDIN_FILENO);
                    515:        close(nullfd);
                    516:      }
                    517:    
                    518:    /* if we are to run scripts, we need to fork a helper before dropping root. */
                    519:   daemon->helperfd = -1;
                    520: #ifdef HAVE_SCRIPT 
                    521:   if ((daemon->dhcp || daemon->dhcp6) && (daemon->lease_change_command || daemon->luascript))
                    522:     daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
                    523: #endif
                    524: 
                    525:   if (!option_bool(OPT_DEBUG) && getuid() == 0)   
                    526:     {
                    527:       int bad_capabilities = 0;
                    528:       gid_t dummy;
                    529:       
                    530:       /* remove all supplimentary groups */
                    531:       if (gp && 
                    532:          (setgroups(0, &dummy) == -1 ||
                    533:           setgid(gp->gr_gid) == -1))
                    534:        {
                    535:          send_event(err_pipe[1], EVENT_GROUP_ERR, errno, daemon->groupname);
                    536:          _exit(0);
                    537:        }
                    538:   
                    539:       if (ent_pw && ent_pw->pw_uid != 0)
                    540:        {     
                    541: #if defined(HAVE_LINUX_NETWORK)          
                    542:          /* On linux, we keep CAP_NETADMIN (for ARP-injection) and
                    543:             CAP_NET_RAW (for icmp) if we're doing dhcp. If we have yet to bind 
                    544:             ports because of DAD, or we're doing it dynamically,
                    545:             we need CAP_NET_BIND_SERVICE too. */
                    546:          if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
                    547:            data->effective = data->permitted = data->inheritable =
                    548:              (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | 
                    549:              (1 << CAP_SETUID) | (1 << CAP_NET_BIND_SERVICE);
                    550:          else
                    551:            data->effective = data->permitted = data->inheritable =
                    552:              (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_SETUID);
                    553:          
                    554:          /* Tell kernel to not clear capabilities when dropping root */
                    555:          if (capset(hdr, data) == -1 || prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1)
                    556:            bad_capabilities = errno;
                    557:                          
                    558: #elif defined(HAVE_SOLARIS_NETWORK)
                    559:          /* http://developers.sun.com/solaris/articles/program_privileges.html */
                    560:          priv_set_t *priv_set;
                    561:          
                    562:          if (!(priv_set = priv_str_to_set("basic", ",", NULL)) ||
                    563:              priv_addset(priv_set, PRIV_NET_ICMPACCESS) == -1 ||
                    564:              priv_addset(priv_set, PRIV_SYS_NET_CONFIG) == -1)
                    565:            bad_capabilities = errno;
                    566: 
                    567:          if (priv_set && bad_capabilities == 0)
                    568:            {
                    569:              priv_inverse(priv_set);
                    570:          
                    571:              if (setppriv(PRIV_OFF, PRIV_LIMIT, priv_set) == -1)
                    572:                bad_capabilities = errno;
                    573:            }
                    574: 
                    575:          if (priv_set)
                    576:            priv_freeset(priv_set);
                    577: 
                    578: #endif    
                    579: 
                    580:          if (bad_capabilities != 0)
                    581:            {
                    582:              send_event(err_pipe[1], EVENT_CAP_ERR, bad_capabilities, NULL);
                    583:              _exit(0);
                    584:            }
                    585:          
                    586:          /* finally drop root */
                    587:          if (setuid(ent_pw->pw_uid) == -1)
                    588:            {
                    589:              send_event(err_pipe[1], EVENT_USER_ERR, errno, daemon->username);
                    590:              _exit(0);
                    591:            }     
                    592: 
                    593: #ifdef HAVE_LINUX_NETWORK
                    594:          if (is_dad_listeners() || option_bool(OPT_CLEVERBIND))
                    595:           data->effective = data->permitted =
                    596:             (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW) | (1 << CAP_NET_BIND_SERVICE);
                    597:         else
                    598:           data->effective = data->permitted = 
                    599:             (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
                    600:          data->inheritable = 0;
                    601:          
                    602:          /* lose the setuid and setgid capbilities */
                    603:          if (capset(hdr, data) == -1)
                    604:            {
                    605:              send_event(err_pipe[1], EVENT_CAP_ERR, errno, NULL);
                    606:              _exit(0);
                    607:            }
                    608: #endif
                    609:          
                    610:        }
                    611:     }
                    612:   
                    613: #ifdef HAVE_LINUX_NETWORK
                    614:   if (option_bool(OPT_DEBUG)) 
                    615:     prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
                    616: #endif
                    617: 
                    618: #ifdef HAVE_TFTP
                    619:       if (option_bool(OPT_TFTP))
                    620:     {
                    621:       DIR *dir;
                    622:       struct tftp_prefix *p;
                    623:       
                    624:       if (daemon->tftp_prefix)
                    625:        {
                    626:          if (!((dir = opendir(daemon->tftp_prefix))))
                    627:            {
                    628:              send_event(err_pipe[1], EVENT_TFTP_ERR, errno, daemon->tftp_prefix);
                    629:              _exit(0);
                    630:            }
                    631:          closedir(dir);
                    632:        }
                    633: 
                    634:       for (p = daemon->if_prefix; p; p = p->next)
                    635:        {
                    636:          if (!((dir = opendir(p->prefix))))
                    637:           {
                    638:             send_event(err_pipe[1], EVENT_TFTP_ERR, errno, p->prefix);
                    639:             _exit(0);
                    640:           } 
                    641:          closedir(dir);
                    642:        }
                    643:     }
                    644: #endif
                    645: 
                    646:   if (daemon->port == 0)
                    647:     my_syslog(LOG_INFO, _("started, version %s DNS disabled"), VERSION);
                    648:   else if (daemon->cachesize != 0)
                    649:     my_syslog(LOG_INFO, _("started, version %s cachesize %d"), VERSION, daemon->cachesize);
                    650:   else
                    651:     my_syslog(LOG_INFO, _("started, version %s cache disabled"), VERSION);
                    652:   
                    653:   my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
                    654:   
                    655: #ifdef HAVE_DBUS
                    656:   if (option_bool(OPT_DBUS))
                    657:     {
                    658:       if (daemon->dbus)
                    659:        my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
                    660:       else
                    661:        my_syslog(LOG_INFO, _("DBus support enabled: bus connection pending"));
                    662:     }
                    663: #endif
                    664: 
1.1.1.2 ! misho     665:   if (option_bool(OPT_LOCAL_SERVICE))
        !           666:     my_syslog(LOG_INFO, _("DNS service limited to local subnets"));
        !           667:   
        !           668: #ifdef HAVE_DNSSEC
        !           669:   if (option_bool(OPT_DNSSEC_VALID))
        !           670:     {
        !           671:       my_syslog(LOG_INFO, _("DNSSEC validation enabled"));
        !           672:       if (option_bool(OPT_DNSSEC_TIME))
        !           673:        my_syslog(LOG_INFO, _("DNSSEC signature timestamps not checked until first cache reload"));
        !           674:     }
        !           675: #endif
        !           676: 
1.1       misho     677:   if (log_err != 0)
                    678:     my_syslog(LOG_WARNING, _("warning: failed to change owner of %s: %s"), 
                    679:              daemon->log_file, strerror(log_err));
1.1.1.2 ! misho     680:   
1.1       misho     681:   if (bind_fallback)
                    682:     my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
1.1.1.2 ! misho     683: 
        !           684:   if (option_bool(OPT_NOWILD))
        !           685:     warn_bound_listeners();
        !           686: 
        !           687:   warn_int_names();
1.1       misho     688:   
                    689:   if (!option_bool(OPT_NOWILD)) 
                    690:     for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
                    691:       if (if_tmp->name && !if_tmp->used)
                    692:        my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
                    693:    
                    694:   if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
                    695:     {
                    696:       if (daemon->resolv_files && !daemon->resolv_files->is_default)
                    697:        my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
                    698:       daemon->resolv_files = NULL;
                    699:       if (!daemon->servers)
                    700:        my_syslog(LOG_WARNING, _("warning: no upstream servers configured"));
                    701:     } 
                    702: 
                    703:   if (daemon->max_logs != 0)
                    704:     my_syslog(LOG_INFO, _("asynchronous logging enabled, queue limit is %d messages"), daemon->max_logs);
                    705:   
                    706: 
                    707: #ifdef HAVE_DHCP
                    708:   for (context = daemon->dhcp; context; context = context->next)
                    709:     log_context(AF_INET, context);
                    710: 
1.1.1.2 ! misho     711:   for (relay = daemon->relay4; relay; relay = relay->next)
        !           712:     log_relay(AF_INET, relay);
        !           713: 
1.1       misho     714: #  ifdef HAVE_DHCP6
                    715:   for (context = daemon->dhcp6; context; context = context->next)
                    716:     log_context(AF_INET6, context);
                    717: 
1.1.1.2 ! misho     718:   for (relay = daemon->relay6; relay; relay = relay->next)
        !           719:     log_relay(AF_INET6, relay);
        !           720:   
1.1       misho     721:   if (daemon->doing_dhcp6 || daemon->doing_ra)
                    722:     dhcp_construct_contexts(now);
                    723:   
                    724:   if (option_bool(OPT_RA))
                    725:     my_syslog(MS_DHCP | LOG_INFO, _("IPv6 router advertisement enabled"));
                    726: #  endif
                    727: 
1.1.1.2 ! misho     728: #  ifdef HAVE_LINUX_NETWORK
        !           729:   if (did_bind)
        !           730:     my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
        !           731: #  endif
        !           732: 
1.1       misho     733:   /* after dhcp_contruct_contexts */
                    734:   if (daemon->dhcp || daemon->doing_dhcp6)
                    735:     lease_find_interfaces(now);
                    736: #endif
                    737: 
                    738: #ifdef HAVE_TFTP
                    739:        if (option_bool(OPT_TFTP))
                    740:     {
                    741: #ifdef FD_SETSIZE
                    742:       if (FD_SETSIZE < (unsigned)max_fd)
                    743:        max_fd = FD_SETSIZE;
                    744: #endif
                    745: 
                    746:       my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s", 
                    747:                daemon->tftp_prefix ? _("root is ") : _("enabled"),
                    748:                daemon->tftp_prefix ? daemon->tftp_prefix: "",
                    749:                option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
                    750:       
                    751:       /* This is a guess, it assumes that for small limits, 
                    752:         disjoint files might be served, but for large limits, 
                    753:         a single file will be sent to may clients (the file only needs
                    754:         one fd). */
                    755: 
                    756:       max_fd -= 30; /* use other than TFTP */
                    757:       
                    758:       if (max_fd < 0)
                    759:        max_fd = 5;
                    760:       else if (max_fd < 100)
                    761:        max_fd = max_fd/2;
                    762:       else
                    763:        max_fd = max_fd - 20;
                    764:       
                    765:       /* if we have to use a limited range of ports, 
                    766:         that will limit the number of transfers */
                    767:       if (daemon->start_tftp_port != 0 &&
                    768:          daemon->end_tftp_port - daemon->start_tftp_port + 1 < max_fd)
                    769:        max_fd = daemon->end_tftp_port - daemon->start_tftp_port + 1;
                    770: 
                    771:       if (daemon->tftp_max > max_fd)
                    772:        {
                    773:          daemon->tftp_max = max_fd;
                    774:          my_syslog(MS_TFTP | LOG_WARNING, 
                    775:                    _("restricting maximum simultaneous TFTP transfers to %d"), 
                    776:                    daemon->tftp_max);
                    777:        }
                    778:     }
                    779: #endif
                    780: 
                    781:   /* finished start-up - release original process */
                    782:   if (err_pipe[1] != -1)
                    783:     close(err_pipe[1]);
                    784:   
                    785:   if (daemon->port != 0)
                    786:     check_servers();
                    787:   
                    788:   pid = getpid();
                    789:   
                    790:   while (1)
                    791:     {
                    792:       int maxfd = -1;
                    793:       struct timeval t, *tp = NULL;
                    794:       fd_set rset, wset, eset;
                    795:       
                    796:       FD_ZERO(&rset);
                    797:       FD_ZERO(&wset);
                    798:       FD_ZERO(&eset);
                    799:       
                    800:       /* if we are out of resources, find how long we have to wait
                    801:         for some to come free, we'll loop around then and restart
                    802:         listening for queries */
                    803:       if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0)
                    804:        {
                    805:          t.tv_usec = 0;
                    806:          tp = &t;
                    807:        }
                    808: 
                    809:       /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
                    810:       if (daemon->tftp_trans ||
                    811:          (option_bool(OPT_DBUS) && !daemon->dbus))
                    812:        {
                    813:          t.tv_sec = 0;
                    814:          t.tv_usec = 250000;
                    815:          tp = &t;
                    816:        }
                    817:       /* Wake every second whilst waiting for DAD to complete */
                    818:       else if (is_dad_listeners())
                    819:        {
                    820:          t.tv_sec = 1;
                    821:          t.tv_usec = 0;
                    822:          tp = &t;
                    823:        }
                    824: 
                    825: #ifdef HAVE_DBUS
                    826:       set_dbus_listeners(&maxfd, &rset, &wset, &eset);
                    827: #endif 
                    828:   
                    829: #ifdef HAVE_DHCP
1.1.1.2 ! misho     830:       if (daemon->dhcp || daemon->relay4)
1.1       misho     831:        {
                    832:          FD_SET(daemon->dhcpfd, &rset);
                    833:          bump_maxfd(daemon->dhcpfd, &maxfd);
                    834:          if (daemon->pxefd != -1)
                    835:            {
                    836:              FD_SET(daemon->pxefd, &rset);
                    837:              bump_maxfd(daemon->pxefd, &maxfd);
                    838:            }
                    839:        }
                    840: #endif
                    841: 
                    842: #ifdef HAVE_DHCP6
1.1.1.2 ! misho     843:       if (daemon->doing_dhcp6 || daemon->relay6)
1.1       misho     844:        {
                    845:          FD_SET(daemon->dhcp6fd, &rset);
                    846:          bump_maxfd(daemon->dhcp6fd, &maxfd);
                    847:        }
                    848: 
                    849:       if (daemon->doing_ra)
                    850:        {
                    851:          FD_SET(daemon->icmp6fd, &rset);
                    852:          bump_maxfd(daemon->icmp6fd, &maxfd); 
                    853:        }
                    854: #endif
                    855: 
1.1.1.2 ! misho     856: #if defined(HAVE_LINUX_NETWORK)
1.1       misho     857:       FD_SET(daemon->netlinkfd, &rset);
                    858:       bump_maxfd(daemon->netlinkfd, &maxfd);
1.1.1.2 ! misho     859: #elif defined(HAVE_BSD_NETWORK)
        !           860:       FD_SET(daemon->routefd, &rset);
        !           861:       bump_maxfd(daemon->routefd, &maxfd);
1.1       misho     862: #endif
1.1.1.2 ! misho     863: 
1.1       misho     864:       FD_SET(piperead, &rset);
                    865:       bump_maxfd(piperead, &maxfd);
                    866: 
                    867: #ifdef HAVE_DHCP
                    868: #  ifdef HAVE_SCRIPT
                    869:       while (helper_buf_empty() && do_script_run(now));
                    870: 
                    871: #    ifdef HAVE_TFTP
                    872:       while (helper_buf_empty() && do_tftp_script_run());
                    873: #    endif
                    874: 
                    875:       if (!helper_buf_empty())
                    876:        {
                    877:          FD_SET(daemon->helperfd, &wset);
                    878:          bump_maxfd(daemon->helperfd, &maxfd);
                    879:        }
                    880: #  else
                    881:       /* need this for other side-effects */
                    882:       while (do_script_run(now));
                    883: 
                    884: #    ifdef HAVE_TFTP 
                    885:       while (do_tftp_script_run());
                    886: #    endif
                    887: 
                    888: #  endif
                    889: #endif
                    890:    
                    891:       /* must do this just before select(), when we know no
                    892:         more calls to my_syslog() can occur */
                    893:       set_log_writer(&wset, &maxfd);
                    894:       
                    895:       if (select(maxfd+1, &rset, &wset, &eset, tp) < 0)
                    896:        {
                    897:          /* otherwise undefined after error */
                    898:          FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
                    899:        }
                    900: 
                    901:       now = dnsmasq_time();
                    902: 
                    903:       check_log_writer(&wset);
1.1.1.2 ! misho     904: 
        !           905:       /* prime. */
        !           906:       enumerate_interfaces(1);
        !           907: 
1.1       misho     908:       /* Check the interfaces to see if any have exited DAD state
                    909:         and if so, bind the address. */
                    910:       if (is_dad_listeners())
                    911:        {
1.1.1.2 ! misho     912:          enumerate_interfaces(0);
1.1       misho     913:          /* NB, is_dad_listeners() == 1 --> we're binding interfaces */
                    914:          create_bound_listeners(0);
1.1.1.2 ! misho     915:          warn_bound_listeners();
1.1       misho     916:        }
                    917: 
1.1.1.2 ! misho     918: #if defined(HAVE_LINUX_NETWORK)
1.1       misho     919:       if (FD_ISSET(daemon->netlinkfd, &rset))
                    920:        netlink_multicast(now);
1.1.1.2 ! misho     921: #elif defined(HAVE_BSD_NETWORK)
        !           922:       if (FD_ISSET(daemon->routefd, &rset))
        !           923:        route_sock(now);
1.1       misho     924: #endif
                    925: 
                    926:       /* Check for changes to resolv files once per second max. */
                    927:       /* Don't go silent for long periods if the clock goes backwards. */
                    928:       if (daemon->last_resolv == 0 || 
                    929:          difftime(now, daemon->last_resolv) > 1.0 || 
                    930:          difftime(now, daemon->last_resolv) < -1.0)
                    931:        {
                    932:          /* poll_resolv doesn't need to reload first time through, since 
                    933:             that's queued anyway. */
                    934: 
                    935:          poll_resolv(0, daemon->last_resolv != 0, now);          
                    936:          daemon->last_resolv = now;
                    937:        }
                    938:       
                    939:       if (FD_ISSET(piperead, &rset))
                    940:        async_event(piperead, now);
                    941:       
                    942: #ifdef HAVE_DBUS
                    943:       /* if we didn't create a DBus connection, retry now. */ 
                    944:      if (option_bool(OPT_DBUS) && !daemon->dbus)
                    945:        {
                    946:          char *err;
                    947:          if ((err = dbus_init()))
                    948:            my_syslog(LOG_WARNING, _("DBus error: %s"), err);
                    949:          if (daemon->dbus)
                    950:            my_syslog(LOG_INFO, _("connected to system DBus"));
                    951:        }
                    952:       check_dbus_listeners(&rset, &wset, &eset);
                    953: #endif
                    954:       
                    955:       check_dns_listeners(&rset, now);
                    956: 
                    957: #ifdef HAVE_TFTP
                    958:       check_tftp_listeners(&rset, now);
                    959: #endif      
                    960: 
                    961: #ifdef HAVE_DHCP
1.1.1.2 ! misho     962:       if (daemon->dhcp || daemon->relay4)
1.1       misho     963:        {
                    964:          if (FD_ISSET(daemon->dhcpfd, &rset))
                    965:            dhcp_packet(now, 0);
                    966:          if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset))
                    967:            dhcp_packet(now, 1);
                    968:        }
                    969: 
                    970: #ifdef HAVE_DHCP6
1.1.1.2 ! misho     971:       if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset))
1.1       misho     972:        dhcp6_packet(now);
                    973: 
                    974:       if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
                    975:        icmp6_packet(now);
                    976: #endif
                    977: 
                    978: #  ifdef HAVE_SCRIPT
                    979:       if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset))
                    980:        helper_write();
                    981: #  endif
                    982: #endif
                    983: 
                    984:     }
                    985: }
                    986: 
                    987: static void sig_handler(int sig)
                    988: {
                    989:   if (pid == 0)
                    990:     {
                    991:       /* ignore anything other than TERM during startup
                    992:         and in helper proc. (helper ignore TERM too) */
                    993:       if (sig == SIGTERM)
                    994:        exit(EC_MISC);
                    995:     }
                    996:   else if (pid != getpid())
                    997:     {
                    998:       /* alarm is used to kill TCP children after a fixed time. */
                    999:       if (sig == SIGALRM)
                   1000:        _exit(0);
                   1001:     }
                   1002:   else
                   1003:     {
                   1004:       /* master process */
                   1005:       int event, errsave = errno;
                   1006:       
                   1007:       if (sig == SIGHUP)
                   1008:        event = EVENT_RELOAD;
                   1009:       else if (sig == SIGCHLD)
                   1010:        event = EVENT_CHILD;
                   1011:       else if (sig == SIGALRM)
                   1012:        event = EVENT_ALARM;
                   1013:       else if (sig == SIGTERM)
                   1014:        event = EVENT_TERM;
                   1015:       else if (sig == SIGUSR1)
                   1016:        event = EVENT_DUMP;
                   1017:       else if (sig == SIGUSR2)
                   1018:        event = EVENT_REOPEN;
                   1019:       else
                   1020:        return;
                   1021: 
                   1022:       send_event(pipewrite, event, 0, NULL); 
                   1023:       errno = errsave;
                   1024:     }
                   1025: }
                   1026: 
                   1027: /* now == 0 -> queue immediate callback */
                   1028: void send_alarm(time_t event, time_t now)
                   1029: {
                   1030:   if (now == 0 || event != 0)
                   1031:     {
                   1032:       /* alarm(0) or alarm(-ve) doesn't do what we want.... */
                   1033:       if ((now == 0 || difftime(event, now) <= 0.0))
                   1034:        send_event(pipewrite, EVENT_ALARM, 0, NULL);
                   1035:       else 
                   1036:        alarm((unsigned)difftime(event, now)); 
                   1037:     }
                   1038: }
                   1039: 
                   1040: void send_event(int fd, int event, int data, char *msg)
                   1041: {
                   1042:   struct event_desc ev;
                   1043:   struct iovec iov[2];
                   1044: 
                   1045:   ev.event = event;
                   1046:   ev.data = data;
                   1047:   ev.msg_sz = msg ? strlen(msg) : 0;
                   1048:   
                   1049:   iov[0].iov_base = &ev;
                   1050:   iov[0].iov_len = sizeof(ev);
                   1051:   iov[1].iov_base = msg;
                   1052:   iov[1].iov_len = ev.msg_sz;
                   1053:   
                   1054:   /* error pipe, debug mode. */
                   1055:   if (fd == -1)
                   1056:     fatal_event(&ev, msg);
                   1057:   else
                   1058:     /* pipe is non-blocking and struct event_desc is smaller than
                   1059:        PIPE_BUF, so this either fails or writes everything */
                   1060:     while (writev(fd, iov, msg ? 2 : 1) == -1 && errno == EINTR);
                   1061: }
                   1062: 
                   1063: /* NOTE: the memory used to return msg is leaked: use msgs in events only
                   1064:    to describe fatal errors. */
                   1065: static int read_event(int fd, struct event_desc *evp, char **msg)
                   1066: {
                   1067:   char *buf;
                   1068: 
                   1069:   if (!read_write(fd, (unsigned char *)evp, sizeof(struct event_desc), 1))
                   1070:     return 0;
                   1071:   
                   1072:   *msg = NULL;
                   1073:   
                   1074:   if (evp->msg_sz != 0 && 
                   1075:       (buf = malloc(evp->msg_sz + 1)) &&
                   1076:       read_write(fd, (unsigned char *)buf, evp->msg_sz, 1))
                   1077:     {
                   1078:       buf[evp->msg_sz] = 0;
                   1079:       *msg = buf;
                   1080:     }
                   1081: 
                   1082:   return 1;
                   1083: }
                   1084:     
                   1085: static void fatal_event(struct event_desc *ev, char *msg)
                   1086: {
                   1087:   errno = ev->data;
                   1088:   
                   1089:   switch (ev->event)
                   1090:     {
                   1091:     case EVENT_DIE:
                   1092:       exit(0);
                   1093: 
                   1094:     case EVENT_FORK_ERR:
                   1095:       die(_("cannot fork into background: %s"), NULL, EC_MISC);
                   1096:   
                   1097:     case EVENT_PIPE_ERR:
                   1098:       die(_("failed to create helper: %s"), NULL, EC_MISC);
                   1099:   
                   1100:     case EVENT_CAP_ERR:
                   1101:       die(_("setting capabilities failed: %s"), NULL, EC_MISC);
                   1102: 
                   1103:     case EVENT_USER_ERR:
                   1104:       die(_("failed to change user-id to %s: %s"), msg, EC_MISC);
                   1105: 
                   1106:     case EVENT_GROUP_ERR:
                   1107:       die(_("failed to change group-id to %s: %s"), msg, EC_MISC);
                   1108:       
                   1109:     case EVENT_PIDFILE:
                   1110:       die(_("failed to open pidfile %s: %s"), msg, EC_FILE);
                   1111: 
                   1112:     case EVENT_LOG_ERR:
                   1113:       die(_("cannot open log %s: %s"), msg, EC_FILE);
                   1114:     
                   1115:     case EVENT_LUA_ERR:
                   1116:       die(_("failed to load Lua script: %s"), msg, EC_MISC);
                   1117: 
                   1118:     case EVENT_TFTP_ERR:
                   1119:       die(_("TFTP directory %s inaccessible: %s"), msg, EC_FILE);
                   1120:     }
                   1121: }      
                   1122:       
                   1123: static void async_event(int pipe, time_t now)
                   1124: {
                   1125:   pid_t p;
                   1126:   struct event_desc ev;
1.1.1.2 ! misho    1127:   int i, check = 0;
1.1       misho    1128:   char *msg;
                   1129:   
                   1130:   /* NOTE: the memory used to return msg is leaked: use msgs in events only
                   1131:      to describe fatal errors. */
                   1132:   
                   1133:   if (read_event(pipe, &ev, &msg))
                   1134:     switch (ev.event)
                   1135:       {
                   1136:       case EVENT_RELOAD:
1.1.1.2 ! misho    1137: #ifdef HAVE_DNSSEC
        !          1138:        if (option_bool(OPT_DNSSEC_VALID) && option_bool(OPT_DNSSEC_TIME))
        !          1139:          {
        !          1140:            my_syslog(LOG_INFO, _("now checking DNSSEC signature timestamps"));
        !          1141:            reset_option_bool(OPT_DNSSEC_TIME);
        !          1142:          } 
        !          1143: #endif
        !          1144:        /* fall through */
        !          1145:        
        !          1146:       case EVENT_INIT:
1.1       misho    1147:        clear_cache_and_reload(now);
1.1.1.2 ! misho    1148:        
        !          1149:        if (daemon->port != 0)
1.1       misho    1150:          {
1.1.1.2 ! misho    1151:            if (daemon->resolv_files && option_bool(OPT_NO_POLL))
        !          1152:              {
        !          1153:                reload_servers(daemon->resolv_files->name);
        !          1154:                check = 1;
        !          1155:              }
        !          1156: 
        !          1157:            if (daemon->servers_file)
        !          1158:              {
        !          1159:                read_servers_file();
        !          1160:                check = 1;
        !          1161:              }
        !          1162: 
        !          1163:            if (check)
        !          1164:              check_servers();
1.1       misho    1165:          }
1.1.1.2 ! misho    1166: 
1.1       misho    1167: #ifdef HAVE_DHCP
                   1168:        rerun_scripts();
                   1169: #endif
                   1170:        break;
                   1171:        
                   1172:       case EVENT_DUMP:
                   1173:        if (daemon->port != 0)
                   1174:          dump_cache(now);
                   1175:        break;
                   1176:        
                   1177:       case EVENT_ALARM:
                   1178: #ifdef HAVE_DHCP
                   1179:        if (daemon->dhcp || daemon->doing_dhcp6)
                   1180:          {
                   1181:            lease_prune(NULL, now);
                   1182:            lease_update_file(now);
                   1183:          }
                   1184: #ifdef HAVE_DHCP6
                   1185:        else if (daemon->doing_ra)
                   1186:          /* Not doing DHCP, so no lease system, manage alarms for ra only */
                   1187:            send_alarm(periodic_ra(now), now);
                   1188: #endif
                   1189: #endif
                   1190:        break;
                   1191:                
                   1192:       case EVENT_CHILD:
                   1193:        /* See Stevens 5.10 */
                   1194:        while ((p = waitpid(-1, NULL, WNOHANG)) != 0)
                   1195:          if (p == -1)
                   1196:            {
                   1197:              if (errno != EINTR)
                   1198:                break;
                   1199:            }      
                   1200:          else 
                   1201:            for (i = 0 ; i < MAX_PROCS; i++)
                   1202:              if (daemon->tcp_pids[i] == p)
                   1203:                daemon->tcp_pids[i] = 0;
                   1204:        break;
                   1205:        
                   1206:       case EVENT_KILLED:
                   1207:        my_syslog(LOG_WARNING, _("script process killed by signal %d"), ev.data);
                   1208:        break;
                   1209: 
                   1210:       case EVENT_EXITED:
                   1211:        my_syslog(LOG_WARNING, _("script process exited with status %d"), ev.data);
                   1212:        break;
                   1213: 
                   1214:       case EVENT_EXEC_ERR:
                   1215:        my_syslog(LOG_ERR, _("failed to execute %s: %s"), 
                   1216:                  daemon->lease_change_command, strerror(ev.data));
                   1217:        break;
                   1218: 
                   1219:        /* necessary for fatal errors in helper */
                   1220:       case EVENT_USER_ERR:
                   1221:       case EVENT_DIE:
                   1222:       case EVENT_LUA_ERR:
                   1223:        fatal_event(&ev, msg);
                   1224:        break;
                   1225: 
                   1226:       case EVENT_REOPEN:
                   1227:        /* Note: this may leave TCP-handling processes with the old file still open.
                   1228:           Since any such process will die in CHILD_LIFETIME or probably much sooner,
                   1229:           we leave them logging to the old file. */
                   1230:        if (daemon->log_file != NULL)
                   1231:          log_reopen(daemon->log_file);
                   1232:        break;
                   1233:        
                   1234:       case EVENT_TERM:
                   1235:        /* Knock all our children on the head. */
                   1236:        for (i = 0; i < MAX_PROCS; i++)
                   1237:          if (daemon->tcp_pids[i] != 0)
                   1238:            kill(daemon->tcp_pids[i], SIGALRM);
                   1239:        
                   1240: #if defined(HAVE_SCRIPT)
                   1241:        /* handle pending lease transitions */
                   1242:        if (daemon->helperfd != -1)
                   1243:          {
                   1244:            /* block in writes until all done */
                   1245:            if ((i = fcntl(daemon->helperfd, F_GETFL)) != -1)
                   1246:              fcntl(daemon->helperfd, F_SETFL, i & ~O_NONBLOCK); 
                   1247:            do {
                   1248:              helper_write();
                   1249:            } while (!helper_buf_empty() || do_script_run(now));
                   1250:            close(daemon->helperfd);
                   1251:          }
                   1252: #endif
                   1253:        
                   1254:        if (daemon->lease_stream)
                   1255:          fclose(daemon->lease_stream);
                   1256: 
                   1257:        if (daemon->runfile)
                   1258:          unlink(daemon->runfile);
                   1259:        
                   1260:        my_syslog(LOG_INFO, _("exiting on receipt of SIGTERM"));
                   1261:        flush_log();
                   1262:        exit(EC_GOOD);
                   1263:       }
                   1264: }
                   1265: 
                   1266: void poll_resolv(int force, int do_reload, time_t now)
                   1267: {
                   1268:   struct resolvc *res, *latest;
                   1269:   struct stat statbuf;
                   1270:   time_t last_change = 0;
                   1271:   /* There may be more than one possible file. 
                   1272:      Go through and find the one which changed _last_.
                   1273:      Warn of any which can't be read. */
                   1274: 
                   1275:   if (daemon->port == 0 || option_bool(OPT_NO_POLL))
                   1276:     return;
                   1277:   
                   1278:   for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
                   1279:     if (stat(res->name, &statbuf) == -1)
                   1280:       {
                   1281:        if (force)
                   1282:          {
                   1283:            res->mtime = 0; 
                   1284:            continue;
                   1285:          }
                   1286: 
                   1287:        if (!res->logged)
                   1288:          my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
                   1289:        res->logged = 1;
                   1290:        
                   1291:        if (res->mtime != 0)
                   1292:          { 
                   1293:            /* existing file evaporated, force selection of the latest
                   1294:               file even if its mtime hasn't changed since we last looked */
                   1295:            poll_resolv(1, do_reload, now);
                   1296:            return;
                   1297:          }
                   1298:       }
                   1299:     else
                   1300:       {
                   1301:        res->logged = 0;
                   1302:        if (force || (statbuf.st_mtime != res->mtime))
                   1303:           {
                   1304:             res->mtime = statbuf.st_mtime;
                   1305:            if (difftime(statbuf.st_mtime, last_change) > 0.0)
                   1306:              {
                   1307:                last_change = statbuf.st_mtime;
                   1308:                latest = res;
                   1309:              }
                   1310:          }
                   1311:       }
                   1312:   
                   1313:   if (latest)
                   1314:     {
                   1315:       static int warned = 0;
                   1316:       if (reload_servers(latest->name))
                   1317:        {
                   1318:          my_syslog(LOG_INFO, _("reading %s"), latest->name);
                   1319:          warned = 0;
                   1320:          check_servers();
                   1321:          if (option_bool(OPT_RELOAD) && do_reload)
                   1322:            clear_cache_and_reload(now);
                   1323:        }
                   1324:       else 
                   1325:        {
                   1326:          latest->mtime = 0;
                   1327:          if (!warned)
                   1328:            {
                   1329:              my_syslog(LOG_WARNING, _("no servers found in %s, will retry"), latest->name);
                   1330:              warned = 1;
                   1331:            }
                   1332:        }
                   1333:     }
                   1334: }       
                   1335: 
                   1336: void clear_cache_and_reload(time_t now)
                   1337: {
1.1.1.2 ! misho    1338:   (void)now;
        !          1339: 
1.1       misho    1340:   if (daemon->port != 0)
                   1341:     cache_reload();
                   1342:   
                   1343: #ifdef HAVE_DHCP
                   1344:   if (daemon->dhcp || daemon->doing_dhcp6)
                   1345:     {
                   1346:       if (option_bool(OPT_ETHERS))
                   1347:        dhcp_read_ethers();
                   1348:       reread_dhcp();
                   1349:       dhcp_update_configs(daemon->dhcp_conf);
                   1350:       lease_update_from_configs(); 
                   1351:       lease_update_file(now); 
                   1352:       lease_update_dns(1);
                   1353:     }
                   1354: #ifdef HAVE_DHCP6
                   1355:   else if (daemon->doing_ra)
                   1356:     /* Not doing DHCP, so no lease system, manage 
                   1357:        alarms for ra only */
                   1358:     send_alarm(periodic_ra(now), now);
                   1359: #endif
                   1360: #endif
                   1361: }
                   1362: 
                   1363: static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
                   1364: {
                   1365:   struct serverfd *serverfdp;
                   1366:   struct listener *listener;
                   1367:   int wait = 0, i;
                   1368:   
                   1369: #ifdef HAVE_TFTP
                   1370:   int  tftp = 0;
                   1371:   struct tftp_transfer *transfer;
                   1372:   for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
                   1373:     {
                   1374:       tftp++;
                   1375:       FD_SET(transfer->sockfd, set);
                   1376:       bump_maxfd(transfer->sockfd, maxfdp);
                   1377:     }
                   1378: #endif
                   1379:   
                   1380:   /* will we be able to get memory? */
                   1381:   if (daemon->port != 0)
1.1.1.2 ! misho    1382:     get_new_frec(now, &wait, 0);
1.1       misho    1383:   
                   1384:   for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
                   1385:     {
                   1386:       FD_SET(serverfdp->fd, set);
                   1387:       bump_maxfd(serverfdp->fd, maxfdp);
                   1388:     }
                   1389: 
                   1390:   if (daemon->port != 0 && !daemon->osport)
                   1391:     for (i = 0; i < RANDOM_SOCKS; i++)
                   1392:       if (daemon->randomsocks[i].refcount != 0)
                   1393:        {
                   1394:          FD_SET(daemon->randomsocks[i].fd, set);
                   1395:          bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
                   1396:        }
                   1397:   
                   1398:   for (listener = daemon->listeners; listener; listener = listener->next)
                   1399:     {
                   1400:       /* only listen for queries if we have resources */
                   1401:       if (listener->fd != -1 && wait == 0)
                   1402:        {
                   1403:          FD_SET(listener->fd, set);
                   1404:          bump_maxfd(listener->fd, maxfdp);
                   1405:        }
                   1406: 
                   1407:       /* death of a child goes through the select loop, so
                   1408:         we don't need to explicitly arrange to wake up here */
                   1409:       if  (listener->tcpfd != -1)
                   1410:        for (i = 0; i < MAX_PROCS; i++)
                   1411:          if (daemon->tcp_pids[i] == 0)
                   1412:            {
                   1413:              FD_SET(listener->tcpfd, set);
                   1414:              bump_maxfd(listener->tcpfd, maxfdp);
                   1415:              break;
                   1416:            }
                   1417: 
                   1418: #ifdef HAVE_TFTP
                   1419:       if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
                   1420:        {
                   1421:          FD_SET(listener->tftpfd, set);
                   1422:          bump_maxfd(listener->tftpfd, maxfdp);
                   1423:        }
                   1424: #endif
                   1425: 
                   1426:     }
                   1427:   
                   1428:   return wait;
                   1429: }
                   1430: 
                   1431: static void check_dns_listeners(fd_set *set, time_t now)
                   1432: {
                   1433:   struct serverfd *serverfdp;
                   1434:   struct listener *listener;
                   1435:   int i;
                   1436: 
                   1437:   for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
                   1438:     if (FD_ISSET(serverfdp->fd, set))
                   1439:       reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
                   1440:   
                   1441:   if (daemon->port != 0 && !daemon->osport)
                   1442:     for (i = 0; i < RANDOM_SOCKS; i++)
                   1443:       if (daemon->randomsocks[i].refcount != 0 && 
                   1444:          FD_ISSET(daemon->randomsocks[i].fd, set))
                   1445:        reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
                   1446:   
                   1447:   for (listener = daemon->listeners; listener; listener = listener->next)
                   1448:     {
                   1449:       if (listener->fd != -1 && FD_ISSET(listener->fd, set))
                   1450:        receive_query(listener, now); 
                   1451:       
                   1452: #ifdef HAVE_TFTP     
                   1453:       if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set))
                   1454:        tftp_request(listener, now);
                   1455: #endif
                   1456: 
                   1457:       if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set))
                   1458:        {
                   1459:          int confd, client_ok = 1;
                   1460:          struct irec *iface = NULL;
                   1461:          pid_t p;
                   1462:          union mysockaddr tcp_addr;
                   1463:          socklen_t tcp_len = sizeof(union mysockaddr);
                   1464: 
                   1465:          while ((confd = accept(listener->tcpfd, NULL, NULL)) == -1 && errno == EINTR);
                   1466:          
                   1467:          if (confd == -1)
                   1468:            continue;
1.1.1.2 ! misho    1469:          
1.1       misho    1470:          if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
                   1471:            {
                   1472:              close(confd);
                   1473:              continue;
                   1474:            }
1.1.1.2 ! misho    1475:          
        !          1476:          /* Make sure that the interface list is up-to-date.
        !          1477:             
        !          1478:             We do this here as we may need the results below, and
        !          1479:             the DNS code needs them for --interface-name stuff.
        !          1480: 
        !          1481:             Multiple calls to enumerate_interfaces() per select loop are
        !          1482:             inhibited, so calls to it in the child process (which doesn't select())
        !          1483:             have no effect. This avoids two processes reading from the same
        !          1484:             netlink fd and screwing the pooch entirely.
        !          1485:          */
1.1       misho    1486:  
1.1.1.2 ! misho    1487:          enumerate_interfaces(0);
        !          1488:          
        !          1489:          if (option_bool(OPT_NOWILD))
        !          1490:            iface = listener->iface; /* May be NULL */
        !          1491:          else 
        !          1492:            {
        !          1493:              int if_index;
        !          1494:              char intr_name[IF_NAMESIZE];
        !          1495:              
        !          1496:              /* if we can find the arrival interface, check it's one that's allowed */
        !          1497:              if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
        !          1498:                  indextoname(listener->tcpfd, if_index, intr_name))
        !          1499:                {
        !          1500:                  struct all_addr addr;
        !          1501:                  addr.addr.addr4 = tcp_addr.in.sin_addr;
1.1       misho    1502: #ifdef HAVE_IPV6
1.1.1.2 ! misho    1503:                  if (tcp_addr.sa.sa_family == AF_INET6)
        !          1504:                    addr.addr.addr6 = tcp_addr.in6.sin6_addr;
1.1       misho    1505: #endif
1.1.1.2 ! misho    1506:                  
        !          1507:                  for (iface = daemon->interfaces; iface; iface = iface->next)
        !          1508:                    if (iface->index == if_index)
        !          1509:                      break;
        !          1510:                  
        !          1511:                  if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
        !          1512:                    client_ok = 0;
        !          1513:                }
        !          1514:              
        !          1515:              if (option_bool(OPT_CLEVERBIND))
        !          1516:                iface = listener->iface; /* May be NULL */
        !          1517:              else
        !          1518:                {
        !          1519:                  /* Check for allowed interfaces when binding the wildcard address:
        !          1520:                     we do this by looking for an interface with the same address as 
        !          1521:                     the local address of the TCP connection, then looking to see if that's
        !          1522:                     an allowed interface. As a side effect, we get the netmask of the
        !          1523:                     interface too, for localisation. */
        !          1524:                  
        !          1525:                  for (iface = daemon->interfaces; iface; iface = iface->next)
        !          1526:                    if (sockaddr_isequal(&iface->addr, &tcp_addr))
        !          1527:                      break;
        !          1528:                  
        !          1529:                  if (!iface)
        !          1530:                    client_ok = 0;
        !          1531:                }
        !          1532:            }
        !          1533:          
1.1       misho    1534:          if (!client_ok)
                   1535:            {
                   1536:              shutdown(confd, SHUT_RDWR);
                   1537:              close(confd);
                   1538:            }
                   1539: #ifndef NO_FORK
                   1540:          else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
                   1541:            {
                   1542:              if (p != -1)
                   1543:                {
                   1544:                  int i;
                   1545:                  for (i = 0; i < MAX_PROCS; i++)
                   1546:                    if (daemon->tcp_pids[i] == 0)
                   1547:                      {
                   1548:                        daemon->tcp_pids[i] = p;
                   1549:                        break;
                   1550:                      }
                   1551:                }
                   1552:              close(confd);
                   1553:            }
                   1554: #endif
                   1555:          else
                   1556:            {
                   1557:              unsigned char *buff;
                   1558:              struct server *s; 
                   1559:              int flags;
                   1560:              struct in_addr netmask;
                   1561:              int auth_dns;
                   1562: 
                   1563:              if (iface)
                   1564:                {
                   1565:                  netmask = iface->netmask;
                   1566:                  auth_dns = iface->dns_auth;
                   1567:                }
                   1568:              else
                   1569:                {
                   1570:                  netmask.s_addr = 0;
                   1571:                  auth_dns = 0;
                   1572:                }
                   1573: 
                   1574: #ifndef NO_FORK
                   1575:              /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
                   1576:                 terminate the process. */
                   1577:              if (!option_bool(OPT_DEBUG))
                   1578:                alarm(CHILD_LIFETIME);
                   1579: #endif
                   1580: 
                   1581:              /* start with no upstream connections. */
                   1582:              for (s = daemon->servers; s; s = s->next)
                   1583:                 s->tcpfd = -1; 
                   1584:              
                   1585:              /* The connected socket inherits non-blocking
                   1586:                 attribute from the listening socket. 
                   1587:                 Reset that here. */
                   1588:              if ((flags = fcntl(confd, F_GETFL, 0)) != -1)
                   1589:                fcntl(confd, F_SETFL, flags & ~O_NONBLOCK);
                   1590:              
                   1591:              buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
                   1592:               
                   1593:              shutdown(confd, SHUT_RDWR);
                   1594:              close(confd);
                   1595:              
                   1596:              if (buff)
                   1597:                free(buff);
                   1598:              
                   1599:              for (s = daemon->servers; s; s = s->next)
                   1600:                if (s->tcpfd != -1)
                   1601:                  {
                   1602:                    shutdown(s->tcpfd, SHUT_RDWR);
                   1603:                    close(s->tcpfd);
                   1604:                  }
                   1605: #ifndef NO_FORK                   
                   1606:              if (!option_bool(OPT_DEBUG))
                   1607:                {
                   1608:                  flush_log();
                   1609:                  _exit(0);
                   1610:                }
                   1611: #endif
                   1612:            }
                   1613:        }
                   1614:     }
                   1615: }
                   1616: 
                   1617: #ifdef HAVE_DHCP
                   1618: int make_icmp_sock(void)
                   1619: {
                   1620:   int fd;
                   1621:   int zeroopt = 0;
                   1622: 
                   1623:   if ((fd = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP)) != -1)
                   1624:     {
                   1625:       if (!fix_fd(fd) ||
                   1626:          setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &zeroopt, sizeof(zeroopt)) == -1)
                   1627:        {
                   1628:          close(fd);
                   1629:          fd = -1;
                   1630:        }
                   1631:     }
                   1632: 
                   1633:   return fd;
                   1634: }
                   1635: 
                   1636: int icmp_ping(struct in_addr addr)
                   1637: {
                   1638:   /* Try and get an ICMP echo from a machine. */
                   1639: 
                   1640:   /* Note that whilst in the three second wait, we check for 
                   1641:      (and service) events on the DNS and TFTP  sockets, (so doing that
                   1642:      better not use any resources our caller has in use...)
                   1643:      but we remain deaf to signals or further DHCP packets. */
                   1644: 
                   1645:   int fd;
                   1646:   struct sockaddr_in saddr;
                   1647:   struct { 
                   1648:     struct ip ip;
                   1649:     struct icmp icmp;
                   1650:   } packet;
                   1651:   unsigned short id = rand16();
                   1652:   unsigned int i, j;
                   1653:   int gotreply = 0;
                   1654:   time_t start, now;
                   1655: 
                   1656: #if defined(HAVE_LINUX_NETWORK) || defined (HAVE_SOLARIS_NETWORK)
                   1657:   if ((fd = make_icmp_sock()) == -1)
                   1658:     return 0;
                   1659: #else
                   1660:   int opt = 2000;
                   1661:   fd = daemon->dhcp_icmp_fd;
                   1662:   setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
                   1663: #endif
                   1664: 
                   1665:   saddr.sin_family = AF_INET;
                   1666:   saddr.sin_port = 0;
                   1667:   saddr.sin_addr = addr;
                   1668: #ifdef HAVE_SOCKADDR_SA_LEN
                   1669:   saddr.sin_len = sizeof(struct sockaddr_in);
                   1670: #endif
                   1671:   
                   1672:   memset(&packet.icmp, 0, sizeof(packet.icmp));
                   1673:   packet.icmp.icmp_type = ICMP_ECHO;
                   1674:   packet.icmp.icmp_id = id;
                   1675:   for (j = 0, i = 0; i < sizeof(struct icmp) / 2; i++)
                   1676:     j += ((u16 *)&packet.icmp)[i];
                   1677:   while (j>>16)
                   1678:     j = (j & 0xffff) + (j >> 16);  
                   1679:   packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
                   1680:   
                   1681:   while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, 
                   1682:                (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
                   1683:         retry_send());
                   1684:   
                   1685:   for (now = start = dnsmasq_time(); 
                   1686:        difftime(now, start) < (float)PING_WAIT;)
                   1687:     {
                   1688:       struct timeval tv;
                   1689:       fd_set rset, wset;
                   1690:       struct sockaddr_in faddr;
                   1691:       int maxfd = fd; 
                   1692:       socklen_t len = sizeof(faddr);
                   1693:       
                   1694:       tv.tv_usec = 250000;
                   1695:       tv.tv_sec = 0; 
                   1696:       
                   1697:       FD_ZERO(&rset);
                   1698:       FD_ZERO(&wset);
                   1699:       FD_SET(fd, &rset);
                   1700:       set_dns_listeners(now, &rset, &maxfd);
                   1701:       set_log_writer(&wset, &maxfd);
                   1702:       
                   1703: #ifdef HAVE_DHCP6
                   1704:       if (daemon->doing_ra)
                   1705:        {
                   1706:          FD_SET(daemon->icmp6fd, &rset);
                   1707:          bump_maxfd(daemon->icmp6fd, &maxfd); 
                   1708:        }
                   1709: #endif
                   1710:       
                   1711:       if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0)
                   1712:        {
                   1713:          FD_ZERO(&rset);
                   1714:          FD_ZERO(&wset);
                   1715:        }
                   1716: 
                   1717:       now = dnsmasq_time();
                   1718: 
                   1719:       check_log_writer(&wset);
                   1720:       check_dns_listeners(&rset, now);
                   1721: 
                   1722: #ifdef HAVE_DHCP6
                   1723:       if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset))
                   1724:        icmp6_packet(now);
                   1725: #endif
                   1726:       
                   1727: #ifdef HAVE_TFTP
                   1728:       check_tftp_listeners(&rset, now);
                   1729: #endif
                   1730: 
                   1731:       if (FD_ISSET(fd, &rset) &&
                   1732:          recvfrom(fd, &packet, sizeof(packet), 0,
                   1733:                   (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
                   1734:          saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
                   1735:          packet.icmp.icmp_type == ICMP_ECHOREPLY &&
                   1736:          packet.icmp.icmp_seq == 0 &&
                   1737:          packet.icmp.icmp_id == id)
                   1738:        {
                   1739:          gotreply = 1;
                   1740:          break;
                   1741:        }
                   1742:     }
                   1743:   
                   1744: #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
                   1745:   close(fd);
                   1746: #else
                   1747:   opt = 1;
                   1748:   setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
                   1749: #endif
                   1750: 
                   1751:   return gotreply;
                   1752: }
                   1753: #endif
                   1754: 
                   1755:  

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>