You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.2 KiB
119 lines
3.2 KiB
From 2675f2061525bc954be14988d64384b74aa7bf8b Mon Sep 17 00:00:00 2001 |
|
From: Beniamino Galvani <bgalvani@redhat.com> |
|
Date: Sun, 28 Aug 2016 20:44:05 +0100 |
|
Subject: [PATCH] Handle binding upstream servers to an interface |
|
(--server=1.2.3.4@eth0) when the named interface is destroyed and recreated |
|
in the kernel. |
|
|
|
--- |
|
CHANGELOG | 5 +++++ |
|
src/dnsmasq.h | 1 + |
|
src/network.c | 31 +++++++++++++++++++++++++++++-- |
|
3 files changed, 35 insertions(+), 2 deletions(-) |
|
|
|
diff --git a/src/dnsmasq.h b/src/dnsmasq.h |
|
index 27385a9..f239ce5 100644 |
|
--- a/src/dnsmasq.h |
|
+++ b/src/dnsmasq.h |
|
@@ -488,6 +488,7 @@ struct serverfd { |
|
int fd; |
|
union mysockaddr source_addr; |
|
char interface[IF_NAMESIZE+1]; |
|
+ unsigned int ifindex, used; |
|
struct serverfd *next; |
|
}; |
|
|
|
diff --git a/src/network.c b/src/network.c |
|
index e7722fd..ddf8d31 100644 |
|
--- a/src/network.c |
|
+++ b/src/network.c |
|
@@ -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) |
|
{ |
|
struct serverfd *sfd; |
|
+ unsigned int ifindex = 0; |
|
int errsave; |
|
|
|
/* 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; |
|
#endif |
|
} |
|
+ |
|
+ if (intname && strlen(intname) != 0) |
|
+ ifindex = if_nametoindex(intname); /* index == 0 when not binding to an interface */ |
|
|
|
/* may have a suitable one already */ |
|
for (sfd = daemon->sfds; sfd; sfd = sfd->next ) |
|
if (sockaddr_isequal(&sfd->source_addr, addr) && |
|
- strcmp(intname, sfd->interface) == 0) |
|
+ strcmp(intname, sfd->interface) == 0 && |
|
+ ifindex == sfd->ifindex) |
|
return sfd; |
|
|
|
/* need to make a new one. */ |
|
@@ -1250,11 +1255,13 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) |
|
errno = errsave; |
|
return NULL; |
|
} |
|
- |
|
+ |
|
strcpy(sfd->interface, intname); |
|
sfd->source_addr = *addr; |
|
sfd->next = daemon->sfds; |
|
+ sfd->ifindex = ifindex; |
|
daemon->sfds = sfd; |
|
+ |
|
return sfd; |
|
} |
|
|
|
@@ -1429,12 +1436,16 @@ void check_servers(void) |
|
{ |
|
struct irec *iface; |
|
struct server *serv; |
|
+ struct serverfd *sfd, *tmp, **up; |
|
int port = 0, count; |
|
|
|
/* interface may be new since startup */ |
|
if (!option_bool(OPT_NOWILD)) |
|
enumerate_interfaces(0); |
|
|
|
+ for (sfd = daemon->sfds; sfd; sfd = sfd->next) |
|
+ sfd->used = 0; |
|
+ |
|
#ifdef HAVE_DNSSEC |
|
/* Disable DNSSEC validation when using server=/domain/.... servers |
|
unless there's a configured trust anchor. */ |
|
@@ -1505,6 +1516,8 @@ void check_servers(void) |
|
serv->flags |= SERV_MARK; |
|
continue; |
|
} |
|
+ |
|
+ serv->sfd->used = 1; |
|
} |
|
|
|
if (!(serv->flags & SERV_NO_REBIND) && !(serv->flags & SERV_LITERAL_ADDRESS)) |
|
@@ -1547,6 +1560,20 @@ void check_servers(void) |
|
if (count - 1 > SERVERS_LOGGED) |
|
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(); |
|
} |
|
|
|
-- |
|
2.7.4 |
|
|
|
|