aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Tuexen <tuexen@FreeBSD.org>2023-08-19 10:35:49 +0000
committerMichael Tuexen <tuexen@FreeBSD.org>2023-08-19 10:35:49 +0000
commit4f14d4b6b7f0ca49b14379e48117121af3ed2669 (patch)
tree3157758bd6455e91f28cd5948174aa954f4663ef
parent0d30f3afa62b4740810006476eb9de0c480619a1 (diff)
downloadsrc-4f14d4b6b7f0ca49b14379e48117121af3ed2669.tar.gz
src-4f14d4b6b7f0ca49b14379e48117121af3ed2669.zip
sctp: cleanup handling of graceful shutdown of the peer
Don't handle a graceful shutdown of the peer as an implicit signal that all partial messages are complete. First, this is not implemented correctly and second this should not be done by the peer. It is more appropriate to handle this as a protocol violation. Remove the incorrect code and leave detecting the protocol violation and its handling in a followup commit. MFC after: 1 week
-rw-r--r--sys/netinet/sctp_input.c63
-rw-r--r--sys/netinet/sctp_pcb.c11
-rw-r--r--sys/netinet/sctp_structs.h9
3 files changed, 16 insertions, 67 deletions
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 81b011b7e78a..059c6ded2e5e 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -837,8 +837,7 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
int some_on_streamwheel;
int old_state;
- SCTPDBG(SCTP_DEBUG_INPUT2,
- "sctp_handle_shutdown: handling SHUTDOWN\n");
+ SCTPDBG(SCTP_DEBUG_INPUT2, "sctp_handle_shutdown: handling SHUTDOWN\n");
if (stcb == NULL)
return;
asoc = &stcb->asoc;
@@ -855,40 +854,12 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
if (*abort_flag) {
return;
}
- if (asoc->control_pdapi) {
- /*
- * With a normal shutdown we assume the end of last record.
- */
- SCTP_INP_READ_LOCK(stcb->sctp_ep);
- if (asoc->control_pdapi->on_strm_q) {
- struct sctp_stream_in *strm;
-
- strm = &asoc->strmin[asoc->control_pdapi->sinfo_stream];
- if (asoc->control_pdapi->on_strm_q == SCTP_ON_UNORDERED) {
- /* Unordered */
- TAILQ_REMOVE(&strm->uno_inqueue, asoc->control_pdapi, next_instrm);
- asoc->control_pdapi->on_strm_q = 0;
- } else if (asoc->control_pdapi->on_strm_q == SCTP_ON_ORDERED) {
- /* Ordered */
- TAILQ_REMOVE(&strm->inqueue, asoc->control_pdapi, next_instrm);
- asoc->control_pdapi->on_strm_q = 0;
-#ifdef INVARIANTS
- } else {
- panic("Unknown state on ctrl:%p on_strm_q:%d",
- asoc->control_pdapi,
- asoc->control_pdapi->on_strm_q);
-#endif
- }
- }
- asoc->control_pdapi->end_added = 1;
- asoc->control_pdapi->pdapi_aborted = 1;
- asoc->control_pdapi = NULL;
- SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
- if (stcb->sctp_socket) {
- sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
- }
- }
- /* goto SHUTDOWN_RECEIVED state to block new requests */
+ /*
+ * FIXME MT: Handle the case where there are still incomplete
+ * received user messages or known missing user messages from the
+ * peer. One way to handle this is to abort the associations in this
+ * case.
+ */
if (stcb->sctp_socket) {
if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_RECEIVED) &&
(SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT) &&
@@ -949,8 +920,9 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
SCTPDBG(SCTP_DEBUG_INPUT2,
"sctp_handle_shutdown_ack: handling SHUTDOWN ACK\n");
- if (stcb == NULL)
+ if (stcb == NULL) {
return;
+ }
asoc = &stcb->asoc;
/* process according to association state */
@@ -967,17 +939,12 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
SCTP_TCB_UNLOCK(stcb);
return;
}
- if (asoc->control_pdapi) {
- /*
- * With a normal shutdown we assume the end of last record.
- */
- SCTP_INP_READ_LOCK(stcb->sctp_ep);
- asoc->control_pdapi->end_added = 1;
- asoc->control_pdapi->pdapi_aborted = 1;
- asoc->control_pdapi = NULL;
- SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
- sctp_sorwakeup(stcb->sctp_ep, stcb->sctp_socket);
- }
+ /*
+ * FIXME MT: Handle the case where there are still incomplete
+ * received user messages or known missing user messages from the
+ * peer. One way to handle this is to abort the associations in this
+ * case.
+ */
#ifdef INVARIANTS
if (!TAILQ_EMPTY(&asoc->send_queue) ||
!TAILQ_EMPTY(&asoc->sent_queue) ||
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index ac47b6aa1bfc..16cde18c4c1d 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -3405,7 +3405,6 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
continue;
}
if ((stcb->asoc.size_on_reasm_queue > 0) ||
- (stcb->asoc.control_pdapi) ||
(stcb->asoc.size_on_all_streams > 0) ||
((so != NULL) && (SCTP_SBAVAIL(&so->so_rcv) > 0))) {
/* Left with Data unread */
@@ -4762,18 +4761,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
* now.
*/
if (sq->end_added == 0) {
- /* Held for PD-API clear that. */
+ /* Held for PD-API, clear that. */
sq->pdapi_aborted = 1;
sq->held_length = 0;
if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT) && (so != NULL)) {
- /*
- * Need to add a PD-API
- * aborted indication.
- * Setting the control_pdapi
- * assures that it will be
- * added right after this
- * msg.
- */
sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
stcb,
SCTP_PARTIAL_DELIVERY_ABORTED,
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 278afb2cc554..53d9bfd4f445 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -956,15 +956,6 @@ struct sctp_association {
uint32_t fast_recovery_tsn;
uint32_t sat_t3_recovery_tsn;
uint32_t tsn_last_delivered;
- /*
- * For the pd-api we should re-write this a bit more efficient. We
- * could have multiple sctp_queued_to_read's that we are building at
- * once. Now we only do this when we get ready to deliver to the
- * socket buffer. Note that we depend on the fact that the struct is
- * "stuck" on the read queue until we finish all the pd-api.
- */
- struct sctp_queued_to_read *control_pdapi;
-
uint32_t tsn_of_pdapi_last_delivered;
uint32_t pdapi_ppid;
uint32_t context;