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