aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/sm_statefuns.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/sm_statefuns.c')
-rw-r--r--net/sctp/sm_statefuns.c78
1 files changed, 72 insertions, 6 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index d4c3fbc4671e..1c4e5d6c29c0 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1123,19 +1123,17 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep,
1123 if (from_addr.sa.sa_family == AF_INET6) { 1123 if (from_addr.sa.sa_family == AF_INET6) {
1124 if (net_ratelimit()) 1124 if (net_ratelimit())
1125 printk(KERN_WARNING 1125 printk(KERN_WARNING
1126 "%s association %p could not find address " 1126 "%s association %p could not find address %pI6\n",
1127 NIP6_FMT "\n",
1128 __func__, 1127 __func__,
1129 asoc, 1128 asoc,
1130 NIP6(from_addr.v6.sin6_addr)); 1129 &from_addr.v6.sin6_addr);
1131 } else { 1130 } else {
1132 if (net_ratelimit()) 1131 if (net_ratelimit())
1133 printk(KERN_WARNING 1132 printk(KERN_WARNING
1134 "%s association %p could not find address " 1133 "%s association %p could not find address %pI4\n",
1135 NIPQUAD_FMT "\n",
1136 __func__, 1134 __func__,
1137 asoc, 1135 asoc,
1138 NIPQUAD(from_addr.v4.sin_addr.s_addr)); 1136 &from_addr.v4.sin_addr.s_addr);
1139 } 1137 }
1140 return SCTP_DISPOSITION_DISCARD; 1138 return SCTP_DISPOSITION_DISCARD;
1141 } 1139 }
@@ -2544,6 +2542,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2544 sctp_shutdownhdr_t *sdh; 2542 sctp_shutdownhdr_t *sdh;
2545 sctp_disposition_t disposition; 2543 sctp_disposition_t disposition;
2546 struct sctp_ulpevent *ev; 2544 struct sctp_ulpevent *ev;
2545 __u32 ctsn;
2547 2546
2548 if (!sctp_vtag_verify(chunk, asoc)) 2547 if (!sctp_vtag_verify(chunk, asoc))
2549 return sctp_sf_pdiscard(ep, asoc, type, arg, commands); 2548 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
@@ -2558,6 +2557,14 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep,
2558 sdh = (sctp_shutdownhdr_t *)chunk->skb->data; 2557 sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
2559 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t)); 2558 skb_pull(chunk->skb, sizeof(sctp_shutdownhdr_t));
2560 chunk->subh.shutdown_hdr = sdh; 2559 chunk->subh.shutdown_hdr = sdh;
2560 ctsn = ntohl(sdh->cum_tsn_ack);
2561
2562 /* If Cumulative TSN Ack beyond the max tsn currently
2563 * send, terminating the association and respond to the
2564 * sender with an ABORT.
2565 */
2566 if (!TSN_lt(ctsn, asoc->next_tsn))
2567 return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
2561 2568
2562 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT 2569 /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT
2563 * When a peer sends a SHUTDOWN, SCTP delivers this notification to 2570 * When a peer sends a SHUTDOWN, SCTP delivers this notification to
@@ -2599,6 +2606,51 @@ out:
2599 return disposition; 2606 return disposition;
2600} 2607}
2601 2608
2609/*
2610 * sctp_sf_do_9_2_shut_ctsn
2611 *
2612 * Once an endpoint has reached the SHUTDOWN-RECEIVED state,
2613 * it MUST NOT send a SHUTDOWN in response to a ULP request.
2614 * The Cumulative TSN Ack of the received SHUTDOWN chunk
2615 * MUST be processed.
2616 */
2617sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep,
2618 const struct sctp_association *asoc,
2619 const sctp_subtype_t type,
2620 void *arg,
2621 sctp_cmd_seq_t *commands)
2622{
2623 struct sctp_chunk *chunk = arg;
2624 sctp_shutdownhdr_t *sdh;
2625
2626 if (!sctp_vtag_verify(chunk, asoc))
2627 return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
2628
2629 /* Make sure that the SHUTDOWN chunk has a valid length. */
2630 if (!sctp_chunk_length_valid(chunk,
2631 sizeof(struct sctp_shutdown_chunk_t)))
2632 return sctp_sf_violation_chunklen(ep, asoc, type, arg,
2633 commands);
2634
2635 sdh = (sctp_shutdownhdr_t *)chunk->skb->data;
2636
2637 /* If Cumulative TSN Ack beyond the max tsn currently
2638 * send, terminating the association and respond to the
2639 * sender with an ABORT.
2640 */
2641 if (!TSN_lt(ntohl(sdh->cum_tsn_ack), asoc->next_tsn))
2642 return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands);
2643
2644 /* verify, by checking the Cumulative TSN Ack field of the
2645 * chunk, that all its outstanding DATA chunks have been
2646 * received by the SHUTDOWN sender.
2647 */
2648 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_CTSN,
2649 SCTP_BE32(sdh->cum_tsn_ack));
2650
2651 return SCTP_DISPOSITION_CONSUME;
2652}
2653
2602/* RFC 2960 9.2 2654/* RFC 2960 9.2
2603 * If an endpoint is in SHUTDOWN-ACK-SENT state and receives an INIT chunk 2655 * 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 2656 * (e.g., if the SHUTDOWN COMPLETE was lost) with source and destination
@@ -3637,6 +3689,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
3637{ 3689{
3638 struct sctp_chunk *chunk = arg; 3690 struct sctp_chunk *chunk = arg;
3639 struct sctp_fwdtsn_hdr *fwdtsn_hdr; 3691 struct sctp_fwdtsn_hdr *fwdtsn_hdr;
3692 struct sctp_fwdtsn_skip *skip;
3640 __u16 len; 3693 __u16 len;
3641 __u32 tsn; 3694 __u32 tsn;
3642 3695
@@ -3666,6 +3719,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep,
3666 if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 3719 if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0)
3667 goto discard_noforce; 3720 goto discard_noforce;
3668 3721
3722 /* Silently discard the chunk if stream-id is not valid */
3723 sctp_walk_fwdtsn(skip, chunk) {
3724 if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams)
3725 goto discard_noforce;
3726 }
3727
3669 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 3728 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
3670 if (len > sizeof(struct sctp_fwdtsn_hdr)) 3729 if (len > sizeof(struct sctp_fwdtsn_hdr))
3671 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 3730 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,
@@ -3697,6 +3756,7 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
3697{ 3756{
3698 struct sctp_chunk *chunk = arg; 3757 struct sctp_chunk *chunk = arg;
3699 struct sctp_fwdtsn_hdr *fwdtsn_hdr; 3758 struct sctp_fwdtsn_hdr *fwdtsn_hdr;
3759 struct sctp_fwdtsn_skip *skip;
3700 __u16 len; 3760 __u16 len;
3701 __u32 tsn; 3761 __u32 tsn;
3702 3762
@@ -3726,6 +3786,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast(
3726 if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0) 3786 if (sctp_tsnmap_check(&asoc->peer.tsn_map, tsn) < 0)
3727 goto gen_shutdown; 3787 goto gen_shutdown;
3728 3788
3789 /* Silently discard the chunk if stream-id is not valid */
3790 sctp_walk_fwdtsn(skip, chunk) {
3791 if (ntohs(skip->stream) >= asoc->c.sinit_max_instreams)
3792 goto gen_shutdown;
3793 }
3794
3729 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn)); 3795 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_FWDTSN, SCTP_U32(tsn));
3730 if (len > sizeof(struct sctp_fwdtsn_hdr)) 3796 if (len > sizeof(struct sctp_fwdtsn_hdr))
3731 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN, 3797 sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_FWDTSN,