Handle binding upstream servers to an interface

(--server=1.2.3.4@eth0) when the named interface
is destroyed and recreated in the kernel.
This commit is contained in:
Beniamino Galvani
2016-08-28 20:44:05 +01:00
committed by Simon Kelley
parent e94ad0fa01
commit 2675f20615
3 changed files with 35 additions and 2 deletions

View File

@@ -30,6 +30,11 @@ version 2.77
and are now converted to names like and are now converted to names like
<prefix>--ffff-1-2-3-4.<domain> <prefix>--ffff-1-2-3-4.<domain>
Handle binding upstream servers to an interface
(--server=1.2.3.4@eth0) when the named interface
is destroyed and recreated in the kernel. Thanks to
Beniamino Galvani for the patch.
version 2.76 version 2.76
Include 0.0.0.0/8 in DNS rebind checks. This range Include 0.0.0.0/8 in DNS rebind checks. This range

View File

@@ -488,6 +488,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;
struct serverfd *next; struct serverfd *next;
}; };

View File

@@ -1204,6 +1204,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
{ {
struct serverfd *sfd; struct serverfd *sfd;
unsigned int ifindex = 0;
int errsave; int errsave;
/* when using random ports, servers which would otherwise use /* when using random ports, servers which would otherwise use
@@ -1224,11 +1225,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
return NULL; return NULL;
#endif #endif
} }
if (intname && strlen(intname) != 0)
ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
/* may have a suitable one already */ /* may have a suitable one already */
for (sfd = daemon->sfds; sfd; sfd = sfd->next ) for (sfd = daemon->sfds; sfd; sfd = sfd->next )
if (sockaddr_isequal(&sfd->source_addr, addr) && if (sockaddr_isequal(&sfd->source_addr, addr) &&
strcmp(intname, sfd->interface) == 0) strcmp(intname, sfd->interface) == 0 &&
ifindex == sfd->ifindex)
return sfd; return sfd;
/* need to make a new one. */ /* need to make a new one. */
@@ -1250,11 +1255,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
errno = errsave; errno = errsave;
return NULL; return NULL;
} }
strcpy(sfd->interface, intname); strcpy(sfd->interface, intname);
sfd->source_addr = *addr; sfd->source_addr = *addr;
sfd->next = daemon->sfds; sfd->next = daemon->sfds;
sfd->ifindex = ifindex;
daemon->sfds = sfd; daemon->sfds = sfd;
return sfd; return sfd;
} }
@@ -1429,12 +1436,16 @@ void check_servers(void)
{ {
struct irec *iface; struct irec *iface;
struct server *serv; struct server *serv;
struct serverfd *sfd, *tmp, **up;
int port = 0, count; int port = 0, count;
/* 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);
for (sfd = daemon->sfds; sfd; sfd = sfd->next)
sfd->used = 0;
#ifdef HAVE_DNSSEC #ifdef HAVE_DNSSEC
/* Disable DNSSEC validation when using server=/domain/.... servers /* Disable DNSSEC validation when using server=/domain/.... servers
unless there's a configured trust anchor. */ unless there's a configured trust anchor. */
@@ -1505,6 +1516,8 @@ void check_servers(void)
serv->flags |= SERV_MARK; serv->flags |= SERV_MARK;
continue; continue;
} }
serv->sfd->used = 1;
} }
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS)) if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
@@ -1547,6 +1560,20 @@ void check_servers(void)
if (count - 1 > SERVERS_LOGGED) if (count - 1 > SERVERS_LOGGED)
my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1); my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
/* Remove unused sfds */
for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
{
tmp = sfd->next;
if (!sfd->used)
{
*up = sfd->next;
close(sfd->fd);
free(sfd);
}
else
up = &sfd->next;
}
cleanup_servers(); cleanup_servers();
} }