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