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