On Mon, Apr 28, 2014 at 02:14:39PM +0100, Daniel P. Berrange wrote:
On Mon, Apr 28, 2014 at 02:05:23PM +0100, Daniel P. Berrange wrote:
> 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
> +}
Obviously this } should be before the #endif :-)