Nikolay Martynov
2016-11-13 01:14:56 UTC
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. */
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
2.9.3