-/* dnsmasq is Copyright (c) 2000-2010 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2011 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
static void sig_handler(int sig);
static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev);
-static void poll_resolv(void);
int main (int argc, char **argv)
{
#elif !(defined(IP_RECVDSTADDR) && \
defined(IP_RECVIF) && \
defined(IP_SENDSRCADDR))
- if (!(daemon->options & OPT_NOWILD))
+ if (!option_bool(OPT_NOWILD))
{
bind_fallback = 1;
- daemon->options |= OPT_NOWILD;
+ set_option_bool(OPT_NOWILD);
}
#endif
#ifndef HAVE_TFTP
- if (daemon->options & OPT_TFTP)
+ if (daemon->tftp_unlimited || daemon->tftp_interfaces)
die(_("TFTP server not available: set HAVE_TFTP in src/config.h"), NULL, EC_BADCONF);
#endif
if (!enumerate_interfaces())
die(_("failed to find list of interfaces: %s"), NULL, EC_MISC);
- if (daemon->options & OPT_NOWILD)
+ if (option_bool(OPT_NOWILD))
{
daemon->listeners = create_bound_listeners();
die(_("no interface with address %s"), daemon->namebuff, EC_BADNET);
}
}
- else if ((daemon->port != 0 || (daemon->options & OPT_TFTP)) &&
- !(daemon->listeners = create_wildcard_listeners()))
- die(_("failed to create listening socket: %s"), NULL, EC_BADNET);
+ else
+ daemon->listeners = create_wildcard_listeners();
if (daemon->port != 0)
cache_init();
- if (daemon->options & OPT_DBUS)
+ if (option_bool(OPT_DBUS))
#ifdef HAVE_DBUS
{
char *err;
err_pipe[1] = -1;
- if (!(daemon->options & OPT_DEBUG))
+ if (!option_bool(OPT_DEBUG))
{
- int nullfd;
-
/* The following code "daemonizes" the process.
See Stevens section 12.4 */
die(_("cannot chdir to filesystem root: %s"), NULL, EC_MISC);
#ifndef NO_FORK
- if (!(daemon->options & OPT_NO_FORK))
+ if (!option_bool(OPT_NO_FORK))
{
pid_t pid;
_exit(0);
}
}
-
- /* open stdout etc to /dev/null */
- nullfd = open("/dev/null", O_RDWR);
- dup2(nullfd, STDOUT_FILENO);
- dup2(nullfd, STDERR_FILENO);
- dup2(nullfd, STDIN_FILENO);
- close(nullfd);
}
- log_err = log_start(ent_pw, err_pipe[1]);
+ log_err = log_start(ent_pw, err_pipe[1]);
+
+ if (!option_bool(OPT_DEBUG))
+ {
+ /* open stdout etc to /dev/null */
+ int nullfd = open("/dev/null", O_RDWR);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ dup2(nullfd, STDIN_FILENO);
+ close(nullfd);
+ }
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon->helperfd = -1;
daemon->helperfd = create_helper(pipewrite, err_pipe[1], script_uid, script_gid, max_fd);
#endif
- if (!(daemon->options & OPT_DEBUG) && getuid() == 0)
+ if (!option_bool(OPT_DEBUG) && getuid() == 0)
{
int bad_capabilities = 0;
gid_t dummy;
}
#ifdef HAVE_LINUX_NETWORK
- if (daemon->options & OPT_DEBUG)
+ if (option_bool(OPT_DEBUG))
prctl(PR_SET_DUMPABLE, 1);
#endif
my_syslog(LOG_INFO, _("compile time options: %s"), compile_opts);
#ifdef HAVE_DBUS
- if (daemon->options & OPT_DBUS)
+ if (option_bool(OPT_DBUS))
{
if (daemon->dbus)
my_syslog(LOG_INFO, _("DBus support enabled: connected to system bus"));
if (bind_fallback)
my_syslog(LOG_WARNING, _("setting --bind-interfaces option because of OS limitations"));
- if (!(daemon->options & OPT_NOWILD))
+ if (!option_bool(OPT_NOWILD))
for (if_tmp = daemon->if_names; if_tmp; if_tmp = if_tmp->next)
if (if_tmp->name && !if_tmp->used)
my_syslog(LOG_WARNING, _("warning: interface %s does not currently exist"), if_tmp->name);
- if (daemon->port != 0 && (daemon->options & OPT_NO_RESOLV))
+ if (daemon->port != 0 && option_bool(OPT_NO_RESOLV))
{
if (daemon->resolv_files && !daemon->resolv_files->is_default)
my_syslog(LOG_WARNING, _("warning: ignoring resolv-file flag because no-resolv is set"));
#endif
#ifdef HAVE_TFTP
- if (daemon->options & OPT_TFTP)
+ if (daemon->tftp_unlimited || daemon->tftp_interfaces)
{
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
daemon->tftp_prefix ? _("root is ") : _("enabled"),
daemon->tftp_prefix ? daemon->tftp_prefix: "",
- daemon->options & OPT_TFTP_SECURE ? _("secure mode") : "");
+ option_bool(OPT_TFTP_SECURE) ? _("secure mode") : "");
/* This is a guess, it assumes that for small limits,
disjoint files might be served, but for large limits,
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
if (daemon->tftp_trans ||
- ((daemon->options & OPT_DBUS) && !daemon->dbus))
+ (option_bool(OPT_DBUS) && !daemon->dbus))
{
t.tv_sec = 0;
t.tv_usec = 250000;
check_log_writer(&wset);
+#ifdef HAVE_LINUX_NETWORK
+ if (FD_ISSET(daemon->netlinkfd, &rset))
+ netlink_multicast();
+#endif
+
/* Check for changes to resolv files once per second max. */
/* Don't go silent for long periods if the clock goes backwards. */
if (daemon->last_resolv == 0 ||
difftime(now, daemon->last_resolv) > 1.0 ||
difftime(now, daemon->last_resolv) < -1.0)
{
- daemon->last_resolv = now;
+ /* poll_resolv doesn't need to reload first time through, since
+ that's queued anyway. */
- if (daemon->port != 0 && !(daemon->options & OPT_NO_POLL))
- poll_resolv();
+ poll_resolv(0, daemon->last_resolv != 0, now);
+ daemon->last_resolv = now;
}
if (FD_ISSET(piperead, &rset))
async_event(piperead, now);
-#ifdef HAVE_LINUX_NETWORK
- if (FD_ISSET(daemon->netlinkfd, &rset))
- netlink_multicast();
-#endif
-
#ifdef HAVE_DBUS
/* if we didn't create a DBus connection, retry now. */
- if ((daemon->options & OPT_DBUS) && !daemon->dbus)
+ if (option_bool(OPT_DBUS) && !daemon->dbus)
{
char *err;
if ((err = dbus_init()))
{
case EVENT_RELOAD:
clear_cache_and_reload(now);
- if (daemon->port != 0 && daemon->resolv_files && (daemon->options & OPT_NO_POLL))
+ if (daemon->port != 0 && daemon->resolv_files && option_bool(OPT_NO_POLL))
{
reload_servers(daemon->resolv_files->name);
check_servers();
}
}
-static void poll_resolv()
+void poll_resolv(int force, int do_reload, time_t now)
{
struct resolvc *res, *latest;
struct stat statbuf;
/* There may be more than one possible file.
Go through and find the one which changed _last_.
Warn of any which can't be read. */
+
+ if (daemon->port == 0 || option_bool(OPT_NO_POLL))
+ return;
+
for (latest = NULL, res = daemon->resolv_files; res; res = res->next)
if (stat(res->name, &statbuf) == -1)
{
+ if (force)
+ {
+ res->mtime = 0;
+ continue;
+ }
+
if (!res->logged)
my_syslog(LOG_WARNING, _("failed to access %s: %s"), res->name, strerror(errno));
res->logged = 1;
+
+ if (res->mtime != 0)
+ {
+ /* existing file evaporated, force selection of the latest
+ file even if its mtime hasn't changed since we last looked */
+ poll_resolv(1, do_reload, now);
+ return;
+ }
}
else
{
res->logged = 0;
- if (statbuf.st_mtime != res->mtime)
- {
- res->mtime = statbuf.st_mtime;
+ if (force || (statbuf.st_mtime != res->mtime))
+ {
+ res->mtime = statbuf.st_mtime;
if (difftime(statbuf.st_mtime, last_change) > 0.0)
{
last_change = statbuf.st_mtime;
my_syslog(LOG_INFO, _("reading %s"), latest->name);
warned = 0;
check_servers();
- if (daemon->options & OPT_RELOAD)
- cache_reload();
+ if (option_bool(OPT_RELOAD) && do_reload)
+ clear_cache_and_reload(now);
}
else
{
#ifdef HAVE_DHCP
if (daemon->dhcp)
{
- if (daemon->options & OPT_ETHERS)
+ if (option_bool(OPT_ETHERS))
dhcp_read_ethers();
reread_dhcp();
dhcp_update_configs(daemon->dhcp_conf);
if (confd == -1)
continue;
- if (daemon->options & OPT_NOWILD)
+ if (option_bool(OPT_NOWILD))
iface = listener->iface;
else
{
close(confd);
}
#ifndef NO_FORK
- else if (!(daemon->options & OPT_DEBUG) && (p = fork()) != 0)
+ else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
{
if (p != -1)
{
dst_addr_4.s_addr = 0;
- /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
- terminate the process. */
- if (!(daemon->options & OPT_DEBUG))
+#ifndef NO_FORK
+ /* Arrange for SIGALARM after CHILD_LIFETIME seconds to
+ terminate the process. */
+ if (!option_bool(OPT_DEBUG))
alarm(CHILD_LIFETIME);
-
+#endif
+
/* start with no upstream connections. */
for (s = daemon->servers; s; s = s->next)
s->tcpfd = -1;
close(s->tcpfd);
}
#ifndef NO_FORK
- if (!(daemon->options & OPT_DEBUG))
+ if (!option_bool(OPT_DEBUG))
{
flush_log();
_exit(0);