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