Commit 4441cf76 authored by Simon Kelley's avatar Simon Kelley

Fix DNS server fd garbage collection.

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.
parent e83915d1
...@@ -506,7 +506,7 @@ struct serverfd { ...@@ -506,7 +506,7 @@ struct serverfd {
int fd; int fd;
union mysockaddr source_addr; union mysockaddr source_addr;
char interface[IF_NAMESIZE+1]; char interface[IF_NAMESIZE+1];
unsigned int ifindex, used; unsigned int ifindex, used, preallocated;
struct serverfd *next; struct serverfd *next;
}; };
......
...@@ -1290,6 +1290,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) ...@@ -1290,6 +1290,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
sfd->source_addr = *addr; sfd->source_addr = *addr;
sfd->next = daemon->sfds; sfd->next = daemon->sfds;
sfd->ifindex = ifindex; sfd->ifindex = ifindex;
sfd->preallocated = 0;
daemon->sfds = sfd; daemon->sfds = sfd;
return sfd; return sfd;
...@@ -1300,6 +1301,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) ...@@ -1300,6 +1301,7 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
void pre_allocate_sfds(void) void pre_allocate_sfds(void)
{ {
struct server *srv; struct server *srv;
struct serverfd *sfd;
if (daemon->query_port != 0) if (daemon->query_port != 0)
{ {
...@@ -1311,7 +1313,8 @@ void pre_allocate_sfds(void) ...@@ -1311,7 +1313,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in); addr.in.sin_len = sizeof(struct sockaddr_in);
#endif #endif
allocate_sfd(&addr, ""); if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
...@@ -1320,7 +1323,8 @@ void pre_allocate_sfds(void) ...@@ -1320,7 +1323,8 @@ void pre_allocate_sfds(void)
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6); addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif #endif
allocate_sfd(&addr, ""); if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1;
#endif #endif
} }
...@@ -1473,9 +1477,10 @@ void check_servers(void) ...@@ -1473,9 +1477,10 @@ void check_servers(void)
/* interface may be new since startup */ /* interface may be new since startup */
if (!option_bool(OPT_NOWILD)) if (!option_bool(OPT_NOWILD))
enumerate_interfaces(0); enumerate_interfaces(0);
/* don't garbage collect pre-allocated sfds. */
for (sfd = daemon->sfds; sfd; sfd = sfd->next) 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) for (count = 0, serv = daemon->servers; serv; serv = serv->next)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment