Fix hang from new interface-name code, when using TCP.

This commit is contained in:
Simon Kelley
2013-05-23 10:04:25 +01:00
parent 63fd27e35f
commit 76dd75de77
2 changed files with 59 additions and 49 deletions

View File

@@ -1362,55 +1362,63 @@ static void check_dns_listeners(fd_set *set, time_t now)
continue; continue;
} }
if (option_bool(OPT_NOWILD)) /* Make sure that the interface list is up-to-date.
We do this here as we may need the results below, and
the DNS code needs them for --interface-name stuff.
Multiple calls to enumerate_interfaces() per select loop are
inhibited, so calls to it in the child process (which doesn't select())
have no effect. This avoids two processes reading from the same
netlink fd and screwing the pooch entirely.
*/
enumerate_interfaces(0);
if (option_bool(OPT_NOWILD))
iface = listener->iface; /* May be NULL */ iface = listener->iface; /* May be NULL */
else else
{ {
int if_index; int if_index;
char intr_name[IF_NAMESIZE]; char intr_name[IF_NAMESIZE];
/* In full wildcard mode, need to refresh interface list. /* if we can find the arrival interface, check it's one that's allowed */
This happens automagically in CLEVERBIND */ if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
if (!option_bool(OPT_CLEVERBIND)) indextoname(listener->tcpfd, if_index, intr_name))
enumerate_interfaces(0); {
struct all_addr addr;
/* if we can find the arrival interface, check it's one that's allowed */ addr.addr.addr4 = tcp_addr.in.sin_addr;
if ((if_index = tcp_interface(confd, tcp_addr.sa.sa_family)) != 0 &&
indextoname(listener->tcpfd, if_index, intr_name))
{
struct all_addr addr;
addr.addr.addr4 = tcp_addr.in.sin_addr;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (tcp_addr.sa.sa_family == AF_INET6) if (tcp_addr.sa.sa_family == AF_INET6)
addr.addr.addr6 = tcp_addr.in6.sin6_addr; addr.addr.addr6 = tcp_addr.in6.sin6_addr;
#endif #endif
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index) if (iface->index == if_index)
break; break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name)) if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
client_ok = 0; client_ok = 0;
} }
if (option_bool(OPT_CLEVERBIND)) if (option_bool(OPT_CLEVERBIND))
iface = listener->iface; /* May be NULL */ iface = listener->iface; /* May be NULL */
else else
{ {
/* Check for allowed interfaces when binding the wildcard address: /* Check for allowed interfaces when binding the wildcard address:
we do this by looking for an interface with the same address as we do this by looking for an interface with the same address as
the local address of the TCP connection, then looking to see if that's the local address of the TCP connection, then looking to see if that's
an allowed interface. As a side effect, we get the netmask of the an allowed interface. As a side effect, we get the netmask of the
interface too, for localisation. */ interface too, for localisation. */
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, &tcp_addr)) if (sockaddr_isequal(&iface->addr, &tcp_addr))
break; break;
if (!iface) if (!iface)
client_ok = 0; client_ok = 0;
} }
} }
if (!client_ok) if (!client_ok)
{ {

View File

@@ -438,7 +438,9 @@ int enumerate_interfaces(int reset)
struct addrlist *addr, *tmp; struct addrlist *addr, *tmp;
struct interface_name *intname; struct interface_name *intname;
/* DO this max once per select cycle */ /* Do this max once per select cycle - also inhibits netlink socket use
in TCP child processes. */
if (reset) if (reset)
{ {
done = 0; done = 0;