summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2018-04-10 21:39:54 +0100
committerSimon Kelley <simon@thekelleys.org.uk>2018-04-10 21:39:54 +0100
commit4441cf762c6e7e62ca20c98b77799e1574095f41 (patch)
tree9f037b04135f0b8e837ff264bfe16a80fd22874b
parente83915d10d7180c40b5cb14fc7a47eac23cfc270 (diff)
downloaddnsmasq-2.80test1.tar.gz
Fix DNS server fd garbage collection.v2.80test1
If we're talking to upstream servers from a fixed port, specified by query-port we create the fds to do this once, before dropping root, so that ports <1024 can be used. But we call check_servers() before reading /etc/resolv.conf, so if the only servers are in resolv.conf, at that point there will be no servers, and the fds get garbage collected away, only to be recreated (but without root) after we read /etc/resolv.conf Make pre-allocated server fds immortal, to avoid this problem.
-rw-r--r--src/dnsmasq.h2
-rw-r--r--src/network.c13
2 files changed, 10 insertions, 5 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 30c4519..ff7172f 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -506,7 +506,7 @@ struct serverfd {
int fd;
union mysockaddr source_addr;
char interface[IF_NAMESIZE+1];
- unsigned int ifindex, used;
+ unsigned int ifindex, used, preallocated;
struct serverfd *next;
};
diff --git a/src/network.c b/src/network.c
index 1af4dbc..b405458 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1290,6 +1290,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
sfd->source_addr = *addr;
sfd->next = daemon->sfds;
sfd->ifindex = ifindex;
+ sfd->preallocated = 0;
daemon->sfds = sfd;
return sfd;
@@ -1300,6 +1301,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
void pre_allocate_sfds(void)
{
struct server *srv;
+ struct serverfd *sfd;
if (daemon->query_port != 0)
{
@@ -1311,7 +1313,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in);
#endif
- allocate_sfd(&addr, "");
+ if ((sfd = allocate_sfd(&addr, "")))
+ sfd->preallocated = 1;
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6;
@@ -1320,7 +1323,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif
- allocate_sfd(&addr, "");
+ if ((sfd = allocate_sfd(&addr, "")))
+ sfd->preallocated = 1;
#endif
}
@@ -1473,9 +1477,10 @@ void check_servers(void)
/* interface may be new since startup */
if (!option_bool(OPT_NOWILD))
enumerate_interfaces(0);
-
+
+ /* don't garbage collect pre-allocated sfds. */
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
- sfd->used = 0;
+ sfd->used = sfd->preallocated;
for (count = 0, serv = daemon->servers; serv; serv = serv->next)
{