aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--slirp/slirp.c12
-rw-r--r--slirp/socket.c34
-rw-r--r--slirp/socket.h2
-rw-r--r--slirp/tcp_input.c6
-rw-r--r--slirp/tcp_subr.c7
5 files changed, 50 insertions, 11 deletions
diff --git a/slirp/slirp.c b/slirp/slirp.c
index fef526c5ad..9f4bea3d3b 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -534,7 +534,12 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
* test for G_IO_IN below if this succeeds
*/
if (revents & G_IO_PRI) {
- sorecvoob(so);
+ ret = sorecvoob(so);
+ if (ret < 0) {
+ /* Socket error might have resulted in the socket being
+ * removed, do not try to do anything more with it. */
+ continue;
+ }
}
/*
* Check sockets for reading
@@ -553,6 +558,11 @@ void slirp_pollfds_poll(GArray *pollfds, int select_error)
if (ret > 0) {
tcp_output(sototcpcb(so));
}
+ if (ret < 0) {
+ /* Socket error might have resulted in the socket being
+ * removed, do not try to do anything more with it. */
+ continue;
+ }
}
/*
diff --git a/slirp/socket.c b/slirp/socket.c
index b836c42b8e..bd97b2d682 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -176,9 +176,24 @@ soread(struct socket *so)
if (nn < 0 && (errno == EINTR || errno == EAGAIN))
return 0;
else {
+ int err;
+ socklen_t slen = sizeof err;
+
+ err = errno;
+ if (nn == 0) {
+ getsockopt(so->s, SOL_SOCKET, SO_ERROR,
+ &err, &slen);
+ }
+
DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno)));
sofcantrcvmore(so);
- tcp_sockclosed(sototcpcb(so));
+
+ if (err == ECONNRESET || err == ECONNREFUSED
+ || err == ENOTCONN || err == EPIPE) {
+ tcp_drop(sototcpcb(so), err);
+ } else {
+ tcp_sockclosed(sototcpcb(so));
+ }
return -1;
}
}
@@ -260,10 +275,11 @@ err:
* so when OOB data arrives, we soread() it and everything
* in the send buffer is sent as urgent data
*/
-void
+int
sorecvoob(struct socket *so)
{
struct tcpcb *tp = sototcpcb(so);
+ int ret;
DEBUG_CALL("sorecvoob");
DEBUG_ARG("so = %p", so);
@@ -276,11 +292,15 @@ sorecvoob(struct socket *so)
* urgent data, or the read() doesn't return all the
* urgent data.
*/
- soread(so);
- tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
- tp->t_force = 1;
- tcp_output(tp);
- tp->t_force = 0;
+ ret = soread(so);
+ if (ret > 0) {
+ tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
+ tp->t_force = 1;
+ tcp_output(tp);
+ tp->t_force = 0;
+ }
+
+ return ret;
}
/*
diff --git a/slirp/socket.h b/slirp/socket.h
index e9c9b053dc..7dca506973 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -127,7 +127,7 @@ struct socket *solookup(struct socket **, struct socket *,
struct socket *socreate(Slirp *);
void sofree(struct socket *);
int soread(struct socket *);
-void sorecvoob(struct socket *);
+int sorecvoob(struct socket *);
int sosendoob(struct socket *);
int sowrite(struct socket *);
void sorecvfrom(struct socket *);
diff --git a/slirp/tcp_input.c b/slirp/tcp_input.c
index 1fcca3040e..5433e7fe9c 100644
--- a/slirp/tcp_input.c
+++ b/slirp/tcp_input.c
@@ -725,6 +725,12 @@ findso:
so->so_ti = ti;
tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
tp->t_state = TCPS_SYN_RECEIVED;
+ /*
+ * Initialize receive sequence numbers now so that we can send a
+ * valid RST if the remote end rejects our connection.
+ */
+ tp->irs = ti->ti_seq;
+ tcp_rcvseqinit(tp);
tcp_template(tp);
}
return;
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index dbfd2c673b..32ff452e93 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -356,6 +356,10 @@ tcp_sockclosed(struct tcpcb *tp)
DEBUG_CALL("tcp_sockclosed");
DEBUG_ARG("tp = %p", tp);
+ if (!tp) {
+ return;
+ }
+
switch (tp->t_state) {
case TCPS_CLOSED:
@@ -374,8 +378,7 @@ tcp_sockclosed(struct tcpcb *tp)
tp->t_state = TCPS_LAST_ACK;
break;
}
- if (tp)
- tcp_output(tp);
+ tcp_output(tp);
}
/*