SO_REUSEADDR on Windows is actually akin to SO_REUSEPORT
on Linux/BSD. ie it allows 2 apps to listen to the same
port at once. Thus we must not set it on Win32 platforms
See
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/rpc/virnetsocket.c | 7 ++-----
src/util/virportallocator.c | 4 +---
src/util/virutil.c | 23 +++++++++++++++++++++++
src/util/virutil.h | 1 +
5 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5788468..ee2f57b 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2059,6 +2059,7 @@ virSetCloseExec;
virSetDeviceUnprivSGIO;
virSetInherit;
virSetNonBlock;
+virSetSockReuseAddr;
virSetUIDGID;
virSetUIDGIDWithCaps;
virStrIsPrint;
diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c
index 2e94a6c..a7e1783 100644
--- a/src/rpc/virnetsocket.c
+++ b/src/rpc/virnetsocket.c
@@ -255,8 +255,7 @@ int virNetSocketNewListenTCP(const char *nodename,
goto error;
}
- int opt = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+ if (virSetSockReuseAddr(fd) < 0) {
virReportSystemError(errno, "%s", _("Unable to enable port
reuse"));
goto error;
}
@@ -460,15 +459,13 @@ int virNetSocketNewConnectTCP(const char *nodename,
runp = ai;
while (runp) {
- int opt = 1;
-
if ((fd = socket(runp->ai_family, runp->ai_socktype,
runp->ai_protocol)) < 0) {
virReportSystemError(errno, "%s", _("Unable to create
socket"));
goto error;
}
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
+ if (virSetSockReuseAddr(fd) < 0) {
VIR_WARN("Unable to enable port reuse");
}
diff --git a/src/util/virportallocator.c b/src/util/virportallocator.c
index ed7bdc2..b68133a 100644
--- a/src/util/virportallocator.c
+++ b/src/util/virportallocator.c
@@ -116,7 +116,6 @@ static int virPortAllocatorBindToPort(bool *used,
struct sockaddr* addr;
size_t addrlen;
int v6only = 1;
- int reuse = 1;
int ret = -1;
int fd = -1;
bool ipv6 = false;
@@ -143,8 +142,7 @@ static int virPortAllocatorBindToPort(bool *used,
goto cleanup;
}
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&reuse,
- sizeof(reuse)) < 0) {
+ if (virSetSockReuseAddr(fd) < 0) {
virReportSystemError(errno, "%s",
_("Unable to set socket reuse addr flag"));
goto cleanup;
diff --git a/src/util/virutil.c b/src/util/virutil.c
index 9be1590..65b10b8 100644
--- a/src/util/virutil.c
+++ b/src/util/virutil.c
@@ -136,6 +136,29 @@ int virSetCloseExec(int fd)
return virSetInherit(fd, false);
}
+#ifdef WIN32
+int virSetSockReuseAddr(int fd ATTRIBUTE_UNUSED)
+{
+ /*
+ * SO_REUSEADDR on Windows is actually akin to SO_REUSEPORT
+ * on Linux/BSD. ie it allows 2 apps to listen to the same
+ * port at once which is certainly not what we want here.
+ *
+ * Win32 sockets have Linux/BSD-like SO_REUSEADDR behaviour
+ * by default, so we can be a no-op.
+ *
+ *
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740621.aspx
+ */
+ return 0;
+}
+#else
+int virSetSockReuseAddr(int fd)
+{
+ int opt = 1;
+ return setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+#endif
+}
+
int
virPipeReadUntilEOF(int outfd, int errfd,
char **outbuf, char **errbuf) {
diff --git a/src/util/virutil.h b/src/util/virutil.h
index 1f2efd5..2bb74e2 100644
--- a/src/util/virutil.h
+++ b/src/util/virutil.h
@@ -42,6 +42,7 @@ int virSetBlocking(int fd, bool blocking) ATTRIBUTE_RETURN_CHECK;
int virSetNonBlock(int fd) ATTRIBUTE_RETURN_CHECK;
int virSetInherit(int fd, bool inherit) ATTRIBUTE_RETURN_CHECK;
int virSetCloseExec(int fd) ATTRIBUTE_RETURN_CHECK;
+int virSetSockReuseAddr(int fd) ATTRIBUTE_RETURN_CHECK;
int virPipeReadUntilEOF(int outfd, int errfd,
char **outbuf, char **errbuf);
--
1.9.0