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