OSDN Git Service

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