Discussion:
[Dnsmasq-discuss] [PATCH] Fix DNS resolution when reconnecting to VPN or other similar interfaces
Nikolay Martynov
2016-11-13 01:14:56 UTC
Permalink
If interface goes down and then interface with same name brought up (e.g. VPN) then sending data for fds bound to this interfaces fails with ENODEV. Fix this by rebinding opened fd to current interface name.

Signed-off-by: Nikolay Martynov <***@gmail.com>
---
src/network.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/network.c b/src/network.c
index e7722fd..af7f94f 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1228,8 +1228,17 @@ static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
/* 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) {
+#if defined(SO_BINDTODEVICE)
+ /* Interface may have went down and reopened after we have
+ opened this sfd (e.g. VPN). This makes interface-bound fd
+ invalid.
+ Bind fd to new interface instance to avoid errors */
+ if (intname[0] != 0)
+ setsockopt(sfd->fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1;
+#endif
return sfd;
+ }

/* need to make a new one. */
errno = ENOMEM; /* in case malloc fails. */
--
2.9.3
Dan Williams
2016-11-13 15:40:09 UTC
Permalink
Post by Nikolay Martynov
If interface goes down and then interface with same name brought up
(e.g. VPN) then sending data for fds bound to this interfaces fails
with ENODEV. Fix this by rebinding opened fd to current interface
name.
Does this commit fix your issue too?  Something similar was already
committed upstream:

http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=2675f2061525bc954be14988d64384b74aa7bf8b

Dan
Post by Nikolay Martynov
---
 src/network.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/network.c b/src/network.c
index e7722fd..af7f94f 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1228,8 +1228,17 @@ static struct serverfd *allocate_sfd(union
mysockaddr *addr, char *intname)
   /* 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) {
+#if defined(SO_BINDTODEVICE)
+      /* Interface may have went down and reopened after we have
+         opened this sfd (e.g. VPN). This makes interface-bound fd
+         invalid.
+         Bind fd to new interface instance to avoid errors */
+      if (intname[0] != 0)
+        setsockopt(sfd->fd, SOL_SOCKET, SO_BINDTODEVICE, intname,
IF_NAMESIZE) == -1;
+#endif
       return sfd;
+    }
   
   /* need to make a new one. */
   errno = ENOMEM; /* in case malloc fails. */
Nikolay Martynov
2016-11-13 21:27:43 UTC
Permalink
Hi, Dan.

Thank you do your response!

Yes, I've verified - this commit fixes issue for me as well. Thanks
for pointing it out. I should have checked it before sending may
patch.
Post by Nikolay Martynov
If interface goes down and then interface with same name brought up
(e.g. VPN) then sending data for fds bound to this interfaces fails
with ENODEV. Fix this by rebinding opened fd to current interface
name.
Does this commit fix your issue too? Something similar was already
http://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=2675f2061525bc954be14988d64384b74aa7bf8b
Dan
Post by Nikolay Martynov
---
src/network.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/network.c b/src/network.c
index e7722fd..af7f94f 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1228,8 +1228,17 @@ static struct serverfd *allocate_sfd(union
mysockaddr *addr, char *intname)
/* 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) {
+#if defined(SO_BINDTODEVICE)
+ /* Interface may have went down and reopened after we have
+ opened this sfd (e.g. VPN). This makes interface-bound fd
+ invalid.
+ Bind fd to new interface instance to avoid errors */
+ if (intname[0] != 0)
+ setsockopt(sfd->fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1;
+#endif
return sfd;
+ }
/* need to make a new one. */
errno = ENOMEM; /* in case malloc fails. */
--
Martynov Nikolay.
Email: ***@gmail.com
Loading...