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