diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/input.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 54 | ||||
-rw-r--r-- | net/sctp/sm_statetable.c | 4 |
3 files changed, 57 insertions, 3 deletions
diff --git a/net/sctp/input.c b/net/sctp/input.c index a49fa80b57b9..bf612d954d41 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -369,7 +369,7 @@ static void sctp_add_backlog(struct sock *sk, struct sk_buff *skb) | |||
369 | void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, | 369 | void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, |
370 | struct sctp_transport *t, __u32 pmtu) | 370 | struct sctp_transport *t, __u32 pmtu) |
371 | { | 371 | { |
372 | if (!t || (t->pathmtu == pmtu)) | 372 | if (!t || (t->pathmtu <= pmtu)) |
373 | return; | 373 | return; |
374 | 374 | ||
375 | if (sock_owned_by_user(sk)) { | 375 | if (sock_owned_by_user(sk)) { |
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 |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index dd4ddc40c0ad..5c8186d88c61 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -266,11 +266,11 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
266 | /* SCTP_STATE_ESTABLISHED */ \ | 266 | /* SCTP_STATE_ESTABLISHED */ \ |
267 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ | 267 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ |
268 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 268 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
269 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 269 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_shutdown), \ |
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 */ |