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