aboutsummaryrefslogtreecommitdiff
path: root/slirp/socket.c
diff options
context:
space:
mode:
authorGavin Grant <gavingrant@protonmail.com>2018-08-30 16:57:57 +0100
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-10-07 19:50:48 +0200
commit93a972f8548571d35c718ca3a94d5ab1507b2443 (patch)
tree4fde3be9dfbce8d3c624aac01bc678bb3878b9e8 /slirp/socket.c
parent3d090aefe29846f8606d06bf55526ebb91f4d725 (diff)
downloadqemu-arm-93a972f8548571d35c718ca3a94d5ab1507b2443.tar.gz
slirp: Propagate host TCP RST packet to the guest after socket disconnected
Commit 27d92ebc5ed1bb0b518d0ebc4c609182ad20a799 handled the case where the TCP connection is abruptly closed via a RST packet, by checking for the ECONNRESET errno. However it does not consider the case where the connection has been half-closed by the host (FIN/ACK), then the host socket is disconnected. For example, if the host application calls close() on the socket, then the application exits. In this case, the socket still exists due to the file descriptor in SLIRP, but it is disconnected. recv() does not indicate an error since an orderly socket close has previously occurred. The socket will then be stuck in FIN_WAIT_2, until the peer sends FIN/ACK or a timeout occurs. Instead we can send a RST to the peer and transition to the CLOSED state. Signed-off-by: Gavin Grant <gavingrant@protonmail.com> Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Diffstat (limited to 'slirp/socket.c')
-rw-r--r--slirp/socket.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/slirp/socket.c b/slirp/socket.c
index 08fe98907d..322383a1f9 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -204,12 +204,19 @@ soread(struct socket *so)
return 0;
else {
int err;
- socklen_t slen = sizeof err;
+ socklen_t elen = sizeof err;
+ struct sockaddr_storage addr;
+ struct sockaddr *paddr = (struct sockaddr *) &addr;
+ socklen_t alen = sizeof addr;
err = errno;
if (nn == 0) {
- getsockopt(so->s, SOL_SOCKET, SO_ERROR,
- &err, &slen);
+ if (getpeername(so->s, paddr, &alen) < 0) {
+ err = errno;
+ } else {
+ getsockopt(so->s, SOL_SOCKET, SO_ERROR,
+ &err, &elen);
+ }
}
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));