summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/uipc_socket.c11
-rw-r--r--sys/netinet/tcp_usrreq.c35
2 files changed, 38 insertions, 8 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 4f2c486463ad..8e911b668346 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94
- * $Id: uipc_socket.c,v 1.57 1999/05/03 23:57:23 billf Exp $
+ * $Id: uipc_socket.c,v 1.58 1999/05/21 15:54:40 ache Exp $
*/
#include <sys/param.h>
@@ -538,6 +538,15 @@ nopages:
if (dontroute)
so->so_options |= SO_DONTROUTE;
s = splnet(); /* XXX */
+ /*
+ * XXX all the SS_CANTSENDMORE checks previously
+ * done could be out of date. We could have recieved
+ * a reset packet in an interrupt or maybe we slept
+ * while doing page faults in uiomove() etc. We could
+ * probably recheck again inside the splnet() protection
+ * here, but there are probably other places that this
+ * also happens. We must rethink this.
+ */
error = (*so->so_proto->pr_usrreqs->pru_send)(so,
(flags & MSG_OOB) ? PRUS_OOB :
/*
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 223c8d5781ef..b6d4ae8a5911 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94
- * $Id: tcp_usrreq.c,v 1.42 1999/04/28 11:37:50 phk Exp $
+ * $Id: tcp_usrreq.c,v 1.43 1999/05/03 23:57:32 billf Exp $
*/
#include "opt_tcpdebug.h"
@@ -326,7 +326,10 @@ tcp_usr_rcvd(struct socket *so, int flags)
/*
* Do a send by putting data in output queue and updating urgent
- * marker if URG set. Possibly send more data.
+ * marker if URG set. Possibly send more data. Unlike the other
+ * pru_*() routines, the mbuf chains are our responsibility. We
+ * must either enqueue them or free them. The other pru_* routines
+ * generally are caller-frees.
*/
static int
tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
@@ -336,16 +339,34 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
int error = 0;
struct inpcb *inp = sotoinpcb(so);
struct tcpcb *tp;
+ TCPDEBUG0;
- COMMON_START();
- if (control && control->m_len) {
- m_freem(control); /* XXX shouldn't caller do this??? */
+ if (inp == NULL) {
+ /*
+ * OOPS! we lost a race, the TCP session got reset after
+ * we checked SS_CANTSENDMORE, eg: while doing uiomove or a
+ * network interrupt in the non-splnet() section of sosend().
+ */
if (m)
m_freem(m);
- error = EINVAL;
+ if (control)
+ m_freem(control);
+ error = ECONNRESET; /* XXX EPIPE? */
goto out;
}
-
+ tp = intotcpcb(inp);
+ TCPDEBUG1();
+ if (control) {
+ /* TCP doesn't do control messages (rights, creds, etc) */
+ if (control->m_len) {
+ m_freem(control);
+ if (m)
+ m_freem(m);
+ error = EINVAL;
+ goto out;
+ }
+ m_freem(control); /* empty control, just free it */
+ }
if(!(flags & PRUS_OOB)) {
sbappend(&so->so_snd, m);
if (nam && tp->t_state < TCPS_SYN_SENT) {