Linux Audio

Check our new training course

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