Linux Audio

Check our new training course

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