diff options
| -rw-r--r-- | net/sctp/sm_statefuns.c | 103 |
1 files changed, 78 insertions, 25 deletions
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index fd2dfdd7d7fd..71cad56dd73f 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -97,6 +97,13 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | |||
| 97 | const struct sctp_association *asoc, | 97 | const struct sctp_association *asoc, |
| 98 | struct sctp_transport *transport); | 98 | struct sctp_transport *transport); |
| 99 | 99 | ||
| 100 | static sctp_disposition_t sctp_sf_abort_violation( | ||
| 101 | const struct sctp_association *asoc, | ||
| 102 | void *arg, | ||
| 103 | sctp_cmd_seq_t *commands, | ||
| 104 | const __u8 *payload, | ||
| 105 | const size_t paylen); | ||
| 106 | |||
| 100 | static sctp_disposition_t sctp_sf_violation_chunklen( | 107 | static sctp_disposition_t sctp_sf_violation_chunklen( |
| 101 | const struct sctp_endpoint *ep, | 108 | const struct sctp_endpoint *ep, |
| 102 | const struct sctp_association *asoc, | 109 | const struct sctp_association *asoc, |
| @@ -104,6 +111,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
| 104 | void *arg, | 111 | void *arg, |
| 105 | sctp_cmd_seq_t *commands); | 112 | sctp_cmd_seq_t *commands); |
| 106 | 113 | ||
| 114 | static sctp_disposition_t sctp_sf_violation_ctsn( | ||
| 115 | const struct sctp_endpoint *ep, | ||
| 116 | const struct sctp_association *asoc, | ||
| 117 | const sctp_subtype_t type, | ||
| 118 | void *arg, | ||
| 119 | sctp_cmd_seq_t *commands); | ||
| 120 | |||
| 107 | /* Small helper function that checks if the chunk length | 121 | /* Small helper function that checks if the chunk length |
| 108 | * is of the appropriate length. The 'required_length' argument | 122 | * is of the appropriate length. The 'required_length' argument |
| 109 | * is set to be the size of a specific chunk we are testing. | 123 | * is set to be the size of a specific chunk we are testing. |
| @@ -2880,6 +2894,13 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, | |||
| 2880 | return SCTP_DISPOSITION_DISCARD; | 2894 | return SCTP_DISPOSITION_DISCARD; |
| 2881 | } | 2895 | } |
| 2882 | 2896 | ||
| 2897 | /* If Cumulative TSN Ack beyond the max tsn currently | ||
| 2898 | * send, terminating the association and respond to the | ||
| 2899 | * sender with an ABORT. | ||
| 2900 | */ | ||
| 2901 | if (!TSN_lt(ctsn, asoc->next_tsn)) | ||
| 2902 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | ||
| 2903 | |||
| 2883 | /* Return this SACK for further processing. */ | 2904 | /* Return this SACK for further processing. */ |
| 2884 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); | 2905 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); |
| 2885 | 2906 | ||
| @@ -3691,40 +3712,21 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, | |||
| 3691 | return SCTP_DISPOSITION_VIOLATION; | 3712 | return SCTP_DISPOSITION_VIOLATION; |
| 3692 | } | 3713 | } |
| 3693 | 3714 | ||
| 3694 | |||
| 3695 | /* | 3715 | /* |
| 3696 | * Handle a protocol violation when the chunk length is invalid. | 3716 | * Common function to handle a protocol violation. |
| 3697 | * "Invalid" length is identified as smaller then the minimal length a | ||
| 3698 | * given chunk can be. For example, a SACK chunk has invalid length | ||
| 3699 | * if it's length is set to be smaller then the size of sctp_sack_chunk_t. | ||
| 3700 | * | ||
| 3701 | * We inform the other end by sending an ABORT with a Protocol Violation | ||
| 3702 | * error code. | ||
| 3703 | * | ||
| 3704 | * Section: Not specified | ||
| 3705 | * Verification Tag: Nothing to do | ||
| 3706 | * Inputs | ||
| 3707 | * (endpoint, asoc, chunk) | ||
| 3708 | * | ||
| 3709 | * Outputs | ||
| 3710 | * (reply_msg, msg_up, counters) | ||
| 3711 | * | ||
| 3712 | * Generate an ABORT chunk and terminate the association. | ||
| 3713 | */ | 3717 | */ |
| 3714 | static sctp_disposition_t sctp_sf_violation_chunklen( | 3718 | static sctp_disposition_t sctp_sf_abort_violation( |
| 3715 | const struct sctp_endpoint *ep, | ||
| 3716 | const struct sctp_association *asoc, | 3719 | const struct sctp_association *asoc, |
| 3717 | const sctp_subtype_t type, | ||
| 3718 | void *arg, | 3720 | void *arg, |
| 3719 | sctp_cmd_seq_t *commands) | 3721 | sctp_cmd_seq_t *commands, |
| 3722 | const __u8 *payload, | ||
| 3723 | const size_t paylen) | ||
| 3720 | { | 3724 | { |
| 3721 | struct sctp_chunk *chunk = arg; | 3725 | struct sctp_chunk *chunk = arg; |
| 3722 | struct sctp_chunk *abort = NULL; | 3726 | struct sctp_chunk *abort = NULL; |
| 3723 | char err_str[]="The following chunk had invalid length:"; | ||
| 3724 | 3727 | ||
| 3725 | /* Make the abort chunk. */ | 3728 | /* Make the abort chunk. */ |
| 3726 | abort = sctp_make_abort_violation(asoc, chunk, err_str, | 3729 | abort = sctp_make_abort_violation(asoc, chunk, payload, paylen); |
| 3727 | sizeof(err_str)); | ||
| 3728 | if (!abort) | 3730 | if (!abort) |
| 3729 | goto nomem; | 3731 | goto nomem; |
| 3730 | 3732 | ||
| @@ -3756,6 +3758,57 @@ nomem: | |||
| 3756 | return SCTP_DISPOSITION_NOMEM; | 3758 | return SCTP_DISPOSITION_NOMEM; |
| 3757 | } | 3759 | } |
| 3758 | 3760 | ||
| 3761 | /* | ||
| 3762 | * Handle a protocol violation when the chunk length is invalid. | ||
| 3763 | * "Invalid" length is identified as smaller then the minimal length a | ||
| 3764 | * given chunk can be. For example, a SACK chunk has invalid length | ||
| 3765 | * if it's length is set to be smaller then the size of sctp_sack_chunk_t. | ||
| 3766 | * | ||
| 3767 | * We inform the other end by sending an ABORT with a Protocol Violation | ||
| 3768 | * error code. | ||
| 3769 | * | ||
| 3770 | * Section: Not specified | ||
| 3771 | * Verification Tag: Nothing to do | ||
| 3772 | * Inputs | ||
| 3773 | * (endpoint, asoc, chunk) | ||
| 3774 | * | ||
| 3775 | * Outputs | ||
| 3776 | * (reply_msg, msg_up, counters) | ||
| 3777 | * | ||
| 3778 | * Generate an ABORT chunk and terminate the association. | ||
| 3779 | */ | ||
| 3780 | static sctp_disposition_t sctp_sf_violation_chunklen( | ||
| 3781 | const struct sctp_endpoint *ep, | ||
| 3782 | const struct sctp_association *asoc, | ||
| 3783 | const sctp_subtype_t type, | ||
| 3784 | void *arg, | ||
| 3785 | sctp_cmd_seq_t *commands) | ||
| 3786 | { | ||
| 3787 | char err_str[]="The following chunk had invalid length:"; | ||
| 3788 | |||
| 3789 | return sctp_sf_abort_violation(asoc, arg, commands, err_str, | ||
| 3790 | sizeof(err_str)); | ||
| 3791 | } | ||
| 3792 | |||
| 3793 | /* Handle a protocol violation when the peer trying to advance the | ||
| 3794 | * cumulative tsn ack to a point beyond the max tsn currently sent. | ||
| 3795 | * | ||
| 3796 | * We inform the other end by sending an ABORT with a Protocol Violation | ||
| 3797 | * error code. | ||
| 3798 | */ | ||
| 3799 | static sctp_disposition_t sctp_sf_violation_ctsn( | ||
| 3800 | const struct sctp_endpoint *ep, | ||
| 3801 | const struct sctp_association *asoc, | ||
| 3802 | const sctp_subtype_t type, | ||
| 3803 | void *arg, | ||
| 3804 | sctp_cmd_seq_t *commands) | ||
| 3805 | { | ||
| 3806 | char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; | ||
| 3807 | |||
| 3808 | return sctp_sf_abort_violation(asoc, arg, commands, err_str, | ||
| 3809 | sizeof(err_str)); | ||
| 3810 | } | ||
| 3811 | |||
| 3759 | /*************************************************************************** | 3812 | /*************************************************************************** |
| 3760 | * These are the state functions for handling primitive (Section 10) events. | 3813 | * These are the state functions for handling primitive (Section 10) events. |
| 3761 | ***************************************************************************/ | 3814 | ***************************************************************************/ |
