This introduces a regression reported by koobs@ when running a pyhton test suite on a loaded system. This patch resulted in a failing accept() call, when the association was setup and gracefully shutdown by the peer before accept was called. So the following packetdrill script would fail: +0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +0.0 bind(3, ..., ...) = 0 +0.0 listen(3, 1) = 0 +0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=15000, os=1, is=1, tsn=1] +0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=1, ...] +0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] +0.0 > sctp: COOKIE_ACK[flgs=0] +0.0 < sctp: DATA[flgs=BE, len=116, tsn=1, sid=0, ssn=0, ppid=0] +0.0 > sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=..., gaps=[], dups=[]] +0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0] +0.0 > sctp: SHUTDOWN_ACK[flgs=0] +0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0] +0.0 accept(3, ..., ...) = 4 +0.0 close(3) = 0 +0.0 recv(4, ..., 4096, 0) = 100 +0.0 recv(4, ..., 4096, 0) = 0 +0.0 close(4) = 0 Reported by: koops@
This commit is contained in:
parent
23e3c0880d
commit
24187cfe72
@ -4739,31 +4739,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
else
|
||||
so = inp->sctp_socket;
|
||||
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
|
||||
/*
|
||||
* For TCP type we need special handling when we are
|
||||
* connected. We also include the peel'ed off ones to.
|
||||
*/
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
|
||||
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
|
||||
inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
|
||||
if (so) {
|
||||
SOCKBUF_LOCK(&so->so_rcv);
|
||||
so->so_state &= ~(SS_ISCONNECTING |
|
||||
SS_ISDISCONNECTING |
|
||||
SS_ISCONFIRMING |
|
||||
SS_ISCONNECTED);
|
||||
so->so_state |= SS_ISDISCONNECTED;
|
||||
socantrcvmore_locked(so);
|
||||
socantsendmore(so);
|
||||
sctp_sowwakeup(inp, so);
|
||||
sctp_sorwakeup(inp, so);
|
||||
SCTP_SOWAKEUP(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We used timer based freeing if a reader or writer is in the way.
|
||||
* So we first check if we are actually being called from a timer,
|
||||
@ -4891,6 +4866,31 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
/* nothing around */
|
||||
so = NULL;
|
||||
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
|
||||
/*
|
||||
* For TCP type we need special handling when we are
|
||||
* connected. We also include the peel'ed off ones to.
|
||||
*/
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
|
||||
inp->sctp_flags &= ~SCTP_PCB_FLAGS_CONNECTED;
|
||||
inp->sctp_flags |= SCTP_PCB_FLAGS_WAS_CONNECTED;
|
||||
if (so) {
|
||||
SOCKBUF_LOCK(&so->so_rcv);
|
||||
so->so_state &= ~(SS_ISCONNECTING |
|
||||
SS_ISDISCONNECTING |
|
||||
SS_ISCONFIRMING |
|
||||
SS_ISCONNECTED);
|
||||
so->so_state |= SS_ISDISCONNECTED;
|
||||
socantrcvmore_locked(so);
|
||||
socantsendmore(so);
|
||||
sctp_sowwakeup(inp, so);
|
||||
sctp_sorwakeup(inp, so);
|
||||
SCTP_SOWAKEUP(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make it invalid too, that way if its about to run it will abort
|
||||
* and return.
|
||||
|
Loading…
x
Reference in New Issue
Block a user