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> --- slirp/misc.c | 2 ++ slirp/tcp_subr.c | 4 ++++ slirp/udp.c | 2 ++ 3 files changed, 8 insertions(+) diff --git a/slirp/misc.c b/slirp/misc.c index c0d4899..fe9c1c3 100644 --- a/slirp/misc.c +++ b/slirp/misc.c @@ -212,8 +212,10 @@ fork_exec(struct socket *so, const char *ex, int do_pty) so->s = accept(s, (struct sockaddr *)&addr, &addrlen); } while (so->s < 0 && errno == EINTR); closesocket(s); +#ifndef _WIN32 opt = 1; qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); +#endif opt = 1; qemu_setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); qemu_set_nonblock(so->s); diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c index 043f28f..148d513 100644 --- a/slirp/tcp_subr.c +++ b/slirp/tcp_subr.c @@ -337,8 +337,10 @@ int tcp_fconnect(struct socket *so) struct sockaddr_in addr; qemu_set_nonblock(s); +#ifndef _WIN32 opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); +#endif opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(opt)); @@ -426,8 +428,10 @@ void tcp_connect(struct socket *inso) return; } qemu_set_nonblock(s); +#ifndef _WIN32 opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); +#endif opt = 1; qemu_setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int)); socket_set_nodelay(s); diff --git a/slirp/udp.c b/slirp/udp.c index b105f87..6ee45d6 100644 --- a/slirp/udp.c +++ b/slirp/udp.c @@ -372,7 +372,9 @@ udp_listen(Slirp *slirp, uint32_t haddr, u_int hport, uint32_t laddr, udp_detach(so); return NULL; } +#ifndef _WIN32 qemu_setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)); +#endif getsockname(so->s,(struct sockaddr *)&addr,&addrlen); so->so_fport = addr.sin_port; -- 1.7.9.5