Merge tag 'scmi-fix-5.5-2' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep...
[linux-2.6-microblaze.git] / net / sctp / stream.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* SCTP kernel implementation
3  * (C) Copyright IBM Corp. 2001, 2004
4  * Copyright (c) 1999-2000 Cisco, Inc.
5  * Copyright (c) 1999-2001 Motorola, Inc.
6  * Copyright (c) 2001 Intel Corp.
7  *
8  * This file is part of the SCTP kernel implementation
9  *
10  * This file contains sctp stream maniuplation primitives and helpers.
11  *
12  * Please send any bug reports or fixes you make to the
13  * email address(es):
14  *    lksctp developers <linux-sctp@vger.kernel.org>
15  *
16  * Written or modified by:
17  *    Xin Long <lucien.xin@gmail.com>
18  */
19
20 #include <linux/list.h>
21 #include <net/sctp/sctp.h>
22 #include <net/sctp/sm.h>
23 #include <net/sctp/stream_sched.h>
24
25 /* Migrates chunks from stream queues to new stream queues if needed,
26  * but not across associations. Also, removes those chunks to streams
27  * higher than the new max.
28  */
29 static void sctp_stream_outq_migrate(struct sctp_stream *stream,
30                                      struct sctp_stream *new, __u16 outcnt)
31 {
32         struct sctp_association *asoc;
33         struct sctp_chunk *ch, *temp;
34         struct sctp_outq *outq;
35         int i;
36
37         asoc = container_of(stream, struct sctp_association, stream);
38         outq = &asoc->outqueue;
39
40         list_for_each_entry_safe(ch, temp, &outq->out_chunk_list, list) {
41                 __u16 sid = sctp_chunk_stream_no(ch);
42
43                 if (sid < outcnt)
44                         continue;
45
46                 sctp_sched_dequeue_common(outq, ch);
47                 /* No need to call dequeue_done here because
48                  * the chunks are not scheduled by now.
49                  */
50
51                 /* Mark as failed send. */
52                 sctp_chunk_fail(ch, (__force __u32)SCTP_ERROR_INV_STRM);
53                 if (asoc->peer.prsctp_capable &&
54                     SCTP_PR_PRIO_ENABLED(ch->sinfo.sinfo_flags))
55                         asoc->sent_cnt_removable--;
56
57                 sctp_chunk_free(ch);
58         }
59
60         if (new) {
61                 /* Here we actually move the old ext stuff into the new
62                  * buffer, because we want to keep it. Then
63                  * sctp_stream_update will swap ->out pointers.
64                  */
65                 for (i = 0; i < outcnt; i++) {
66                         kfree(SCTP_SO(new, i)->ext);
67                         SCTP_SO(new, i)->ext = SCTP_SO(stream, i)->ext;
68                         SCTP_SO(stream, i)->ext = NULL;
69                 }
70         }
71
72         for (i = outcnt; i < stream->outcnt; i++) {
73                 kfree(SCTP_SO(stream, i)->ext);
74                 SCTP_SO(stream, i)->ext = NULL;
75         }
76 }
77
78 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
79                                  gfp_t gfp)
80 {
81         int ret;
82
83         if (outcnt <= stream->outcnt)
84                 return 0;
85
86         ret = genradix_prealloc(&stream->out, outcnt, gfp);
87         if (ret)
88                 return ret;
89
90         stream->outcnt = outcnt;
91         return 0;
92 }
93
94 static int sctp_stream_alloc_in(struct sctp_stream *stream, __u16 incnt,
95                                 gfp_t gfp)
96 {
97         int ret;
98
99         if (incnt <= stream->incnt)
100                 return 0;
101
102         ret = genradix_prealloc(&stream->in, incnt, gfp);
103         if (ret)
104                 return ret;
105
106         stream->incnt = incnt;
107         return 0;
108 }
109
110 int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
111                      gfp_t gfp)
112 {
113         struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
114         int i, ret = 0;
115
116         gfp |= __GFP_NOWARN;
117
118         /* Initial stream->out size may be very big, so free it and alloc
119          * a new one with new outcnt to save memory if needed.
120          */
121         if (outcnt == stream->outcnt)
122                 goto in;
123
124         /* Filter out chunks queued on streams that won't exist anymore */
125         sched->unsched_all(stream);
126         sctp_stream_outq_migrate(stream, NULL, outcnt);
127         sched->sched_all(stream);
128
129         ret = sctp_stream_alloc_out(stream, outcnt, gfp);
130         if (ret)
131                 goto out;
132
133         for (i = 0; i < stream->outcnt; i++)
134                 SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
135
136 in:
137         sctp_stream_interleave_init(stream);
138         if (!incnt)
139                 goto out;
140
141         ret = sctp_stream_alloc_in(stream, incnt, gfp);
142         if (ret) {
143                 sched->free(stream);
144                 genradix_free(&stream->out);
145                 stream->outcnt = 0;
146                 goto out;
147         }
148
149 out:
150         return ret;
151 }
152
153 int sctp_stream_init_ext(struct sctp_stream *stream, __u16 sid)
154 {
155         struct sctp_stream_out_ext *soute;
156         int ret;
157
158         soute = kzalloc(sizeof(*soute), GFP_KERNEL);
159         if (!soute)
160                 return -ENOMEM;
161         SCTP_SO(stream, sid)->ext = soute;
162
163         ret = sctp_sched_init_sid(stream, sid, GFP_KERNEL);
164         if (ret) {
165                 kfree(SCTP_SO(stream, sid)->ext);
166                 SCTP_SO(stream, sid)->ext = NULL;
167         }
168
169         return ret;
170 }
171
172 void sctp_stream_free(struct sctp_stream *stream)
173 {
174         struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
175         int i;
176
177         sched->free(stream);
178         for (i = 0; i < stream->outcnt; i++)
179                 kfree(SCTP_SO(stream, i)->ext);
180         genradix_free(&stream->out);
181         genradix_free(&stream->in);
182 }
183
184 void sctp_stream_clear(struct sctp_stream *stream)
185 {
186         int i;
187
188         for (i = 0; i < stream->outcnt; i++) {
189                 SCTP_SO(stream, i)->mid = 0;
190                 SCTP_SO(stream, i)->mid_uo = 0;
191         }
192
193         for (i = 0; i < stream->incnt; i++)
194                 SCTP_SI(stream, i)->mid = 0;
195 }
196
197 void sctp_stream_update(struct sctp_stream *stream, struct sctp_stream *new)
198 {
199         struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
200
201         sched->unsched_all(stream);
202         sctp_stream_outq_migrate(stream, new, new->outcnt);
203         sctp_stream_free(stream);
204
205         stream->out = new->out;
206         stream->in  = new->in;
207         stream->outcnt = new->outcnt;
208         stream->incnt  = new->incnt;
209
210         sched->sched_all(stream);
211
212         new->out.tree.root = NULL;
213         new->in.tree.root  = NULL;
214         new->outcnt = 0;
215         new->incnt  = 0;
216 }
217
218 static int sctp_send_reconf(struct sctp_association *asoc,
219                             struct sctp_chunk *chunk)
220 {
221         struct net *net = sock_net(asoc->base.sk);
222         int retval = 0;
223
224         retval = sctp_primitive_RECONF(net, asoc, chunk);
225         if (retval)
226                 sctp_chunk_free(chunk);
227
228         return retval;
229 }
230
231 static bool sctp_stream_outq_is_empty(struct sctp_stream *stream,
232                                       __u16 str_nums, __be16 *str_list)
233 {
234         struct sctp_association *asoc;
235         __u16 i;
236
237         asoc = container_of(stream, struct sctp_association, stream);
238         if (!asoc->outqueue.out_qlen)
239                 return true;
240
241         if (!str_nums)
242                 return false;
243
244         for (i = 0; i < str_nums; i++) {
245                 __u16 sid = ntohs(str_list[i]);
246
247                 if (SCTP_SO(stream, sid)->ext &&
248                     !list_empty(&SCTP_SO(stream, sid)->ext->outq))
249                         return false;
250         }
251
252         return true;
253 }
254
255 int sctp_send_reset_streams(struct sctp_association *asoc,
256                             struct sctp_reset_streams *params)
257 {
258         struct sctp_stream *stream = &asoc->stream;
259         __u16 i, str_nums, *str_list;
260         struct sctp_chunk *chunk;
261         int retval = -EINVAL;
262         __be16 *nstr_list;
263         bool out, in;
264
265         if (!asoc->peer.reconf_capable ||
266             !(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ)) {
267                 retval = -ENOPROTOOPT;
268                 goto out;
269         }
270
271         if (asoc->strreset_outstanding) {
272                 retval = -EINPROGRESS;
273                 goto out;
274         }
275
276         out = params->srs_flags & SCTP_STREAM_RESET_OUTGOING;
277         in  = params->srs_flags & SCTP_STREAM_RESET_INCOMING;
278         if (!out && !in)
279                 goto out;
280
281         str_nums = params->srs_number_streams;
282         str_list = params->srs_stream_list;
283         if (str_nums) {
284                 int param_len = 0;
285
286                 if (out) {
287                         for (i = 0; i < str_nums; i++)
288                                 if (str_list[i] >= stream->outcnt)
289                                         goto out;
290
291                         param_len = str_nums * sizeof(__u16) +
292                                     sizeof(struct sctp_strreset_outreq);
293                 }
294
295                 if (in) {
296                         for (i = 0; i < str_nums; i++)
297                                 if (str_list[i] >= stream->incnt)
298                                         goto out;
299
300                         param_len += str_nums * sizeof(__u16) +
301                                      sizeof(struct sctp_strreset_inreq);
302                 }
303
304                 if (param_len > SCTP_MAX_CHUNK_LEN -
305                                 sizeof(struct sctp_reconf_chunk))
306                         goto out;
307         }
308
309         nstr_list = kcalloc(str_nums, sizeof(__be16), GFP_KERNEL);
310         if (!nstr_list) {
311                 retval = -ENOMEM;
312                 goto out;
313         }
314
315         for (i = 0; i < str_nums; i++)
316                 nstr_list[i] = htons(str_list[i]);
317
318         if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) {
319                 kfree(nstr_list);
320                 retval = -EAGAIN;
321                 goto out;
322         }
323
324         chunk = sctp_make_strreset_req(asoc, str_nums, nstr_list, out, in);
325
326         kfree(nstr_list);
327
328         if (!chunk) {
329                 retval = -ENOMEM;
330                 goto out;
331         }
332
333         if (out) {
334                 if (str_nums)
335                         for (i = 0; i < str_nums; i++)
336                                 SCTP_SO(stream, str_list[i])->state =
337                                                        SCTP_STREAM_CLOSED;
338                 else
339                         for (i = 0; i < stream->outcnt; i++)
340                                 SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
341         }
342
343         asoc->strreset_chunk = chunk;
344         sctp_chunk_hold(asoc->strreset_chunk);
345
346         retval = sctp_send_reconf(asoc, chunk);
347         if (retval) {
348                 sctp_chunk_put(asoc->strreset_chunk);
349                 asoc->strreset_chunk = NULL;
350                 if (!out)
351                         goto out;
352
353                 if (str_nums)
354                         for (i = 0; i < str_nums; i++)
355                                 SCTP_SO(stream, str_list[i])->state =
356                                                        SCTP_STREAM_OPEN;
357                 else
358                         for (i = 0; i < stream->outcnt; i++)
359                                 SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
360
361                 goto out;
362         }
363
364         asoc->strreset_outstanding = out + in;
365
366 out:
367         return retval;
368 }
369
370 int sctp_send_reset_assoc(struct sctp_association *asoc)
371 {
372         struct sctp_stream *stream = &asoc->stream;
373         struct sctp_chunk *chunk = NULL;
374         int retval;
375         __u16 i;
376
377         if (!asoc->peer.reconf_capable ||
378             !(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
379                 return -ENOPROTOOPT;
380
381         if (asoc->strreset_outstanding)
382                 return -EINPROGRESS;
383
384         if (!sctp_outq_is_empty(&asoc->outqueue))
385                 return -EAGAIN;
386
387         chunk = sctp_make_strreset_tsnreq(asoc);
388         if (!chunk)
389                 return -ENOMEM;
390
391         /* Block further xmit of data until this request is completed */
392         for (i = 0; i < stream->outcnt; i++)
393                 SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
394
395         asoc->strreset_chunk = chunk;
396         sctp_chunk_hold(asoc->strreset_chunk);
397
398         retval = sctp_send_reconf(asoc, chunk);
399         if (retval) {
400                 sctp_chunk_put(asoc->strreset_chunk);
401                 asoc->strreset_chunk = NULL;
402
403                 for (i = 0; i < stream->outcnt; i++)
404                         SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
405
406                 return retval;
407         }
408
409         asoc->strreset_outstanding = 1;
410
411         return 0;
412 }
413
414 int sctp_send_add_streams(struct sctp_association *asoc,
415                           struct sctp_add_streams *params)
416 {
417         struct sctp_stream *stream = &asoc->stream;
418         struct sctp_chunk *chunk = NULL;
419         int retval;
420         __u32 outcnt, incnt;
421         __u16 out, in;
422
423         if (!asoc->peer.reconf_capable ||
424             !(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ)) {
425                 retval = -ENOPROTOOPT;
426                 goto out;
427         }
428
429         if (asoc->strreset_outstanding) {
430                 retval = -EINPROGRESS;
431                 goto out;
432         }
433
434         out = params->sas_outstrms;
435         in  = params->sas_instrms;
436         outcnt = stream->outcnt + out;
437         incnt = stream->incnt + in;
438         if (outcnt > SCTP_MAX_STREAM || incnt > SCTP_MAX_STREAM ||
439             (!out && !in)) {
440                 retval = -EINVAL;
441                 goto out;
442         }
443
444         if (out) {
445                 retval = sctp_stream_alloc_out(stream, outcnt, GFP_KERNEL);
446                 if (retval)
447                         goto out;
448         }
449
450         chunk = sctp_make_strreset_addstrm(asoc, out, in);
451         if (!chunk) {
452                 retval = -ENOMEM;
453                 goto out;
454         }
455
456         asoc->strreset_chunk = chunk;
457         sctp_chunk_hold(asoc->strreset_chunk);
458
459         retval = sctp_send_reconf(asoc, chunk);
460         if (retval) {
461                 sctp_chunk_put(asoc->strreset_chunk);
462                 asoc->strreset_chunk = NULL;
463                 goto out;
464         }
465
466         asoc->strreset_outstanding = !!out + !!in;
467
468 out:
469         return retval;
470 }
471
472 static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
473                         struct sctp_association *asoc, __be32 resp_seq,
474                         __be16 type)
475 {
476         struct sctp_chunk *chunk = asoc->strreset_chunk;
477         struct sctp_reconf_chunk *hdr;
478         union sctp_params param;
479
480         if (!chunk)
481                 return NULL;
482
483         hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
484         sctp_walk_params(param, hdr, params) {
485                 /* sctp_strreset_tsnreq is actually the basic structure
486                  * of all stream reconf params, so it's safe to use it
487                  * to access request_seq.
488                  */
489                 struct sctp_strreset_tsnreq *req = param.v;
490
491                 if ((!resp_seq || req->request_seq == resp_seq) &&
492                     (!type || type == req->param_hdr.type))
493                         return param.v;
494         }
495
496         return NULL;
497 }
498
499 static void sctp_update_strreset_result(struct sctp_association *asoc,
500                                         __u32 result)
501 {
502         asoc->strreset_result[1] = asoc->strreset_result[0];
503         asoc->strreset_result[0] = result;
504 }
505
506 struct sctp_chunk *sctp_process_strreset_outreq(
507                                 struct sctp_association *asoc,
508                                 union sctp_params param,
509                                 struct sctp_ulpevent **evp)
510 {
511         struct sctp_strreset_outreq *outreq = param.v;
512         struct sctp_stream *stream = &asoc->stream;
513         __u32 result = SCTP_STRRESET_DENIED;
514         __be16 *str_p = NULL;
515         __u32 request_seq;
516         __u16 i, nums;
517
518         request_seq = ntohl(outreq->request_seq);
519
520         if (ntohl(outreq->send_reset_at_tsn) >
521             sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map)) {
522                 result = SCTP_STRRESET_IN_PROGRESS;
523                 goto err;
524         }
525
526         if (TSN_lt(asoc->strreset_inseq, request_seq) ||
527             TSN_lt(request_seq, asoc->strreset_inseq - 2)) {
528                 result = SCTP_STRRESET_ERR_BAD_SEQNO;
529                 goto err;
530         } else if (TSN_lt(request_seq, asoc->strreset_inseq)) {
531                 i = asoc->strreset_inseq - request_seq - 1;
532                 result = asoc->strreset_result[i];
533                 goto err;
534         }
535         asoc->strreset_inseq++;
536
537         /* Check strreset_enable after inseq inc, as sender cannot tell
538          * the peer doesn't enable strreset after receiving response with
539          * result denied, as well as to keep consistent with bsd.
540          */
541         if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
542                 goto out;
543
544         nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
545         str_p = outreq->list_of_streams;
546         for (i = 0; i < nums; i++) {
547                 if (ntohs(str_p[i]) >= stream->incnt) {
548                         result = SCTP_STRRESET_ERR_WRONG_SSN;
549                         goto out;
550                 }
551         }
552
553         if (asoc->strreset_chunk) {
554                 if (!sctp_chunk_lookup_strreset_param(
555                                 asoc, outreq->response_seq,
556                                 SCTP_PARAM_RESET_IN_REQUEST)) {
557                         /* same process with outstanding isn't 0 */
558                         result = SCTP_STRRESET_ERR_IN_PROGRESS;
559                         goto out;
560                 }
561
562                 asoc->strreset_outstanding--;
563                 asoc->strreset_outseq++;
564
565                 if (!asoc->strreset_outstanding) {
566                         struct sctp_transport *t;
567
568                         t = asoc->strreset_chunk->transport;
569                         if (del_timer(&t->reconf_timer))
570                                 sctp_transport_put(t);
571
572                         sctp_chunk_put(asoc->strreset_chunk);
573                         asoc->strreset_chunk = NULL;
574                 }
575         }
576
577         if (nums)
578                 for (i = 0; i < nums; i++)
579                         SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
580         else
581                 for (i = 0; i < stream->incnt; i++)
582                         SCTP_SI(stream, i)->mid = 0;
583
584         result = SCTP_STRRESET_PERFORMED;
585
586         *evp = sctp_ulpevent_make_stream_reset_event(asoc,
587                 SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
588
589 out:
590         sctp_update_strreset_result(asoc, result);
591 err:
592         return sctp_make_strreset_resp(asoc, result, request_seq);
593 }
594
595 struct sctp_chunk *sctp_process_strreset_inreq(
596                                 struct sctp_association *asoc,
597                                 union sctp_params param,
598                                 struct sctp_ulpevent **evp)
599 {
600         struct sctp_strreset_inreq *inreq = param.v;
601         struct sctp_stream *stream = &asoc->stream;
602         __u32 result = SCTP_STRRESET_DENIED;
603         struct sctp_chunk *chunk = NULL;
604         __u32 request_seq;
605         __u16 i, nums;
606         __be16 *str_p;
607
608         request_seq = ntohl(inreq->request_seq);
609         if (TSN_lt(asoc->strreset_inseq, request_seq) ||
610             TSN_lt(request_seq, asoc->strreset_inseq - 2)) {
611                 result = SCTP_STRRESET_ERR_BAD_SEQNO;
612                 goto err;
613         } else if (TSN_lt(request_seq, asoc->strreset_inseq)) {
614                 i = asoc->strreset_inseq - request_seq - 1;
615                 result = asoc->strreset_result[i];
616                 if (result == SCTP_STRRESET_PERFORMED)
617                         return NULL;
618                 goto err;
619         }
620         asoc->strreset_inseq++;
621
622         if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
623                 goto out;
624
625         if (asoc->strreset_outstanding) {
626                 result = SCTP_STRRESET_ERR_IN_PROGRESS;
627                 goto out;
628         }
629
630         nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16);
631         str_p = inreq->list_of_streams;
632         for (i = 0; i < nums; i++) {
633                 if (ntohs(str_p[i]) >= stream->outcnt) {
634                         result = SCTP_STRRESET_ERR_WRONG_SSN;
635                         goto out;
636                 }
637         }
638
639         if (!sctp_stream_outq_is_empty(stream, nums, str_p)) {
640                 result = SCTP_STRRESET_IN_PROGRESS;
641                 asoc->strreset_inseq--;
642                 goto err;
643         }
644
645         chunk = sctp_make_strreset_req(asoc, nums, str_p, 1, 0);
646         if (!chunk)
647                 goto out;
648
649         if (nums)
650                 for (i = 0; i < nums; i++)
651                         SCTP_SO(stream, ntohs(str_p[i]))->state =
652                                                SCTP_STREAM_CLOSED;
653         else
654                 for (i = 0; i < stream->outcnt; i++)
655                         SCTP_SO(stream, i)->state = SCTP_STREAM_CLOSED;
656
657         asoc->strreset_chunk = chunk;
658         asoc->strreset_outstanding = 1;
659         sctp_chunk_hold(asoc->strreset_chunk);
660
661         result = SCTP_STRRESET_PERFORMED;
662
663 out:
664         sctp_update_strreset_result(asoc, result);
665 err:
666         if (!chunk)
667                 chunk =  sctp_make_strreset_resp(asoc, result, request_seq);
668
669         return chunk;
670 }
671
672 struct sctp_chunk *sctp_process_strreset_tsnreq(
673                                 struct sctp_association *asoc,
674                                 union sctp_params param,
675                                 struct sctp_ulpevent **evp)
676 {
677         __u32 init_tsn = 0, next_tsn = 0, max_tsn_seen;
678         struct sctp_strreset_tsnreq *tsnreq = param.v;
679         struct sctp_stream *stream = &asoc->stream;
680         __u32 result = SCTP_STRRESET_DENIED;
681         __u32 request_seq;
682         __u16 i;
683
684         request_seq = ntohl(tsnreq->request_seq);
685         if (TSN_lt(asoc->strreset_inseq, request_seq) ||
686             TSN_lt(request_seq, asoc->strreset_inseq - 2)) {
687                 result = SCTP_STRRESET_ERR_BAD_SEQNO;
688                 goto err;
689         } else if (TSN_lt(request_seq, asoc->strreset_inseq)) {
690                 i = asoc->strreset_inseq - request_seq - 1;
691                 result = asoc->strreset_result[i];
692                 if (result == SCTP_STRRESET_PERFORMED) {
693                         next_tsn = asoc->ctsn_ack_point + 1;
694                         init_tsn =
695                                 sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1;
696                 }
697                 goto err;
698         }
699
700         if (!sctp_outq_is_empty(&asoc->outqueue)) {
701                 result = SCTP_STRRESET_IN_PROGRESS;
702                 goto err;
703         }
704
705         asoc->strreset_inseq++;
706
707         if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_ASSOC_REQ))
708                 goto out;
709
710         if (asoc->strreset_outstanding) {
711                 result = SCTP_STRRESET_ERR_IN_PROGRESS;
712                 goto out;
713         }
714
715         /* G4: The same processing as though a FWD-TSN chunk (as defined in
716          *     [RFC3758]) with all streams affected and a new cumulative TSN
717          *     ACK of the Receiver's Next TSN minus 1 were received MUST be
718          *     performed.
719          */
720         max_tsn_seen = sctp_tsnmap_get_max_tsn_seen(&asoc->peer.tsn_map);
721         asoc->stream.si->report_ftsn(&asoc->ulpq, max_tsn_seen);
722
723         /* G1: Compute an appropriate value for the Receiver's Next TSN -- the
724          *     TSN that the peer should use to send the next DATA chunk.  The
725          *     value SHOULD be the smallest TSN not acknowledged by the
726          *     receiver of the request plus 2^31.
727          */
728         init_tsn = sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + (1 << 31);
729         sctp_tsnmap_init(&asoc->peer.tsn_map, SCTP_TSN_MAP_INITIAL,
730                          init_tsn, GFP_ATOMIC);
731
732         /* G3: The same processing as though a SACK chunk with no gap report
733          *     and a cumulative TSN ACK of the Sender's Next TSN minus 1 were
734          *     received MUST be performed.
735          */
736         sctp_outq_free(&asoc->outqueue);
737
738         /* G2: Compute an appropriate value for the local endpoint's next TSN,
739          *     i.e., the next TSN assigned by the receiver of the SSN/TSN reset
740          *     chunk.  The value SHOULD be the highest TSN sent by the receiver
741          *     of the request plus 1.
742          */
743         next_tsn = asoc->next_tsn;
744         asoc->ctsn_ack_point = next_tsn - 1;
745         asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
746
747         /* G5:  The next expected and outgoing SSNs MUST be reset to 0 for all
748          *      incoming and outgoing streams.
749          */
750         for (i = 0; i < stream->outcnt; i++) {
751                 SCTP_SO(stream, i)->mid = 0;
752                 SCTP_SO(stream, i)->mid_uo = 0;
753         }
754         for (i = 0; i < stream->incnt; i++)
755                 SCTP_SI(stream, i)->mid = 0;
756
757         result = SCTP_STRRESET_PERFORMED;
758
759         *evp = sctp_ulpevent_make_assoc_reset_event(asoc, 0, init_tsn,
760                                                     next_tsn, GFP_ATOMIC);
761
762 out:
763         sctp_update_strreset_result(asoc, result);
764 err:
765         return sctp_make_strreset_tsnresp(asoc, result, request_seq,
766                                           next_tsn, init_tsn);
767 }
768
769 struct sctp_chunk *sctp_process_strreset_addstrm_out(
770                                 struct sctp_association *asoc,
771                                 union sctp_params param,
772                                 struct sctp_ulpevent **evp)
773 {
774         struct sctp_strreset_addstrm *addstrm = param.v;
775         struct sctp_stream *stream = &asoc->stream;
776         __u32 result = SCTP_STRRESET_DENIED;
777         __u32 request_seq, incnt;
778         __u16 in, i;
779
780         request_seq = ntohl(addstrm->request_seq);
781         if (TSN_lt(asoc->strreset_inseq, request_seq) ||
782             TSN_lt(request_seq, asoc->strreset_inseq - 2)) {
783                 result = SCTP_STRRESET_ERR_BAD_SEQNO;
784                 goto err;
785         } else if (TSN_lt(request_seq, asoc->strreset_inseq)) {
786                 i = asoc->strreset_inseq - request_seq - 1;
787                 result = asoc->strreset_result[i];
788                 goto err;
789         }
790         asoc->strreset_inseq++;
791
792         if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
793                 goto out;
794
795         in = ntohs(addstrm->number_of_streams);
796         incnt = stream->incnt + in;
797         if (!in || incnt > SCTP_MAX_STREAM)
798                 goto out;
799
800         if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
801                 goto out;
802
803         if (asoc->strreset_chunk) {
804                 if (!sctp_chunk_lookup_strreset_param(
805                         asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
806                         /* same process with outstanding isn't 0 */
807                         result = SCTP_STRRESET_ERR_IN_PROGRESS;
808                         goto out;
809                 }
810
811                 asoc->strreset_outstanding--;
812                 asoc->strreset_outseq++;
813
814                 if (!asoc->strreset_outstanding) {
815                         struct sctp_transport *t;
816
817                         t = asoc->strreset_chunk->transport;
818                         if (del_timer(&t->reconf_timer))
819                                 sctp_transport_put(t);
820
821                         sctp_chunk_put(asoc->strreset_chunk);
822                         asoc->strreset_chunk = NULL;
823                 }
824         }
825
826         stream->incnt = incnt;
827
828         result = SCTP_STRRESET_PERFORMED;
829
830         *evp = sctp_ulpevent_make_stream_change_event(asoc,
831                 0, ntohs(addstrm->number_of_streams), 0, GFP_ATOMIC);
832
833 out:
834         sctp_update_strreset_result(asoc, result);
835 err:
836         return sctp_make_strreset_resp(asoc, result, request_seq);
837 }
838
839 struct sctp_chunk *sctp_process_strreset_addstrm_in(
840                                 struct sctp_association *asoc,
841                                 union sctp_params param,
842                                 struct sctp_ulpevent **evp)
843 {
844         struct sctp_strreset_addstrm *addstrm = param.v;
845         struct sctp_stream *stream = &asoc->stream;
846         __u32 result = SCTP_STRRESET_DENIED;
847         struct sctp_chunk *chunk = NULL;
848         __u32 request_seq, outcnt;
849         __u16 out, i;
850         int ret;
851
852         request_seq = ntohl(addstrm->request_seq);
853         if (TSN_lt(asoc->strreset_inseq, request_seq) ||
854             TSN_lt(request_seq, asoc->strreset_inseq - 2)) {
855                 result = SCTP_STRRESET_ERR_BAD_SEQNO;
856                 goto err;
857         } else if (TSN_lt(request_seq, asoc->strreset_inseq)) {
858                 i = asoc->strreset_inseq - request_seq - 1;
859                 result = asoc->strreset_result[i];
860                 if (result == SCTP_STRRESET_PERFORMED)
861                         return NULL;
862                 goto err;
863         }
864         asoc->strreset_inseq++;
865
866         if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
867                 goto out;
868
869         if (asoc->strreset_outstanding) {
870                 result = SCTP_STRRESET_ERR_IN_PROGRESS;
871                 goto out;
872         }
873
874         out = ntohs(addstrm->number_of_streams);
875         outcnt = stream->outcnt + out;
876         if (!out || outcnt > SCTP_MAX_STREAM)
877                 goto out;
878
879         ret = sctp_stream_alloc_out(stream, outcnt, GFP_ATOMIC);
880         if (ret)
881                 goto out;
882
883         chunk = sctp_make_strreset_addstrm(asoc, out, 0);
884         if (!chunk)
885                 goto out;
886
887         asoc->strreset_chunk = chunk;
888         asoc->strreset_outstanding = 1;
889         sctp_chunk_hold(asoc->strreset_chunk);
890
891         stream->outcnt = outcnt;
892
893         result = SCTP_STRRESET_PERFORMED;
894
895 out:
896         sctp_update_strreset_result(asoc, result);
897 err:
898         if (!chunk)
899                 chunk = sctp_make_strreset_resp(asoc, result, request_seq);
900
901         return chunk;
902 }
903
904 struct sctp_chunk *sctp_process_strreset_resp(
905                                 struct sctp_association *asoc,
906                                 union sctp_params param,
907                                 struct sctp_ulpevent **evp)
908 {
909         struct sctp_stream *stream = &asoc->stream;
910         struct sctp_strreset_resp *resp = param.v;
911         struct sctp_transport *t;
912         __u16 i, nums, flags = 0;
913         struct sctp_paramhdr *req;
914         __u32 result;
915
916         req = sctp_chunk_lookup_strreset_param(asoc, resp->response_seq, 0);
917         if (!req)
918                 return NULL;
919
920         result = ntohl(resp->result);
921         if (result != SCTP_STRRESET_PERFORMED) {
922                 /* if in progress, do nothing but retransmit */
923                 if (result == SCTP_STRRESET_IN_PROGRESS)
924                         return NULL;
925                 else if (result == SCTP_STRRESET_DENIED)
926                         flags = SCTP_STREAM_RESET_DENIED;
927                 else
928                         flags = SCTP_STREAM_RESET_FAILED;
929         }
930
931         if (req->type == SCTP_PARAM_RESET_OUT_REQUEST) {
932                 struct sctp_strreset_outreq *outreq;
933                 __be16 *str_p;
934
935                 outreq = (struct sctp_strreset_outreq *)req;
936                 str_p = outreq->list_of_streams;
937                 nums = (ntohs(outreq->param_hdr.length) - sizeof(*outreq)) /
938                        sizeof(__u16);
939
940                 if (result == SCTP_STRRESET_PERFORMED) {
941                         struct sctp_stream_out *sout;
942                         if (nums) {
943                                 for (i = 0; i < nums; i++) {
944                                         sout = SCTP_SO(stream, ntohs(str_p[i]));
945                                         sout->mid = 0;
946                                         sout->mid_uo = 0;
947                                 }
948                         } else {
949                                 for (i = 0; i < stream->outcnt; i++) {
950                                         sout = SCTP_SO(stream, i);
951                                         sout->mid = 0;
952                                         sout->mid_uo = 0;
953                                 }
954                         }
955                 }
956
957                 flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
958
959                 for (i = 0; i < stream->outcnt; i++)
960                         SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
961
962                 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
963                         nums, str_p, GFP_ATOMIC);
964         } else if (req->type == SCTP_PARAM_RESET_IN_REQUEST) {
965                 struct sctp_strreset_inreq *inreq;
966                 __be16 *str_p;
967
968                 /* if the result is performed, it's impossible for inreq */
969                 if (result == SCTP_STRRESET_PERFORMED)
970                         return NULL;
971
972                 inreq = (struct sctp_strreset_inreq *)req;
973                 str_p = inreq->list_of_streams;
974                 nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
975                        sizeof(__u16);
976
977                 flags |= SCTP_STREAM_RESET_INCOMING_SSN;
978
979                 *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
980                         nums, str_p, GFP_ATOMIC);
981         } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
982                 struct sctp_strreset_resptsn *resptsn;
983                 __u32 stsn, rtsn;
984
985                 /* check for resptsn, as sctp_verify_reconf didn't do it*/
986                 if (ntohs(param.p->length) != sizeof(*resptsn))
987                         return NULL;
988
989                 resptsn = (struct sctp_strreset_resptsn *)resp;
990                 stsn = ntohl(resptsn->senders_next_tsn);
991                 rtsn = ntohl(resptsn->receivers_next_tsn);
992
993                 if (result == SCTP_STRRESET_PERFORMED) {
994                         __u32 mtsn = sctp_tsnmap_get_max_tsn_seen(
995                                                 &asoc->peer.tsn_map);
996                         LIST_HEAD(temp);
997
998                         asoc->stream.si->report_ftsn(&asoc->ulpq, mtsn);
999
1000                         sctp_tsnmap_init(&asoc->peer.tsn_map,
1001                                          SCTP_TSN_MAP_INITIAL,
1002                                          stsn, GFP_ATOMIC);
1003
1004                         /* Clean up sacked and abandoned queues only. As the
1005                          * out_chunk_list may not be empty, splice it to temp,
1006                          * then get it back after sctp_outq_free is done.
1007                          */
1008                         list_splice_init(&asoc->outqueue.out_chunk_list, &temp);
1009                         sctp_outq_free(&asoc->outqueue);
1010                         list_splice_init(&temp, &asoc->outqueue.out_chunk_list);
1011
1012                         asoc->next_tsn = rtsn;
1013                         asoc->ctsn_ack_point = asoc->next_tsn - 1;
1014                         asoc->adv_peer_ack_point = asoc->ctsn_ack_point;
1015
1016                         for (i = 0; i < stream->outcnt; i++) {
1017                                 SCTP_SO(stream, i)->mid = 0;
1018                                 SCTP_SO(stream, i)->mid_uo = 0;
1019                         }
1020                         for (i = 0; i < stream->incnt; i++)
1021                                 SCTP_SI(stream, i)->mid = 0;
1022                 }
1023
1024                 for (i = 0; i < stream->outcnt; i++)
1025                         SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
1026
1027                 *evp = sctp_ulpevent_make_assoc_reset_event(asoc, flags,
1028                         stsn, rtsn, GFP_ATOMIC);
1029         } else if (req->type == SCTP_PARAM_RESET_ADD_OUT_STREAMS) {
1030                 struct sctp_strreset_addstrm *addstrm;
1031                 __u16 number;
1032
1033                 addstrm = (struct sctp_strreset_addstrm *)req;
1034                 nums = ntohs(addstrm->number_of_streams);
1035                 number = stream->outcnt - nums;
1036
1037                 if (result == SCTP_STRRESET_PERFORMED)
1038                         for (i = number; i < stream->outcnt; i++)
1039                                 SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
1040                 else
1041                         stream->outcnt = number;
1042
1043                 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
1044                         0, nums, GFP_ATOMIC);
1045         } else if (req->type == SCTP_PARAM_RESET_ADD_IN_STREAMS) {
1046                 struct sctp_strreset_addstrm *addstrm;
1047
1048                 /* if the result is performed, it's impossible for addstrm in
1049                  * request.
1050                  */
1051                 if (result == SCTP_STRRESET_PERFORMED)
1052                         return NULL;
1053
1054                 addstrm = (struct sctp_strreset_addstrm *)req;
1055                 nums = ntohs(addstrm->number_of_streams);
1056
1057                 *evp = sctp_ulpevent_make_stream_change_event(asoc, flags,
1058                         nums, 0, GFP_ATOMIC);
1059         }
1060
1061         asoc->strreset_outstanding--;
1062         asoc->strreset_outseq++;
1063
1064         /* remove everything for this reconf request */
1065         if (!asoc->strreset_outstanding) {
1066                 t = asoc->strreset_chunk->transport;
1067                 if (del_timer(&t->reconf_timer))
1068                         sctp_transport_put(t);
1069
1070                 sctp_chunk_put(asoc->strreset_chunk);
1071                 asoc->strreset_chunk = NULL;
1072         }
1073
1074         return NULL;
1075 }