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