Commit 2e6dc4d9 authored by Xin Long's avatar Xin Long Committed by David S. Miller

sctp: improve the events for sctp stream reset

This patch is to improve sctp stream reset events in 4 places:

  1. In sctp_process_strreset_outreq(), the flag should always be set with
     SCTP_STREAM_RESET_INCOMING_SSN instead of OUTGOING, as receiver's in
     stream is reset here.
  2. In sctp_process_strreset_outreq(), move up SCTP_STRRESET_ERR_WRONG_SSN
     check, as the reset has to succeed after reconf_timer stops for the
     in stream reset request retransmission.
  3. In sctp_process_strreset_inreq(), no event should be sent, as no in
     or out stream is reset here.
  4. In sctp_process_strreset_resp(), SCTP_STREAM_RESET_INCOMING_SSN or
     OUTGOING event should always be sent for stream reset requests, no
     matter it fails or succeeds to process the request.

Fixes: 81054476 ("sctp: implement receiver-side procedures for the Outgoing SSN Reset Request Parameter")
Fixes: 16e1a919 ("sctp: implement receiver-side procedures for the Incoming SSN Reset Request Parameter")
Fixes: 11ae76e6 ("sctp: implement receiver-side procedures for the Reconf Response Parameter")
Reported-by: default avatarYing Xu <yinxu@redhat.com>
Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d71b5753
...@@ -585,9 +585,9 @@ struct sctp_chunk *sctp_process_strreset_outreq( ...@@ -585,9 +585,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
struct sctp_strreset_outreq *outreq = param.v; struct sctp_strreset_outreq *outreq = param.v;
struct sctp_stream *stream = &asoc->stream; struct sctp_stream *stream = &asoc->stream;
__u32 result = SCTP_STRRESET_DENIED; __u32 result = SCTP_STRRESET_DENIED;
__u16 i, nums, flags = 0;
__be16 *str_p = NULL; __be16 *str_p = NULL;
__u32 request_seq; __u32 request_seq;
__u16 i, nums;
request_seq = ntohl(outreq->request_seq); request_seq = ntohl(outreq->request_seq);
...@@ -615,6 +615,15 @@ struct sctp_chunk *sctp_process_strreset_outreq( ...@@ -615,6 +615,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
goto out; goto out;
nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
str_p = outreq->list_of_streams;
for (i = 0; i < nums; i++) {
if (ntohs(str_p[i]) >= stream->incnt) {
result = SCTP_STRRESET_ERR_WRONG_SSN;
goto out;
}
}
if (asoc->strreset_chunk) { if (asoc->strreset_chunk) {
if (!sctp_chunk_lookup_strreset_param( if (!sctp_chunk_lookup_strreset_param(
asoc, outreq->response_seq, asoc, outreq->response_seq,
...@@ -637,32 +646,19 @@ struct sctp_chunk *sctp_process_strreset_outreq( ...@@ -637,32 +646,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
sctp_chunk_put(asoc->strreset_chunk); sctp_chunk_put(asoc->strreset_chunk);
asoc->strreset_chunk = NULL; asoc->strreset_chunk = NULL;
} }
flags = SCTP_STREAM_RESET_INCOMING_SSN;
} }
nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16); if (nums)
if (nums) {
str_p = outreq->list_of_streams;
for (i = 0; i < nums; i++) {
if (ntohs(str_p[i]) >= stream->incnt) {
result = SCTP_STRRESET_ERR_WRONG_SSN;
goto out;
}
}
for (i = 0; i < nums; i++) for (i = 0; i < nums; i++)
SCTP_SI(stream, ntohs(str_p[i]))->mid = 0; SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
} else { else
for (i = 0; i < stream->incnt; i++) for (i = 0; i < stream->incnt; i++)
SCTP_SI(stream, i)->mid = 0; SCTP_SI(stream, i)->mid = 0;
}
result = SCTP_STRRESET_PERFORMED; result = SCTP_STRRESET_PERFORMED;
*evp = sctp_ulpevent_make_stream_reset_event(asoc, *evp = sctp_ulpevent_make_stream_reset_event(asoc,
flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p, SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
GFP_ATOMIC);
out: out:
sctp_update_strreset_result(asoc, result); sctp_update_strreset_result(asoc, result);
...@@ -738,9 +734,6 @@ struct sctp_chunk *sctp_process_strreset_inreq( ...@@ -738,9 +734,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
result = SCTP_STRRESET_PERFORMED; result = SCTP_STRRESET_PERFORMED;
*evp = sctp_ulpevent_make_stream_reset_event(asoc,
SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
out: out:
sctp_update_strreset_result(asoc, result); sctp_update_strreset_result(asoc, result);
err: err:
...@@ -1036,10 +1029,10 @@ struct sctp_chunk *sctp_process_strreset_resp( ...@@ -1036,10 +1029,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
sout->mid_uo = 0; sout->mid_uo = 0;
} }
} }
flags = SCTP_STREAM_RESET_OUTGOING_SSN;
} }
flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
for (i = 0; i < stream->outcnt; i++) for (i = 0; i < stream->outcnt; i++)
SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN; SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
...@@ -1058,6 +1051,8 @@ struct sctp_chunk *sctp_process_strreset_resp( ...@@ -1058,6 +1051,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) / nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
sizeof(__u16); sizeof(__u16);
flags |= SCTP_STREAM_RESET_INCOMING_SSN;
*evp = sctp_ulpevent_make_stream_reset_event(asoc, flags, *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
nums, str_p, GFP_ATOMIC); nums, str_p, GFP_ATOMIC);
} else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) { } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment