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