If a socket is closed it may remain in TIME_WAIT state for some time. On most operating systems the local port of the connection or socket may not be reeused while in this state unless SO_REUSEADDR was set on the socket. On windows on the other hand the default behaviour is to allow reuse (i.e. identical to SO_REUSEADDR on other operating systems) and setting SO_REUSEADDR on a socket allows it to be bound to a endpoint even if the endpoint is already used by another socket independently of the other sockets state. This may result in undefined behaviour. Fix this issue by no setting SO_REUSEADDR on windows.
Signed-off-by: Sebastian Ottlik <ott...@fzi.de> --- net/socket.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/socket.c b/net/socket.c index e61309d..f44ebcb 100644 --- a/net/socket.c +++ b/net/socket.c @@ -262,12 +262,14 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr, struct in_addr return -1; } +#ifndef _WIN32 val = 1; ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); goto fail; } +#endif ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); if (ret < 0) { @@ -523,8 +525,10 @@ static int net_socket_listen_init(NetClientState *peer, qemu_set_nonblock(fd); /* allow fast reuse */ +#ifndef _WIN32 val = 1; qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); +#endif ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { @@ -661,6 +665,7 @@ static int net_socket_udp_init(NetClientState *peer, perror("socket(PF_INET, SOCK_DGRAM)"); return -1; } +#ifndef _WIN32 val = 1; ret = qemu_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); @@ -669,6 +674,7 @@ static int net_socket_udp_init(NetClientState *peer, closesocket(fd); return -1; } +#endif ret = bind(fd, (struct sockaddr *)&laddr, sizeof(laddr)); if (ret < 0) { perror("bind"); -- 1.7.9.5