diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/sm_statefuns.c | 45 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 2 |
2 files changed, 46 insertions, 1 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 12f62174f4a1..a6a0ea71ae93 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -2608,6 +2608,51 @@ out: | |||
2608 | return disposition; | 2608 | return disposition; |
2609 | } | 2609 | } |
2610 | 2610 | ||
2611 | /* | ||
2612 | * sctp_sf_do_9_2_shut_ctsn | ||
2613 | * | ||
2614 | * Once an endpoint has reached the SHUTDOWN-RECEIVED state, | ||
2615 | * it MUST NOT send a SHUTDOWN in response to a ULP request. | ||
2616 | * The Cumulative TSN Ack of the received SHUTDOWN chunk | ||
2617 | * MUST be processed. | ||
2618 | */ | ||
2619 | sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | ||
2620 | const struct sctp_association *asoc, | ||
2621 | const sctp_subtype_t type, | ||
2622 | void *arg, | ||
2623 | sctp_cmd_seq_t *commands) | ||
2624 | { | ||
2625 | struct sctp_chunk *chunk = arg; | ||
2626 | sctp_shutdownhdr_t *sdh; | ||
2627 | |||
2628 | if (!sctp_vtag_verify(chunk, asoc)) | ||
2629 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
2630 | |||
2631 | /* Make sure that the SHUTDOWN chunk has a valid length. */ | ||
2632 | if (!sctp_chunk_length_valid(chunk, | ||
2633 | sizeof(struct sctp_shutdown_chunk_t))) | ||
2634 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | ||
2635 | commands); | ||
2636 | |||
2637 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; | ||
2638 | |||
2639 | /* If Cumulative TSN Ack beyond the max tsn currently | ||
2640 | * send, terminating the association and respond to the | ||
2641 | * sender with an ABORT. | ||
2642 | */ | ||
2643 | if (!TSN_lt(ntohl(sdh->cum_tsn_ack), asoc->next_tsn)) | ||
2644 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | ||
2645 | |||
2646 | /* verify, by checking the Cumulative TSN Ack field of the | ||
2647 | * chunk, that all its outstanding DATA chunks have been | ||
2648 | * received by the SHUTDOWN sender. | ||
2649 | */ | ||
2650 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN, | ||
2651 | SCTP_BE32(sdh->cum_tsn_ack)); | ||
2652 | |||
2653 | return SCTP_DISPOSITION_CONSUME; | ||
2654 | } | ||
2655 | |||
2611 | /* RFC 2960 9.2 | 2656 | /* RFC 2960 9.2 |
2612 | * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk | 2657 | * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk |
2613 | * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination | 2658 | * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index a5b5590dc1a6..5c8186d88c61 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -270,7 +270,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
270 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 270 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
271 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ | 271 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown_ack), \ |
272 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ | 272 | /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ |
273 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 273 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shut_ctsn), \ |
274 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ | 274 | /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ |
275 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 275 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
276 | } /* TYPE_SCTP_SHUTDOWN */ | 276 | } /* TYPE_SCTP_SHUTDOWN */ |