]> Git Repo - qemu.git/commitdiff
slirp: Propagate host TCP RST packet to the guest after socket disconnected
authorGavin Grant <[email protected]>
Thu, 30 Aug 2018 15:57:57 +0000 (16:57 +0100)
committerSamuel Thibault <[email protected]>
Sun, 7 Oct 2018 17:50:48 +0000 (19:50 +0200)
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 <[email protected]>
Signed-off-by: Samuel Thibault <[email protected]>
slirp/socket.c

index 08fe98907d08b3b49b5aff08140c6b84142a6dfd..322383a1f9f2edf28a0d740a48511bd83c863274 100644 (file)
@@ -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)));
This page took 0.027457 seconds and 4 git commands to generate.