|
|
e20e41 |
From 2675f2061525bc954be14988d64384b74aa7bf8b Mon Sep 17 00:00:00 2001
|
|
|
e20e41 |
From: Beniamino Galvani <bgalvani@redhat.com>
|
|
|
e20e41 |
Date: Sun, 28 Aug 2016 20:44:05 +0100
|
|
|
e20e41 |
Subject: [PATCH] Handle binding upstream servers to an interface
|
|
|
e20e41 |
(--server=1.2.3.4@eth0) when the named interface is destroyed and recreated
|
|
|
e20e41 |
in the kernel.
|
|
|
e20e41 |
|
|
|
e20e41 |
---
|
|
|
e20e41 |
CHANGELOG | 5 +++++
|
|
|
e20e41 |
src/dnsmasq.h | 1 +
|
|
|
e20e41 |
src/network.c | 31 +++++++++++++++++++++++++++++--
|
|
|
e20e41 |
3 files changed, 35 insertions(+), 2 deletions(-)
|
|
|
e20e41 |
|
|
|
e20e41 |
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
|
|
|
e20e41 |
index 27385a9..f239ce5 100644
|
|
|
e20e41 |
--- a/src/dnsmasq.h
|
|
|
e20e41 |
+++ b/src/dnsmasq.h
|
|
|
e20e41 |
@@ -488,6 +488,7 @@ struct serverfd {
|
|
|
e20e41 |
int fd;
|
|
|
e20e41 |
union mysockaddr source_addr;
|
|
|
e20e41 |
char interface[IF_NAMESIZE+1];
|
|
|
e20e41 |
+ unsigned int ifindex, used;
|
|
|
e20e41 |
struct serverfd *next;
|
|
|
e20e41 |
};
|
|
|
e20e41 |
|
|
|
e20e41 |
diff --git a/src/network.c b/src/network.c
|
|
|
e20e41 |
index e7722fd..ddf8d31 100644
|
|
|
e20e41 |
--- a/src/network.c
|
|
|
e20e41 |
+++ b/src/network.c
|
|
|
e20e41 |
@@ -1204,6 +1204,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, int is_tcp)
|
|
|
e20e41 |
static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|
|
e20e41 |
{
|
|
|
e20e41 |
struct serverfd *sfd;
|
|
|
e20e41 |
+ unsigned int ifindex = 0;
|
|
|
e20e41 |
int errsave;
|
|
|
e20e41 |
|
|
|
e20e41 |
/* when using random ports, servers which would otherwise use
|
|
|
e20e41 |
@@ -1224,11 +1225,15 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|
|
e20e41 |
return NULL;
|
|
|
e20e41 |
#endif
|
|
|
e20e41 |
}
|
|
|
e20e41 |
+
|
|
|
e20e41 |
+ if (intname && strlen(intname) != 0)
|
|
|
e20e41 |
+ ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */
|
|
|
e20e41 |
|
|
|
e20e41 |
/* may have a suitable one already */
|
|
|
e20e41 |
for (sfd = daemon->sfds; sfd; sfd = sfd->next )
|
|
|
e20e41 |
if (sockaddr_isequal(&sfd->source_addr, addr) &&
|
|
|
e20e41 |
- strcmp(intname, sfd->interface) == 0)
|
|
|
e20e41 |
+ strcmp(intname, sfd->interface) == 0 &&
|
|
|
e20e41 |
+ ifindex == sfd->ifindex)
|
|
|
e20e41 |
return sfd;
|
|
|
e20e41 |
|
|
|
e20e41 |
/* need to make a new one. */
|
|
|
e20e41 |
@@ -1250,11 +1255,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
|
|
|
e20e41 |
errno = errsave;
|
|
|
e20e41 |
return NULL;
|
|
|
e20e41 |
}
|
|
|
e20e41 |
-
|
|
|
e20e41 |
+
|
|
|
e20e41 |
strcpy(sfd->interface, intname);
|
|
|
e20e41 |
sfd->source_addr = *addr;
|
|
|
e20e41 |
sfd->next = daemon->sfds;
|
|
|
e20e41 |
+ sfd->ifindex = ifindex;
|
|
|
e20e41 |
daemon->sfds = sfd;
|
|
|
e20e41 |
+
|
|
|
e20e41 |
return sfd;
|
|
|
e20e41 |
}
|
|
|
e20e41 |
|
|
|
e20e41 |
@@ -1429,12 +1436,16 @@ void check_servers(void)
|
|
|
e20e41 |
{
|
|
|
e20e41 |
struct irec *iface;
|
|
|
e20e41 |
struct server *serv;
|
|
|
e20e41 |
+ struct serverfd *sfd, *tmp, **up;
|
|
|
e20e41 |
int port = 0, count;
|
|
|
e20e41 |
|
|
|
e20e41 |
/* interface may be new since startup */
|
|
|
e20e41 |
if (!option_bool(OPT_NOWILD))
|
|
|
e20e41 |
enumerate_interfaces(0);
|
|
|
e20e41 |
|
|
|
e20e41 |
+ for (sfd = daemon->sfds; sfd; sfd = sfd->next)
|
|
|
e20e41 |
+ sfd->used = 0;
|
|
|
e20e41 |
+
|
|
|
e20e41 |
#ifdef HAVE_DNSSEC
|
|
|
e20e41 |
/* Disable DNSSEC validation when using server=/domain/.... servers
|
|
|
e20e41 |
unless there's a configured trust anchor. */
|
|
|
e20e41 |
@@ -1505,6 +1516,8 @@ void check_servers(void)
|
|
|
e20e41 |
serv->flags |= SERV_MARK;
|
|
|
e20e41 |
continue;
|
|
|
e20e41 |
}
|
|
|
e20e41 |
+
|
|
|
e20e41 |
+ serv->sfd->used = 1;
|
|
|
e20e41 |
}
|
|
|
e20e41 |
|
|
|
e20e41 |
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS))
|
|
|
e20e41 |
@@ -1547,6 +1560,20 @@ void check_servers(void)
|
|
|
e20e41 |
if (count - 1 > SERVERS_LOGGED)
|
|
|
e20e41 |
my_syslog(LOG_INFO, _("using %d more nameservers"), count - SERVERS_LOGGED - 1);
|
|
|
e20e41 |
|
|
|
e20e41 |
+ /* Remove unused sfds */
|
|
|
e20e41 |
+ for (sfd = daemon->sfds, up = &daemon->sfds; sfd; sfd = tmp)
|
|
|
e20e41 |
+ {
|
|
|
e20e41 |
+ tmp = sfd->next;
|
|
|
e20e41 |
+ if (!sfd->used)
|
|
|
e20e41 |
+ {
|
|
|
e20e41 |
+ *up = sfd->next;
|
|
|
e20e41 |
+ close(sfd->fd);
|
|
|
e20e41 |
+ free(sfd);
|
|
|
e20e41 |
+ }
|
|
|
e20e41 |
+ else
|
|
|
e20e41 |
+ up = &sfd->next;
|
|
|
e20e41 |
+ }
|
|
|
e20e41 |
+
|
|
|
e20e41 |
cleanup_servers();
|
|
|
e20e41 |
}
|
|
|
e20e41 |
|
|
|
e20e41 |
--
|
|
|
e20e41 |
2.7.4
|
|
|
e20e41 |
|