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