diff options
Diffstat (limited to 'net/sctp/sm_statefuns.c')
| -rw-r--r-- | net/sctp/sm_statefuns.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index d4c3fbc4671e..a6a0ea71ae93 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -2544,6 +2544,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
| 2544 | sctp_shutdownhdr_t *sdh; | 2544 | sctp_shutdownhdr_t *sdh; |
| 2545 | sctp_disposition_t disposition; | 2545 | sctp_disposition_t disposition; |
| 2546 | struct sctp_ulpevent *ev; | 2546 | struct sctp_ulpevent *ev; |
| 2547 | __u32 ctsn; | ||
| 2547 | 2548 | ||
| 2548 | if (!sctp_vtag_verify(chunk, asoc)) | 2549 | if (!sctp_vtag_verify(chunk, asoc)) |
| 2549 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2550 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
| @@ -2558,6 +2559,14 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
| 2558 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; | 2559 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; |
| 2559 | skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); | 2560 | skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); |
| 2560 | chunk->subh.shutdown_hdr = sdh; | 2561 | chunk->subh.shutdown_hdr = sdh; |
| 2562 | ctsn = ntohl(sdh->cum_tsn_ack); | ||
| 2563 | |||
| 2564 | /* If Cumulative TSN Ack beyond the max tsn currently | ||
| 2565 | * send, terminating the association and respond to the | ||
| 2566 | * sender with an ABORT. | ||
| 2567 | */ | ||
| 2568 | if (!TSN_lt(ctsn, asoc->next_tsn)) | ||
| 2569 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | ||
| 2561 | 2570 | ||
| 2562 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT | 2571 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT |
| 2563 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to | 2572 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to |
| @@ -2599,6 +2608,51 @@ out: | |||
| 2599 | return disposition; | 2608 | return disposition; |
| 2600 | } | 2609 | } |
| 2601 | 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 | |||
| 2602 | /* RFC 2960 9.2 | 2656 | /* RFC 2960 9.2 |
| 2603 | * 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 |
| 2604 | * (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 |
