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