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