Compare commits

...
9 Commits
15 changed files with 318 additions and 188 deletions

No files matched your search

+8
View File
@@ -1,3 +1,11 @@
version 2.74
Fix reversion in 2.73 where --conf-file would attempt to
read the default file, rather than no file.
Fix inotify code to handle dangling symlinks better and
not SEGV in some circumstances.
version 2.73 version 2.73
Fix crash at startup when an empty suffix is supplied to Fix crash at startup when an empty suffix is supplied to
--conf-dir, also trivial memory leak. Thanks to --conf-dir, also trivial memory leak. Thanks to
+1 -1
View File
@@ -73,7 +73,7 @@ objs = cache.o rfc1035.o util.o option.o forward.o network.o \
dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \ dnsmasq.o dhcp.o lease.o rfc2131.o netlink.o dbus.o bpf.o \
helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \ helper.o tftp.o log.o conntrack.o dhcp6.o rfc3315.o \
dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \ dhcp-common.o outpacket.o radv.o slaac.o auth.o ipset.o \
domain.o dnssec.o blockdata.o tables.o loop.o inotify.o domain.o dnssec.o blockdata.o tables.o loop.o inotify.o poll.o
hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \ hdrs = dnsmasq.h config.h dhcp-protocol.h dhcp6-protocol.h \
dns-protocol.h radv-protocol.h ip6addr.h dns-protocol.h radv-protocol.h ip6addr.h
+1 -1
View File
@@ -10,7 +10,7 @@ LOCAL_SRC_FILES := bpf.c cache.c dbus.c dhcp.c dnsmasq.c \
dhcp6.c rfc3315.c dhcp-common.c outpacket.c \ dhcp6.c rfc3315.c dhcp-common.c outpacket.c \
radv.c slaac.c auth.c ipset.c domain.c \ radv.c slaac.c auth.c ipset.c domain.c \
dnssec.c dnssec-openssl.c blockdata.c tables.c \ dnssec.c dnssec-openssl.c blockdata.c tables.c \
loop.c inotify.c loop.c inotify.c poll.c
LOCAL_MODULE := dnsmasq LOCAL_MODULE := dnsmasq
+12
View File
@@ -1,3 +1,15 @@
dnsmasq (2.74-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:54:11 +0000
dnsmasq (2.73-2) unstable; urgency=low
* Fix behaviour of empty --conf-file (closes: #790341)
-- Simon Kelley <simon@thekelleys.org.uk> Thu, 7 Jul 2015 21:46:42 +0000
dnsmasq (2.73-1) unstable; urgency=low dnsmasq (2.73-1) unstable; urgency=low
* New upstream. (closes: #786996) * New upstream. (closes: #786996)
+1 -1
View File
@@ -654,7 +654,7 @@ Provide DS records to act a trust anchors for DNSSEC
validation. Typically these will be the DS record(s) for Zone Signing validation. Typically these will be the DS record(s) for Zone Signing
key(s) of the root zone, key(s) of the root zone,
but trust anchors for limited domains are also possible. The current but trust anchors for limited domains are also possible. The current
root-zone trust anchors may be donwloaded from https://data.iana.org/root-anchors/root-anchors.xml root-zone trust anchors may be downloaded from https://data.iana.org/root-anchors/root-anchors.xml
.TP .TP
.B --dnssec-check-unsigned .B --dnssec-check-unsigned
As a default, dnsmasq does not check that unsigned DNS replies are As a default, dnsmasq does not check that unsigned DNS replies are
+8 -11
View File
@@ -749,8 +749,7 @@ char *dbus_init(void)
} }
void set_dbus_listeners(int *maxfdp, void set_dbus_listeners(void)
fd_set *rset, fd_set *wset, fd_set *eset)
{ {
struct watch *w; struct watch *w;
@@ -760,19 +759,17 @@ void set_dbus_listeners(int *maxfdp,
unsigned int flags = dbus_watch_get_flags(w->watch); unsigned int flags = dbus_watch_get_flags(w->watch);
int fd = dbus_watch_get_unix_fd(w->watch); int fd = dbus_watch_get_unix_fd(w->watch);
bump_maxfd(fd, maxfdp);
if (flags & DBUS_WATCH_READABLE) if (flags & DBUS_WATCH_READABLE)
FD_SET(fd, rset); poll_listen(fd, POLLIN);
if (flags & DBUS_WATCH_WRITABLE) if (flags & DBUS_WATCH_WRITABLE)
FD_SET(fd, wset); poll_listen(fd, POLLOUT);
FD_SET(fd, eset); poll_listen(fd, POLLERR);
} }
} }
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset) void check_dbus_listeners()
{ {
DBusConnection *connection = (DBusConnection *)daemon->dbus; DBusConnection *connection = (DBusConnection *)daemon->dbus;
struct watch *w; struct watch *w;
@@ -783,13 +780,13 @@ void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset)
unsigned int flags = 0; unsigned int flags = 0;
int fd = dbus_watch_get_unix_fd(w->watch); int fd = dbus_watch_get_unix_fd(w->watch);
if (FD_ISSET(fd, rset)) if (poll_check(fd, POLLIN))
flags |= DBUS_WATCH_READABLE; flags |= DBUS_WATCH_READABLE;
if (FD_ISSET(fd, wset)) if (poll_check(fd, POLLOUT))
flags |= DBUS_WATCH_WRITABLE; flags |= DBUS_WATCH_WRITABLE;
if (FD_ISSET(fd, eset)) if (poll_check(fd, POLLERR))
flags |= DBUS_WATCH_ERROR; flags |= DBUS_WATCH_ERROR;
if (flags != 0) if (flags != 0)
+76 -131
View File
@@ -24,8 +24,8 @@ struct daemon *daemon;
static volatile pid_t pid = 0; static volatile pid_t pid = 0;
static volatile int pipewrite; static volatile int pipewrite;
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp); static int set_dns_listeners(time_t now);
static void check_dns_listeners(fd_set *set, time_t now); static void check_dns_listeners(time_t now);
static void sig_handler(int sig); static void sig_handler(int sig);
static void async_event(int pipe, time_t now); static void async_event(int pipe, time_t now);
static void fatal_event(struct event_desc *ev, char *msg); static void fatal_event(struct event_desc *ev, char *msg);
@@ -799,10 +799,6 @@ int main (int argc, char **argv)
if (option_bool(OPT_TFTP)) if (option_bool(OPT_TFTP))
{ {
struct tftp_prefix *p; struct tftp_prefix *p;
#ifdef FD_SETSIZE
if (FD_SETSIZE < (unsigned)max_fd)
max_fd = FD_SETSIZE;
#endif
my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s", my_syslog(MS_TFTP | LOG_INFO, "TFTP %s%s %s",
daemon->tftp_prefix ? _("root is ") : _("enabled"), daemon->tftp_prefix ? _("root is ") : _("enabled"),
@@ -862,88 +858,58 @@ int main (int argc, char **argv)
while (1) while (1)
{ {
int maxfd = -1; int t, timeout = -1;
struct timeval t, *tp = NULL;
fd_set rset, wset, eset;
FD_ZERO(&rset); poll_reset();
FD_ZERO(&wset);
FD_ZERO(&eset);
/* if we are out of resources, find how long we have to wait /* if we are out of resources, find how long we have to wait
for some to come free, we'll loop around then and restart for some to come free, we'll loop around then and restart
listening for queries */ listening for queries */
if ((t.tv_sec = set_dns_listeners(now, &rset, &maxfd)) != 0) if ((t = set_dns_listeners(now)) != 0)
{ timeout = t * 1000;
t.tv_usec = 0;
tp = &t;
}
/* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */ /* Whilst polling for the dbus, or doing a tftp transfer, wake every quarter second */
if (daemon->tftp_trans || if (daemon->tftp_trans ||
(option_bool(OPT_DBUS) && !daemon->dbus)) (option_bool(OPT_DBUS) && !daemon->dbus))
{ timeout = 250;
t.tv_sec = 0;
t.tv_usec = 250000;
tp = &t;
}
/* Wake every second whilst waiting for DAD to complete */ /* Wake every second whilst waiting for DAD to complete */
else if (is_dad_listeners()) else if (is_dad_listeners())
{ timeout = 1000;
t.tv_sec = 1;
t.tv_usec = 0;
tp = &t;
}
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
set_dbus_listeners(&maxfd, &rset, &wset, &eset); set_dbus_listeners();
#endif #endif
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (daemon->dhcp || daemon->relay4) if (daemon->dhcp || daemon->relay4)
{ {
FD_SET(daemon->dhcpfd, &rset); poll_listen(daemon->dhcpfd, POLLIN);
bump_maxfd(daemon->dhcpfd, &maxfd);
if (daemon->pxefd != -1) if (daemon->pxefd != -1)
{ poll_listen(daemon->pxefd, POLLIN);
FD_SET(daemon->pxefd, &rset);
bump_maxfd(daemon->pxefd, &maxfd);
}
} }
#endif #endif
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
if (daemon->doing_dhcp6 || daemon->relay6) if (daemon->doing_dhcp6 || daemon->relay6)
{ poll_listen(daemon->dhcp6fd, POLLIN);
FD_SET(daemon->dhcp6fd, &rset);
bump_maxfd(daemon->dhcp6fd, &maxfd);
}
if (daemon->doing_ra) if (daemon->doing_ra)
{ poll_listen(daemon->icmp6fd, POLLIN);
FD_SET(daemon->icmp6fd, &rset);
bump_maxfd(daemon->icmp6fd, &maxfd);
}
#endif #endif
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
if (daemon->inotifyfd != -1) if (daemon->inotifyfd != -1)
{ poll_listen(daemon->inotifyfd, POLLIN);
FD_SET(daemon->inotifyfd, &rset);
bump_maxfd(daemon->inotifyfd, &maxfd);
}
#endif #endif
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
FD_SET(daemon->netlinkfd, &rset); poll_listen(daemon->netlinkfd, POLLIN);
bump_maxfd(daemon->netlinkfd, &maxfd);
#elif defined(HAVE_BSD_NETWORK) #elif defined(HAVE_BSD_NETWORK)
FD_SET(daemon->routefd, &rset); poll_listen(daemon->routefd, POLLIN);
bump_maxfd(daemon->routefd, &maxfd);
#endif #endif
FD_SET(piperead, &rset); poll_listen(piperead, POLLIN);
bump_maxfd(piperead, &maxfd);
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
# ifdef HAVE_SCRIPT # ifdef HAVE_SCRIPT
@@ -954,10 +920,7 @@ int main (int argc, char **argv)
# endif # endif
if (!helper_buf_empty()) if (!helper_buf_empty())
{ poll_listen(daemon->helperfd, POLLOUT);
FD_SET(daemon->helperfd, &wset);
bump_maxfd(daemon->helperfd, &maxfd);
}
# else # else
/* need this for other side-effects */ /* need this for other side-effects */
while (do_script_run(now)); while (do_script_run(now));
@@ -971,17 +934,14 @@ int main (int argc, char **argv)
/* must do this just before select(), when we know no /* must do this just before select(), when we know no
more calls to my_syslog() can occur */ more calls to my_syslog() can occur */
set_log_writer(&wset, &maxfd); set_log_writer();
if (select(maxfd+1, &rset, &wset, &eset, tp) < 0) if (do_poll(timeout) < 0)
{ continue;
/* otherwise undefined after error */
FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&eset);
}
now = dnsmasq_time(); now = dnsmasq_time();
check_log_writer(&wset); check_log_writer(0);
/* prime. */ /* prime. */
enumerate_interfaces(1); enumerate_interfaces(1);
@@ -997,15 +957,15 @@ int main (int argc, char **argv)
} }
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
if (FD_ISSET(daemon->netlinkfd, &rset)) if (poll_check(daemon->netlinkfd, POLLIN))
netlink_multicast(); netlink_multicast();
#elif defined(HAVE_BSD_NETWORK) #elif defined(HAVE_BSD_NETWORK)
if (FD_ISSET(daemon->routefd, &rset)) if (poll_check(daemon->routefd, POLLIN))
route_sock(); route_sock();
#endif #endif
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
if (daemon->inotifyfd != -1 && FD_ISSET(daemon->inotifyfd, &rset) && inotify_check(now)) if (daemon->inotifyfd != -1 && poll_check(daemon->inotifyfd, POLLIN) && inotify_check(now))
{ {
if (daemon->port != 0 && !option_bool(OPT_NO_POLL)) if (daemon->port != 0 && !option_bool(OPT_NO_POLL))
poll_resolv(1, 1, now); poll_resolv(1, 1, now);
@@ -1025,7 +985,7 @@ int main (int argc, char **argv)
} }
#endif #endif
if (FD_ISSET(piperead, &rset)) if (poll_check(piperead, POLLIN))
async_event(piperead, now); async_event(piperead, now);
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
@@ -1038,34 +998,34 @@ int main (int argc, char **argv)
if (daemon->dbus) if (daemon->dbus)
my_syslog(LOG_INFO, _("connected to system DBus")); my_syslog(LOG_INFO, _("connected to system DBus"));
} }
check_dbus_listeners(&rset, &wset, &eset); check_dbus_listeners();
#endif #endif
check_dns_listeners(&rset, now); check_dns_listeners(now);
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
check_tftp_listeners(&rset, now); check_tftp_listeners(now);
#endif #endif
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
if (daemon->dhcp || daemon->relay4) if (daemon->dhcp || daemon->relay4)
{ {
if (FD_ISSET(daemon->dhcpfd, &rset)) if (poll_check(daemon->dhcpfd, POLLIN))
dhcp_packet(now, 0); dhcp_packet(now, 0);
if (daemon->pxefd != -1 && FD_ISSET(daemon->pxefd, &rset)) if (daemon->pxefd != -1 && poll_check(daemon->pxefd, POLLIN))
dhcp_packet(now, 1); dhcp_packet(now, 1);
} }
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
if ((daemon->doing_dhcp6 || daemon->relay6) && FD_ISSET(daemon->dhcp6fd, &rset)) if ((daemon->doing_dhcp6 || daemon->relay6) && poll_check(daemon->dhcp6fd, POLLIN))
dhcp6_packet(now); dhcp6_packet(now);
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset)) if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
icmp6_packet(now); icmp6_packet(now);
#endif #endif
# ifdef HAVE_SCRIPT # ifdef HAVE_SCRIPT
if (daemon->helperfd != -1 && FD_ISSET(daemon->helperfd, &wset)) if (daemon->helperfd != -1 && poll_check(daemon->helperfd, POLLIN))
helper_write(); helper_write();
# endif # endif
#endif #endif
@@ -1470,7 +1430,7 @@ void clear_cache_and_reload(time_t now)
#endif #endif
} }
static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp) static int set_dns_listeners(time_t now)
{ {
struct serverfd *serverfdp; struct serverfd *serverfdp;
struct listener *listener; struct listener *listener;
@@ -1482,8 +1442,7 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next) for (transfer = daemon->tftp_trans; transfer; transfer = transfer->next)
{ {
tftp++; tftp++;
FD_SET(transfer->sockfd, set); poll_listen(transfer->sockfd, POLLIN);
bump_maxfd(transfer->sockfd, maxfdp);
} }
#endif #endif
@@ -1492,27 +1451,18 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
get_new_frec(now, &wait, 0); get_new_frec(now, &wait, 0);
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
{ poll_listen(serverfdp->fd, POLLIN);
FD_SET(serverfdp->fd, set);
bump_maxfd(serverfdp->fd, maxfdp);
}
if (daemon->port != 0 && !daemon->osport) if (daemon->port != 0 && !daemon->osport)
for (i = 0; i < RANDOM_SOCKS; i++) for (i = 0; i < RANDOM_SOCKS; i++)
if (daemon->randomsocks[i].refcount != 0) if (daemon->randomsocks[i].refcount != 0)
{ poll_listen(daemon->randomsocks[i].fd, POLLIN);
FD_SET(daemon->randomsocks[i].fd, set);
bump_maxfd(daemon->randomsocks[i].fd, maxfdp);
}
for (listener = daemon->listeners; listener; listener = listener->next) for (listener = daemon->listeners; listener; listener = listener->next)
{ {
/* only listen for queries if we have resources */ /* only listen for queries if we have resources */
if (listener->fd != -1 && wait == 0) if (listener->fd != -1 && wait == 0)
{ poll_listen(listener->fd, POLLIN);
FD_SET(listener->fd, set);
bump_maxfd(listener->fd, maxfdp);
}
/* death of a child goes through the select loop, so /* death of a child goes through the select loop, so
we don't need to explicitly arrange to wake up here */ we don't need to explicitly arrange to wake up here */
@@ -1520,17 +1470,13 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
for (i = 0; i < MAX_PROCS; i++) for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0) if (daemon->tcp_pids[i] == 0)
{ {
FD_SET(listener->tcpfd, set); poll_listen(listener->tcpfd, POLLIN);
bump_maxfd(listener->tcpfd, maxfdp);
break; break;
} }
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
if (tftp <= daemon->tftp_max && listener->tftpfd != -1) if (tftp <= daemon->tftp_max && listener->tftpfd != -1)
{ poll_listen(listener->tftpfd, POLLIN);
FD_SET(listener->tftpfd, set);
bump_maxfd(listener->tftpfd, maxfdp);
}
#endif #endif
} }
@@ -1538,33 +1484,33 @@ static int set_dns_listeners(time_t now, fd_set *set, int *maxfdp)
return wait; return wait;
} }
static void check_dns_listeners(fd_set *set, time_t now) static void check_dns_listeners(time_t now)
{ {
struct serverfd *serverfdp; struct serverfd *serverfdp;
struct listener *listener; struct listener *listener;
int i; int i;
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next) for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
if (FD_ISSET(serverfdp->fd, set)) if (poll_check(serverfdp->fd, POLLIN))
reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now); reply_query(serverfdp->fd, serverfdp->source_addr.sa.sa_family, now);
if (daemon->port != 0 && !daemon->osport) if (daemon->port != 0 && !daemon->osport)
for (i = 0; i < RANDOM_SOCKS; i++) for (i = 0; i < RANDOM_SOCKS; i++)
if (daemon->randomsocks[i].refcount != 0 && if (daemon->randomsocks[i].refcount != 0 &&
FD_ISSET(daemon->randomsocks[i].fd, set)) poll_check(daemon->randomsocks[i].fd, POLLIN))
reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now); reply_query(daemon->randomsocks[i].fd, daemon->randomsocks[i].family, now);
for (listener = daemon->listeners; listener; listener = listener->next) for (listener = daemon->listeners; listener; listener = listener->next)
{ {
if (listener->fd != -1 && FD_ISSET(listener->fd, set)) if (listener->fd != -1 && poll_check(listener->fd, POLLIN))
receive_query(listener, now); receive_query(listener, now);
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
if (listener->tftpfd != -1 && FD_ISSET(listener->tftpfd, set)) if (listener->tftpfd != -1 && poll_check(listener->tftpfd, POLLIN))
tftp_request(listener, now); tftp_request(listener, now);
#endif #endif
if (listener->tcpfd != -1 && FD_ISSET(listener->tcpfd, set)) if (listener->tcpfd != -1 && poll_check(listener->tcpfd, POLLIN))
{ {
int confd, client_ok = 1; int confd, client_ok = 1;
struct irec *iface = NULL; struct irec *iface = NULL;
@@ -1755,14 +1701,22 @@ int icmp_ping(struct in_addr addr)
better not use any resources our caller has in use...) better not use any resources our caller has in use...)
but we remain deaf to signals or further DHCP packets. */ but we remain deaf to signals or further DHCP packets. */
int fd; /* There can be a problem using dnsmasq_time() to end the loop, since
it's not monotonic, and can go backwards if the system clock is
tweaked, leading to the code getting stuck in this loop and
ignoring DHCP requests. To fix this, we check to see if select returned
as a result of a timeout rather than a socket becoming available. We
only allow this to happen as many times as it takes to get to the wait time
in quarter-second chunks. This provides a fallback way to end loop. */
int fd, rc;
struct sockaddr_in saddr; struct sockaddr_in saddr;
struct { struct {
struct ip ip; struct ip ip;
struct icmp icmp; struct icmp icmp;
} packet; } packet;
unsigned short id = rand16(); unsigned short id = rand16();
unsigned int i, j; unsigned int i, j, timeout_count;
int gotreply = 0; int gotreply = 0;
time_t start, now; time_t start, now;
@@ -1794,53 +1748,44 @@ int icmp_ping(struct in_addr addr)
while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0, while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
(struct sockaddr *)&saddr, sizeof(saddr)))); (struct sockaddr *)&saddr, sizeof(saddr))));
for (now = start = dnsmasq_time(); for (now = start = dnsmasq_time(), timeout_count = 0;
difftime(now, start) < (float)PING_WAIT;) (difftime(now, start) < (float)PING_WAIT) && (timeout_count < PING_WAIT * 4);)
{ {
struct timeval tv;
fd_set rset, wset;
struct sockaddr_in faddr; struct sockaddr_in faddr;
int maxfd = fd;
socklen_t len = sizeof(faddr); socklen_t len = sizeof(faddr);
tv.tv_usec = 250000; poll_reset();
tv.tv_sec = 0; poll_listen(fd, POLLIN);
set_dns_listeners(now);
FD_ZERO(&rset); set_log_writer();
FD_ZERO(&wset);
FD_SET(fd, &rset);
set_dns_listeners(now, &rset, &maxfd);
set_log_writer(&wset, &maxfd);
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
if (daemon->doing_ra) if (daemon->doing_ra)
{ poll_listen(daemon->icmp6fd, POLLIN);
FD_SET(daemon->icmp6fd, &rset);
bump_maxfd(daemon->icmp6fd, &maxfd);
}
#endif #endif
if (select(maxfd+1, &rset, &wset, NULL, &tv) < 0) rc = do_poll(250);
{
FD_ZERO(&rset); if (rc < 0)
FD_ZERO(&wset); continue;
} else if (rc == 0)
timeout_count++;
now = dnsmasq_time(); now = dnsmasq_time();
check_log_writer(&wset); check_log_writer(0);
check_dns_listeners(&rset, now); check_dns_listeners(now);
#ifdef HAVE_DHCP6 #ifdef HAVE_DHCP6
if (daemon->doing_ra && FD_ISSET(daemon->icmp6fd, &rset)) if (daemon->doing_ra && poll_check(daemon->icmp6fd, POLLIN))
icmp6_packet(now); icmp6_packet(now);
#endif #endif
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
check_tftp_listeners(&rset, now); check_tftp_listeners(now);
#endif #endif
if (FD_ISSET(fd, &rset) && if (poll_check(fd, POLLIN) &&
recvfrom(fd, &packet, sizeof(packet), 0, recvfrom(fd, &packet, sizeof(packet), 0,
(struct sockaddr *)&faddr, &len) == sizeof(packet) && (struct sockaddr *)&faddr, &len) == sizeof(packet) &&
saddr.sin_addr.s_addr == faddr.sin_addr.s_addr && saddr.sin_addr.s_addr == faddr.sin_addr.s_addr &&
+13 -7
View File
@@ -82,7 +82,7 @@ typedef unsigned long long u64;
#if defined(HAVE_SOLARIS_NETWORK) #if defined(HAVE_SOLARIS_NETWORK)
# include <sys/sockio.h> # include <sys/sockio.h>
#endif #endif
#include <sys/select.h> #include <sys/poll.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/un.h> #include <sys/un.h>
@@ -1191,7 +1191,6 @@ int memcmp_masked(unsigned char *a, unsigned char *b, int len,
unsigned int mask); unsigned int mask);
int expand_buf(struct iovec *iov, size_t size); int expand_buf(struct iovec *iov, size_t size);
char *print_mac(char *buff, unsigned char *mac, int len); char *print_mac(char *buff, unsigned char *mac, int len);
void bump_maxfd(int fd, int *max);
int read_write(int fd, unsigned char *packet, int size, int rw); int read_write(int fd, unsigned char *packet, int size, int rw);
int wildcard_match(const char* wildcard, const char* match); int wildcard_match(const char* wildcard, const char* match);
@@ -1202,8 +1201,8 @@ void die(char *message, char *arg1, int exit_code);
int log_start(struct passwd *ent_pw, int errfd); int log_start(struct passwd *ent_pw, int errfd);
int log_reopen(char *log_file); int log_reopen(char *log_file);
void my_syslog(int priority, const char *format, ...); void my_syslog(int priority, const char *format, ...);
void set_log_writer(fd_set *set, int *maxfdp); void set_log_writer(void);
void check_log_writer(fd_set *set); void check_log_writer(int force);
void flush_log(void); void flush_log(void);
/* option.c */ /* option.c */
@@ -1366,8 +1365,8 @@ int iface_enumerate(int family, void *parm, int (callback)());
/* dbus.c */ /* dbus.c */
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
char *dbus_init(void); char *dbus_init(void);
void check_dbus_listeners(fd_set *rset, fd_set *wset, fd_set *eset); void check_dbus_listeners(void);
void set_dbus_listeners(int *maxfdp, fd_set *rset, fd_set *wset, fd_set *eset); void set_dbus_listeners(void);
# ifdef HAVE_DHCP # ifdef HAVE_DHCP
void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname); void emit_dbus_signal(int action, struct dhcp_lease *lease, char *hostname);
# endif # endif
@@ -1394,7 +1393,7 @@ int helper_buf_empty(void);
/* tftp.c */ /* tftp.c */
#ifdef HAVE_TFTP #ifdef HAVE_TFTP
void tftp_request(struct listener *listen, time_t now); void tftp_request(struct listener *listen, time_t now);
void check_tftp_listeners(fd_set *rset, time_t now); void check_tftp_listeners(time_t now);
int do_tftp_script_run(void); int do_tftp_script_run(void);
#endif #endif
@@ -1511,3 +1510,10 @@ void inotify_dnsmasq_init();
int inotify_check(time_t now); int inotify_check(time_t now);
void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz); void set_dynamic_inotify(int flag, int total_size, struct crec **rhash, int revhashsz);
#endif #endif
/* poll.c */
void poll_reset(void);
int poll_check(int fd, short event);
void poll_listen(int fd, short event);
int do_poll(int timeout);
+2 -2
View File
@@ -1887,7 +1887,7 @@ unsigned char *tcp_request(int confd, time_t now,
dst_addr_4, netmask, now, &ad_question, &do_bit); dst_addr_4, netmask, now, &ad_question, &do_bit);
/* Do this by steam now we're not in the select() loop */ /* Do this by steam now we're not in the select() loop */
check_log_writer(NULL); check_log_writer(1);
if (m == 0) if (m == 0)
{ {
@@ -2108,7 +2108,7 @@ unsigned char *tcp_request(int confd, time_t now,
} }
} }
check_log_writer(NULL); check_log_writer(1);
*length = htons(m); *length = htons(m);
+63 -13
View File
@@ -18,6 +18,7 @@
#ifdef HAVE_INOTIFY #ifdef HAVE_INOTIFY
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/param.h> /* For MAXSYMLINKS */
/* the strategy is to set a inotify on the directories containing /* the strategy is to set a inotify on the directories containing
resolv files, for any files in the directory which are close-write resolv files, for any files in the directory which are close-write
@@ -35,10 +36,55 @@
static char *inotify_buffer; static char *inotify_buffer;
#define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1) #define INOTIFY_SZ (sizeof(struct inotify_event) + NAME_MAX + 1)
/* If path is a symbolic link, return the path it
points to, made absolute if relative.
If path doesn't exist or is not a symlink, return NULL.
Return value is malloc'ed */
static char *my_readlink(char *path)
{
ssize_t rc, size = 64;
char *buf;
while (1)
{
buf = safe_malloc(size);
rc = readlink(path, buf, (size_t)size);
if (rc == -1)
{
/* Not link or doesn't exist. */
if (errno == EINVAL || errno == ENOENT)
return NULL;
else
die(_("cannot access path %s: %s"), path, EC_MISC);
}
else if (rc < size-1)
{
char *d;
buf[rc] = 0;
if (buf[0] != '/' && ((d = strrchr(path, '/'))))
{
/* Add path to relative link */
char *new_buf = safe_malloc((d - path) + strlen(buf) + 2);
*(d+1) = 0;
strcpy(new_buf, path);
strcat(new_buf, buf);
free(buf);
buf = new_buf;
}
return buf;
}
/* Buffer too small, increase and retry */
size += 64;
free(buf);
}
}
void inotify_dnsmasq_init() void inotify_dnsmasq_init()
{ {
struct resolvc *res; struct resolvc *res;
inotify_buffer = safe_malloc(INOTIFY_SZ); inotify_buffer = safe_malloc(INOTIFY_SZ);
daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); daemon->inotifyfd = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
@@ -47,19 +93,22 @@ void inotify_dnsmasq_init()
for (res = daemon->resolv_files; res; res = res->next) for (res = daemon->resolv_files; res; res = res->next)
{ {
char *d = NULL, *path; char *d, *new_path, *path = safe_malloc(strlen(res->name) + 1);
int links = MAXSYMLINKS;
if (!(path = realpath(res->name, NULL))) strcpy(path, res->name);
/* Follow symlinks until we reach a non-symlink, or a non-existant file. */
while ((new_path = my_readlink(path)))
{ {
/* realpath will fail if the file doesn't exist, but if (links-- == 0)
dnsmasq copes with missing files, so fall back die(_("too many symlinks following %s"), res->name, EC_MISC);
and assume that symlinks are not in use in that case. */ free(path);
if (errno == ENOENT) path = new_path;
path = res->name;
else
die(_("cannot cannonicalise resolv-file %s: %s"), res->name, EC_MISC);
} }
res->wd = -1;
if ((d = strrchr(path, '/'))) if ((d = strrchr(path, '/')))
{ {
*d = 0; /* make path just directory */ *d = 0; /* make path just directory */
@@ -70,10 +119,11 @@ void inotify_dnsmasq_init()
if (res->wd == -1 && errno == ENOENT) if (res->wd == -1 && errno == ENOENT)
die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC); die(_("directory %s for resolv-file is missing, cannot poll"), res->name, EC_MISC);
if (res->wd == -1)
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
} }
if (res->wd == -1)
die(_("failed to create inotify for %s: %s"), res->name, EC_MISC);
} }
} }
+4 -7
View File
@@ -421,18 +421,15 @@ void my_syslog(int priority, const char *format, ...)
} }
} }
void set_log_writer(fd_set *set, int *maxfdp) void set_log_writer(void)
{ {
if (entries && log_fd != -1 && connection_good) if (entries && log_fd != -1 && connection_good)
{ poll_listen(log_fd, POLLOUT);
FD_SET(log_fd, set);
bump_maxfd(log_fd, maxfdp);
}
} }
void check_log_writer(fd_set *set) void check_log_writer(int force)
{ {
if (log_fd != -1 && (!set || FD_ISSET(log_fd, set))) if (log_fd != -1 && (force || poll_check(log_fd, POLLOUT)))
log_write(); log_write();
} }
+3 -6
View File
@@ -4371,7 +4371,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
{ {
char *buff = opt_malloc(MAXDNAME); char *buff = opt_malloc(MAXDNAME);
int option, conffile_opt = '7', testmode = 0; int option, conffile_opt = '7', testmode = 0;
char *arg, *conffile = NULL; char *arg, *conffile = CONFFILE;
opterr = 0; opterr = 0;
@@ -4488,11 +4488,8 @@ void read_opts(int argc, char **argv, char *compile_opts)
if (conffile) if (conffile)
{ {
one_file(conffile, conffile_opt); one_file(conffile, conffile_opt);
free(conffile); if (conffile_opt == 0)
} free(conffile);
else
{
one_file(CONFFILE, conffile_opt);
} }
/* port might not be known when the address is parsed - fill in here */ /* port might not be known when the address is parsed - fill in here */
+124
View File
@@ -0,0 +1,124 @@
/* dnsmasq is Copyright (c) 2000-2015 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
the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
/* Wrapper for poll(). Allocates and extends array of struct pollfds,
keeps them in fd order so that we can set and test conditions on
fd using a simple but efficient binary chop. */
/* poll_reset()
poll_listen(fd, event)
.
.
poll_listen(fd, event);
hits = do_poll(timeout);
if (poll_check(fd, event)
.
.
if (poll_check(fd, event)
.
.
event is OR of POLLIN, POLLOUT, POLLERR, etc
*/
static struct pollfd *pollfds = NULL;
static nfds_t nfds, arrsize = 0;
/* Binary search. Returns either the pollfd with fd, or
if the fd doesn't match, or return equals nfds, the entry
to the left of which a new record should be inserted. */
static nfds_t fd_search(int fd)
{
nfds_t left, right, mid;
if ((right = nfds) == 0)
return 0;
left = 0;
while (1)
{
if (right == left + 1)
return (pollfds[left].fd >= fd) ? left : right;
mid = (left + right)/2;
if (pollfds[mid].fd > fd)
right = mid;
else
left = mid;
}
}
void poll_reset(void)
{
nfds = 0;
}
int do_poll(int timeout)
{
return poll(pollfds, nfds, timeout);
}
int poll_check(int fd, short event)
{
nfds_t i = fd_search(fd);
if (i < nfds && pollfds[i].fd == fd)
return pollfds[i].revents & event;
return 0;
}
void poll_listen(int fd, short event)
{
nfds_t i = fd_search(fd);
if (i < nfds && pollfds[i].fd == fd)
pollfds[i].events |= event;
else
{
if (arrsize != nfds)
memmove(&pollfds[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
else
{
/* Array too small, extend. */
struct pollfd *new;
arrsize += 64;
if (!(new = whine_malloc(arrsize * sizeof(struct pollfd))))
return;
if (pollfds)
{
memcpy(new, pollfds, i * sizeof(struct pollfd));
memcpy(&new[i+1], &pollfds[i], (nfds - i) * sizeof(struct pollfd));
free(pollfds);
}
pollfds = new;
}
pollfds[i].fd = fd;
pollfds[i].events = event;
nfds++;
}
}
+2 -2
View File
@@ -502,7 +502,7 @@ static struct tftp_file *check_tftp_fileperm(ssize_t *len, char *prefix)
return NULL; return NULL;
} }
void check_tftp_listeners(fd_set *rset, time_t now) void check_tftp_listeners(time_t now)
{ {
struct tftp_transfer *transfer, *tmp, **up; struct tftp_transfer *transfer, *tmp, **up;
ssize_t len; ssize_t len;
@@ -518,7 +518,7 @@ void check_tftp_listeners(fd_set *rset, time_t now)
prettyprint_addr(&transfer->peer, daemon->addrbuff); prettyprint_addr(&transfer->peer, daemon->addrbuff);
if (FD_ISSET(transfer->sockfd, rset)) if (poll_check(transfer->sockfd, POLLIN))
{ {
/* we overwrote the buffer... */ /* we overwrote the buffer... */
daemon->srv_save = NULL; daemon->srv_save = NULL;
-6
View File
@@ -570,12 +570,6 @@ char *print_mac(char *buff, unsigned char *mac, int len)
return buff; return buff;
} }
void bump_maxfd(int fd, int *max)
{
if (fd > *max)
*max = fd;
}
/* rc is return from sendto and friends. /* rc is return from sendto and friends.
Return 1 if we should retry. Return 1 if we should retry.
Set errno to zero if we succeeded. */ Set errno to zero if we succeeded. */