aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/input.c2
-rw-r--r--net/sctp/sm_statefuns.c54
-rw-r--r--net/sctp/sm_statetable.c4
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)
369void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc, 369void 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 */
2619sctp_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 */