Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/* SCTP kernel implementation
   3 * (C) Copyright Red Hat Inc. 2017
   4 *
   5 * This file is part of the SCTP kernel implementation
   6 *
   7 * These functions implement sctp stream message interleaving, mostly
   8 * including I-DATA and I-FORWARD-TSN chunks process.
   9 *
  10 * Please send any bug reports or fixes you make to the
  11 * email addresched(es):
  12 *    lksctp developers <linux-sctp@vger.kernel.org>
  13 *
  14 * Written or modified by:
  15 *    Xin Long <lucien.xin@gmail.com>
  16 */
  17
  18#include <net/busy_poll.h>
  19#include <net/sctp/sctp.h>
  20#include <net/sctp/sm.h>
  21#include <net/sctp/ulpevent.h>
  22#include <linux/sctp.h>
  23
  24static struct sctp_chunk *sctp_make_idatafrag_empty(
  25					const struct sctp_association *asoc,
  26					const struct sctp_sndrcvinfo *sinfo,
  27					int len, __u8 flags, gfp_t gfp)
  28{
  29	struct sctp_chunk *retval;
  30	struct sctp_idatahdr dp;
  31
  32	memset(&dp, 0, sizeof(dp));
  33	dp.stream = htons(sinfo->sinfo_stream);
  34
  35	if (sinfo->sinfo_flags & SCTP_UNORDERED)
  36		flags |= SCTP_DATA_UNORDERED;
  37
  38	retval = sctp_make_idata(asoc, flags, sizeof(dp) + len, gfp);
  39	if (!retval)
  40		return NULL;
  41
  42	retval->subh.idata_hdr = sctp_addto_chunk(retval, sizeof(dp), &dp);
  43	memcpy(&retval->sinfo, sinfo, sizeof(struct sctp_sndrcvinfo));
  44
  45	return retval;
  46}
  47
  48static void sctp_chunk_assign_mid(struct sctp_chunk *chunk)
  49{
  50	struct sctp_stream *stream;
  51	struct sctp_chunk *lchunk;
  52	__u32 cfsn = 0;
  53	__u16 sid;
  54
  55	if (chunk->has_mid)
  56		return;
  57
  58	sid = sctp_chunk_stream_no(chunk);
  59	stream = &chunk->asoc->stream;
  60
  61	list_for_each_entry(lchunk, &chunk->msg->chunks, frag_list) {
  62		struct sctp_idatahdr *hdr;
  63		__u32 mid;
  64
  65		lchunk->has_mid = 1;
  66
  67		hdr = lchunk->subh.idata_hdr;
  68
  69		if (lchunk->chunk_hdr->flags & SCTP_DATA_FIRST_FRAG)
  70			hdr->ppid = lchunk->sinfo.sinfo_ppid;
  71		else
  72			hdr->fsn = htonl(cfsn++);
  73
  74		if (lchunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
  75			mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
  76				sctp_mid_uo_next(stream, out, sid) :
  77				sctp_mid_uo_peek(stream, out, sid);
  78		} else {
  79			mid = lchunk->chunk_hdr->flags & SCTP_DATA_LAST_FRAG ?
  80				sctp_mid_next(stream, out, sid) :
  81				sctp_mid_peek(stream, out, sid);
  82		}
  83		hdr->mid = htonl(mid);
  84	}
  85}
  86
  87static bool sctp_validate_data(struct sctp_chunk *chunk)
  88{
  89	struct sctp_stream *stream;
  90	__u16 sid, ssn;
  91
  92	if (chunk->chunk_hdr->type != SCTP_CID_DATA)
  93		return false;
  94
  95	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
  96		return true;
  97
  98	stream = &chunk->asoc->stream;
  99	sid = sctp_chunk_stream_no(chunk);
 100	ssn = ntohs(chunk->subh.data_hdr->ssn);
 101
 102	return !SSN_lt(ssn, sctp_ssn_peek(stream, in, sid));
 103}
 104
 105static bool sctp_validate_idata(struct sctp_chunk *chunk)
 106{
 107	struct sctp_stream *stream;
 108	__u32 mid;
 109	__u16 sid;
 110
 111	if (chunk->chunk_hdr->type != SCTP_CID_I_DATA)
 112		return false;
 113
 114	if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
 115		return true;
 116
 117	stream = &chunk->asoc->stream;
 118	sid = sctp_chunk_stream_no(chunk);
 119	mid = ntohl(chunk->subh.idata_hdr->mid);
 120
 121	return !MID_lt(mid, sctp_mid_peek(stream, in, sid));
 122}
 123
 124static void sctp_intl_store_reasm(struct sctp_ulpq *ulpq,
 125				  struct sctp_ulpevent *event)
 126{
 127	struct sctp_ulpevent *cevent;
 128	struct sk_buff *pos, *loc;
 129
 130	pos = skb_peek_tail(&ulpq->reasm);
 131	if (!pos) {
 132		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
 133		return;
 134	}
 135
 136	cevent = sctp_skb2event(pos);
 137
 138	if (event->stream == cevent->stream &&
 139	    event->mid == cevent->mid &&
 140	    (cevent->msg_flags & SCTP_DATA_FIRST_FRAG ||
 141	     (!(event->msg_flags & SCTP_DATA_FIRST_FRAG) &&
 142	      event->fsn > cevent->fsn))) {
 143		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
 144		return;
 145	}
 146
 147	if ((event->stream == cevent->stream &&
 148	     MID_lt(cevent->mid, event->mid)) ||
 149	    event->stream > cevent->stream) {
 150		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
 151		return;
 152	}
 153
 154	loc = NULL;
 155	skb_queue_walk(&ulpq->reasm, pos) {
 156		cevent = sctp_skb2event(pos);
 157
 158		if (event->stream < cevent->stream ||
 159		    (event->stream == cevent->stream &&
 160		     MID_lt(event->mid, cevent->mid))) {
 161			loc = pos;
 162			break;
 163		}
 164		if (event->stream == cevent->stream &&
 165		    event->mid == cevent->mid &&
 166		    !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
 167		    (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
 168		     event->fsn < cevent->fsn)) {
 169			loc = pos;
 170			break;
 171		}
 172	}
 173
 174	if (!loc)
 175		__skb_queue_tail(&ulpq->reasm, sctp_event2skb(event));
 176	else
 177		__skb_queue_before(&ulpq->reasm, loc, sctp_event2skb(event));
 178}
 179
 180static struct sctp_ulpevent *sctp_intl_retrieve_partial(
 181						struct sctp_ulpq *ulpq,
 182						struct sctp_ulpevent *event)
 183{
 184	struct sk_buff *first_frag = NULL;
 185	struct sk_buff *last_frag = NULL;
 186	struct sctp_ulpevent *retval;
 187	struct sctp_stream_in *sin;
 188	struct sk_buff *pos;
 189	__u32 next_fsn = 0;
 190	int is_last = 0;
 191
 192	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 193
 194	skb_queue_walk(&ulpq->reasm, pos) {
 195		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 196
 197		if (cevent->stream < event->stream)
 198			continue;
 199
 200		if (cevent->stream > event->stream ||
 201		    cevent->mid != sin->mid)
 202			break;
 203
 204		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 205		case SCTP_DATA_FIRST_FRAG:
 206			goto out;
 207		case SCTP_DATA_MIDDLE_FRAG:
 208			if (!first_frag) {
 209				if (cevent->fsn == sin->fsn) {
 210					first_frag = pos;
 211					last_frag = pos;
 212					next_fsn = cevent->fsn + 1;
 213				}
 214			} else if (cevent->fsn == next_fsn) {
 215				last_frag = pos;
 216				next_fsn++;
 217			} else {
 218				goto out;
 219			}
 220			break;
 221		case SCTP_DATA_LAST_FRAG:
 222			if (!first_frag) {
 223				if (cevent->fsn == sin->fsn) {
 224					first_frag = pos;
 225					last_frag = pos;
 226					next_fsn = 0;
 227					is_last = 1;
 228				}
 229			} else if (cevent->fsn == next_fsn) {
 230				last_frag = pos;
 231				next_fsn = 0;
 232				is_last = 1;
 233			}
 234			goto out;
 235		default:
 236			goto out;
 237		}
 238	}
 239
 240out:
 241	if (!first_frag)
 242		return NULL;
 243
 244	retval = sctp_make_reassembled_event(ulpq->asoc->base.net, &ulpq->reasm,
 245					     first_frag, last_frag);
 246	if (retval) {
 247		sin->fsn = next_fsn;
 248		if (is_last) {
 249			retval->msg_flags |= MSG_EOR;
 250			sin->pd_mode = 0;
 251		}
 252	}
 253
 254	return retval;
 255}
 256
 257static struct sctp_ulpevent *sctp_intl_retrieve_reassembled(
 258						struct sctp_ulpq *ulpq,
 259						struct sctp_ulpevent *event)
 260{
 261	struct sctp_association *asoc = ulpq->asoc;
 262	struct sk_buff *pos, *first_frag = NULL;
 263	struct sctp_ulpevent *retval = NULL;
 264	struct sk_buff *pd_first = NULL;
 265	struct sk_buff *pd_last = NULL;
 266	struct sctp_stream_in *sin;
 267	__u32 next_fsn = 0;
 268	__u32 pd_point = 0;
 269	__u32 pd_len = 0;
 270	__u32 mid = 0;
 271
 272	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 273
 274	skb_queue_walk(&ulpq->reasm, pos) {
 275		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 276
 277		if (cevent->stream < event->stream)
 278			continue;
 279		if (cevent->stream > event->stream)
 280			break;
 281
 282		if (MID_lt(cevent->mid, event->mid))
 283			continue;
 284		if (MID_lt(event->mid, cevent->mid))
 285			break;
 286
 287		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 288		case SCTP_DATA_FIRST_FRAG:
 289			if (cevent->mid == sin->mid) {
 290				pd_first = pos;
 291				pd_last = pos;
 292				pd_len = pos->len;
 293			}
 294
 295			first_frag = pos;
 296			next_fsn = 0;
 297			mid = cevent->mid;
 298			break;
 299
 300		case SCTP_DATA_MIDDLE_FRAG:
 301			if (first_frag && cevent->mid == mid &&
 302			    cevent->fsn == next_fsn) {
 303				next_fsn++;
 304				if (pd_first) {
 305					pd_last = pos;
 306					pd_len += pos->len;
 307				}
 308			} else {
 309				first_frag = NULL;
 310			}
 311			break;
 312
 313		case SCTP_DATA_LAST_FRAG:
 314			if (first_frag && cevent->mid == mid &&
 315			    cevent->fsn == next_fsn)
 316				goto found;
 317			else
 318				first_frag = NULL;
 319			break;
 320		}
 321	}
 322
 323	if (!pd_first)
 324		goto out;
 325
 326	pd_point = sctp_sk(asoc->base.sk)->pd_point;
 327	if (pd_point && pd_point <= pd_len) {
 328		retval = sctp_make_reassembled_event(asoc->base.net,
 329						     &ulpq->reasm,
 330						     pd_first, pd_last);
 331		if (retval) {
 332			sin->fsn = next_fsn;
 333			sin->pd_mode = 1;
 334		}
 335	}
 336	goto out;
 337
 338found:
 339	retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm,
 340					     first_frag, pos);
 341	if (retval)
 342		retval->msg_flags |= MSG_EOR;
 343
 344out:
 345	return retval;
 346}
 347
 348static struct sctp_ulpevent *sctp_intl_reasm(struct sctp_ulpq *ulpq,
 349					     struct sctp_ulpevent *event)
 350{
 351	struct sctp_ulpevent *retval = NULL;
 352	struct sctp_stream_in *sin;
 353
 354	if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) {
 355		event->msg_flags |= MSG_EOR;
 356		return event;
 357	}
 358
 359	sctp_intl_store_reasm(ulpq, event);
 360
 361	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 362	if (sin->pd_mode && event->mid == sin->mid &&
 363	    event->fsn == sin->fsn)
 364		retval = sctp_intl_retrieve_partial(ulpq, event);
 365
 366	if (!retval)
 367		retval = sctp_intl_retrieve_reassembled(ulpq, event);
 368
 369	return retval;
 370}
 371
 372static void sctp_intl_store_ordered(struct sctp_ulpq *ulpq,
 373				    struct sctp_ulpevent *event)
 374{
 375	struct sctp_ulpevent *cevent;
 376	struct sk_buff *pos, *loc;
 377
 378	pos = skb_peek_tail(&ulpq->lobby);
 379	if (!pos) {
 380		__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
 381		return;
 382	}
 383
 384	cevent = (struct sctp_ulpevent *)pos->cb;
 385	if (event->stream == cevent->stream &&
 386	    MID_lt(cevent->mid, event->mid)) {
 387		__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
 388		return;
 389	}
 390
 391	if (event->stream > cevent->stream) {
 392		__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
 393		return;
 394	}
 395
 396	loc = NULL;
 397	skb_queue_walk(&ulpq->lobby, pos) {
 398		cevent = (struct sctp_ulpevent *)pos->cb;
 399
 400		if (cevent->stream > event->stream) {
 401			loc = pos;
 402			break;
 403		}
 404		if (cevent->stream == event->stream &&
 405		    MID_lt(event->mid, cevent->mid)) {
 406			loc = pos;
 407			break;
 408		}
 409	}
 410
 411	if (!loc)
 412		__skb_queue_tail(&ulpq->lobby, sctp_event2skb(event));
 413	else
 414		__skb_queue_before(&ulpq->lobby, loc, sctp_event2skb(event));
 415}
 416
 417static void sctp_intl_retrieve_ordered(struct sctp_ulpq *ulpq,
 418				       struct sctp_ulpevent *event)
 419{
 420	struct sk_buff_head *event_list;
 421	struct sctp_stream *stream;
 422	struct sk_buff *pos, *tmp;
 423	__u16 sid = event->stream;
 424
 425	stream  = &ulpq->asoc->stream;
 426	event_list = (struct sk_buff_head *)sctp_event2skb(event)->prev;
 427
 428	sctp_skb_for_each(pos, &ulpq->lobby, tmp) {
 429		struct sctp_ulpevent *cevent = (struct sctp_ulpevent *)pos->cb;
 430
 431		if (cevent->stream > sid)
 432			break;
 433
 434		if (cevent->stream < sid)
 435			continue;
 436
 437		if (cevent->mid != sctp_mid_peek(stream, in, sid))
 438			break;
 439
 440		sctp_mid_next(stream, in, sid);
 441
 442		__skb_unlink(pos, &ulpq->lobby);
 443
 444		__skb_queue_tail(event_list, pos);
 445	}
 446}
 447
 448static struct sctp_ulpevent *sctp_intl_order(struct sctp_ulpq *ulpq,
 449					     struct sctp_ulpevent *event)
 450{
 451	struct sctp_stream *stream;
 452	__u16 sid;
 453
 454	stream  = &ulpq->asoc->stream;
 455	sid = event->stream;
 456
 457	if (event->mid != sctp_mid_peek(stream, in, sid)) {
 458		sctp_intl_store_ordered(ulpq, event);
 459		return NULL;
 460	}
 461
 462	sctp_mid_next(stream, in, sid);
 463
 464	sctp_intl_retrieve_ordered(ulpq, event);
 465
 466	return event;
 467}
 468
 469static int sctp_enqueue_event(struct sctp_ulpq *ulpq,
 470			      struct sk_buff_head *skb_list)
 471{
 472	struct sock *sk = ulpq->asoc->base.sk;
 473	struct sctp_sock *sp = sctp_sk(sk);
 474	struct sctp_ulpevent *event;
 475	struct sk_buff *skb;
 476
 477	skb = __skb_peek(skb_list);
 478	event = sctp_skb2event(skb);
 479
 480	if (sk->sk_shutdown & RCV_SHUTDOWN &&
 481	    (sk->sk_shutdown & SEND_SHUTDOWN ||
 482	     !sctp_ulpevent_is_notification(event)))
 483		goto out_free;
 484
 485	if (!sctp_ulpevent_is_notification(event)) {
 486		sk_mark_napi_id(sk, skb);
 487		sk_incoming_cpu_update(sk);
 488	}
 489
 490	if (!sctp_ulpevent_is_enabled(event, ulpq->asoc->subscribe))
 491		goto out_free;
 492
 493	if (skb_list)
 494		skb_queue_splice_tail_init(skb_list,
 495					   &sk->sk_receive_queue);
 496	else
 497		__skb_queue_tail(&sk->sk_receive_queue, skb);
 498
 499	if (!sp->data_ready_signalled) {
 500		sp->data_ready_signalled = 1;
 501		sk->sk_data_ready(sk);
 502	}
 503
 504	return 1;
 505
 506out_free:
 507	if (skb_list)
 508		sctp_queue_purge_ulpevents(skb_list);
 509	else
 510		sctp_ulpevent_free(event);
 511
 512	return 0;
 513}
 514
 515static void sctp_intl_store_reasm_uo(struct sctp_ulpq *ulpq,
 516				     struct sctp_ulpevent *event)
 517{
 518	struct sctp_ulpevent *cevent;
 519	struct sk_buff *pos;
 520
 521	pos = skb_peek_tail(&ulpq->reasm_uo);
 522	if (!pos) {
 523		__skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
 524		return;
 525	}
 526
 527	cevent = sctp_skb2event(pos);
 528
 529	if (event->stream == cevent->stream &&
 530	    event->mid == cevent->mid &&
 531	    (cevent->msg_flags & SCTP_DATA_FIRST_FRAG ||
 532	     (!(event->msg_flags & SCTP_DATA_FIRST_FRAG) &&
 533	      event->fsn > cevent->fsn))) {
 534		__skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
 535		return;
 536	}
 537
 538	if ((event->stream == cevent->stream &&
 539	     MID_lt(cevent->mid, event->mid)) ||
 540	    event->stream > cevent->stream) {
 541		__skb_queue_tail(&ulpq->reasm_uo, sctp_event2skb(event));
 542		return;
 543	}
 544
 545	skb_queue_walk(&ulpq->reasm_uo, pos) {
 546		cevent = sctp_skb2event(pos);
 547
 548		if (event->stream < cevent->stream ||
 549		    (event->stream == cevent->stream &&
 550		     MID_lt(event->mid, cevent->mid)))
 551			break;
 552
 553		if (event->stream == cevent->stream &&
 554		    event->mid == cevent->mid &&
 555		    !(cevent->msg_flags & SCTP_DATA_FIRST_FRAG) &&
 556		    (event->msg_flags & SCTP_DATA_FIRST_FRAG ||
 557		     event->fsn < cevent->fsn))
 558			break;
 559	}
 560
 561	__skb_queue_before(&ulpq->reasm_uo, pos, sctp_event2skb(event));
 562}
 563
 564static struct sctp_ulpevent *sctp_intl_retrieve_partial_uo(
 565						struct sctp_ulpq *ulpq,
 566						struct sctp_ulpevent *event)
 567{
 568	struct sk_buff *first_frag = NULL;
 569	struct sk_buff *last_frag = NULL;
 570	struct sctp_ulpevent *retval;
 571	struct sctp_stream_in *sin;
 572	struct sk_buff *pos;
 573	__u32 next_fsn = 0;
 574	int is_last = 0;
 575
 576	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 577
 578	skb_queue_walk(&ulpq->reasm_uo, pos) {
 579		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 580
 581		if (cevent->stream < event->stream)
 582			continue;
 583		if (cevent->stream > event->stream)
 584			break;
 585
 586		if (MID_lt(cevent->mid, sin->mid_uo))
 587			continue;
 588		if (MID_lt(sin->mid_uo, cevent->mid))
 589			break;
 590
 591		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 592		case SCTP_DATA_FIRST_FRAG:
 593			goto out;
 594		case SCTP_DATA_MIDDLE_FRAG:
 595			if (!first_frag) {
 596				if (cevent->fsn == sin->fsn_uo) {
 597					first_frag = pos;
 598					last_frag = pos;
 599					next_fsn = cevent->fsn + 1;
 600				}
 601			} else if (cevent->fsn == next_fsn) {
 602				last_frag = pos;
 603				next_fsn++;
 604			} else {
 605				goto out;
 606			}
 607			break;
 608		case SCTP_DATA_LAST_FRAG:
 609			if (!first_frag) {
 610				if (cevent->fsn == sin->fsn_uo) {
 611					first_frag = pos;
 612					last_frag = pos;
 613					next_fsn = 0;
 614					is_last = 1;
 615				}
 616			} else if (cevent->fsn == next_fsn) {
 617				last_frag = pos;
 618				next_fsn = 0;
 619				is_last = 1;
 620			}
 621			goto out;
 622		default:
 623			goto out;
 624		}
 625	}
 626
 627out:
 628	if (!first_frag)
 629		return NULL;
 630
 631	retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
 632					     &ulpq->reasm_uo, first_frag,
 633					     last_frag);
 634	if (retval) {
 635		sin->fsn_uo = next_fsn;
 636		if (is_last) {
 637			retval->msg_flags |= MSG_EOR;
 638			sin->pd_mode_uo = 0;
 639		}
 640	}
 641
 642	return retval;
 643}
 644
 645static struct sctp_ulpevent *sctp_intl_retrieve_reassembled_uo(
 646						struct sctp_ulpq *ulpq,
 647						struct sctp_ulpevent *event)
 648{
 649	struct sctp_association *asoc = ulpq->asoc;
 650	struct sk_buff *pos, *first_frag = NULL;
 651	struct sctp_ulpevent *retval = NULL;
 652	struct sk_buff *pd_first = NULL;
 653	struct sk_buff *pd_last = NULL;
 654	struct sctp_stream_in *sin;
 655	__u32 next_fsn = 0;
 656	__u32 pd_point = 0;
 657	__u32 pd_len = 0;
 658	__u32 mid = 0;
 659
 660	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 661
 662	skb_queue_walk(&ulpq->reasm_uo, pos) {
 663		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 664
 665		if (cevent->stream < event->stream)
 666			continue;
 667		if (cevent->stream > event->stream)
 668			break;
 669
 670		if (MID_lt(cevent->mid, event->mid))
 671			continue;
 672		if (MID_lt(event->mid, cevent->mid))
 673			break;
 674
 675		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 676		case SCTP_DATA_FIRST_FRAG:
 677			if (!sin->pd_mode_uo) {
 678				sin->mid_uo = cevent->mid;
 679				pd_first = pos;
 680				pd_last = pos;
 681				pd_len = pos->len;
 682			}
 683
 684			first_frag = pos;
 685			next_fsn = 0;
 686			mid = cevent->mid;
 687			break;
 688
 689		case SCTP_DATA_MIDDLE_FRAG:
 690			if (first_frag && cevent->mid == mid &&
 691			    cevent->fsn == next_fsn) {
 692				next_fsn++;
 693				if (pd_first) {
 694					pd_last = pos;
 695					pd_len += pos->len;
 696				}
 697			} else {
 698				first_frag = NULL;
 699			}
 700			break;
 701
 702		case SCTP_DATA_LAST_FRAG:
 703			if (first_frag && cevent->mid == mid &&
 704			    cevent->fsn == next_fsn)
 705				goto found;
 706			else
 707				first_frag = NULL;
 708			break;
 709		}
 710	}
 711
 712	if (!pd_first)
 713		goto out;
 714
 715	pd_point = sctp_sk(asoc->base.sk)->pd_point;
 716	if (pd_point && pd_point <= pd_len) {
 717		retval = sctp_make_reassembled_event(asoc->base.net,
 718						     &ulpq->reasm_uo,
 719						     pd_first, pd_last);
 720		if (retval) {
 721			sin->fsn_uo = next_fsn;
 722			sin->pd_mode_uo = 1;
 723		}
 724	}
 725	goto out;
 726
 727found:
 728	retval = sctp_make_reassembled_event(asoc->base.net, &ulpq->reasm_uo,
 729					     first_frag, pos);
 730	if (retval)
 731		retval->msg_flags |= MSG_EOR;
 732
 733out:
 734	return retval;
 735}
 736
 737static struct sctp_ulpevent *sctp_intl_reasm_uo(struct sctp_ulpq *ulpq,
 738						struct sctp_ulpevent *event)
 739{
 740	struct sctp_ulpevent *retval = NULL;
 741	struct sctp_stream_in *sin;
 742
 743	if (SCTP_DATA_NOT_FRAG == (event->msg_flags & SCTP_DATA_FRAG_MASK)) {
 744		event->msg_flags |= MSG_EOR;
 745		return event;
 746	}
 747
 748	sctp_intl_store_reasm_uo(ulpq, event);
 749
 750	sin = sctp_stream_in(&ulpq->asoc->stream, event->stream);
 751	if (sin->pd_mode_uo && event->mid == sin->mid_uo &&
 752	    event->fsn == sin->fsn_uo)
 753		retval = sctp_intl_retrieve_partial_uo(ulpq, event);
 754
 755	if (!retval)
 756		retval = sctp_intl_retrieve_reassembled_uo(ulpq, event);
 757
 758	return retval;
 759}
 760
 761static struct sctp_ulpevent *sctp_intl_retrieve_first_uo(struct sctp_ulpq *ulpq)
 762{
 763	struct sctp_stream_in *csin, *sin = NULL;
 764	struct sk_buff *first_frag = NULL;
 765	struct sk_buff *last_frag = NULL;
 766	struct sctp_ulpevent *retval;
 767	struct sk_buff *pos;
 768	__u32 next_fsn = 0;
 769	__u16 sid = 0;
 770
 771	skb_queue_walk(&ulpq->reasm_uo, pos) {
 772		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 773
 774		csin = sctp_stream_in(&ulpq->asoc->stream, cevent->stream);
 775		if (csin->pd_mode_uo)
 776			continue;
 777
 778		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 779		case SCTP_DATA_FIRST_FRAG:
 780			if (first_frag)
 781				goto out;
 782			first_frag = pos;
 783			last_frag = pos;
 784			next_fsn = 0;
 785			sin = csin;
 786			sid = cevent->stream;
 787			sin->mid_uo = cevent->mid;
 788			break;
 789		case SCTP_DATA_MIDDLE_FRAG:
 790			if (!first_frag)
 791				break;
 792			if (cevent->stream == sid &&
 793			    cevent->mid == sin->mid_uo &&
 794			    cevent->fsn == next_fsn) {
 795				next_fsn++;
 796				last_frag = pos;
 797			} else {
 798				goto out;
 799			}
 800			break;
 801		case SCTP_DATA_LAST_FRAG:
 802			if (first_frag)
 803				goto out;
 804			break;
 805		default:
 806			break;
 807		}
 808	}
 809
 810	if (!first_frag)
 811		return NULL;
 812
 813out:
 814	retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
 815					     &ulpq->reasm_uo, first_frag,
 816					     last_frag);
 817	if (retval) {
 818		sin->fsn_uo = next_fsn;
 819		sin->pd_mode_uo = 1;
 820	}
 821
 822	return retval;
 823}
 824
 825static int sctp_ulpevent_idata(struct sctp_ulpq *ulpq,
 826			       struct sctp_chunk *chunk, gfp_t gfp)
 827{
 828	struct sctp_ulpevent *event;
 829	struct sk_buff_head temp;
 830	int event_eor = 0;
 831
 832	event = sctp_ulpevent_make_rcvmsg(chunk->asoc, chunk, gfp);
 833	if (!event)
 834		return -ENOMEM;
 835
 836	event->mid = ntohl(chunk->subh.idata_hdr->mid);
 837	if (event->msg_flags & SCTP_DATA_FIRST_FRAG)
 838		event->ppid = chunk->subh.idata_hdr->ppid;
 839	else
 840		event->fsn = ntohl(chunk->subh.idata_hdr->fsn);
 841
 842	if (!(event->msg_flags & SCTP_DATA_UNORDERED)) {
 843		event = sctp_intl_reasm(ulpq, event);
 844		if (event) {
 845			skb_queue_head_init(&temp);
 846			__skb_queue_tail(&temp, sctp_event2skb(event));
 847
 848			if (event->msg_flags & MSG_EOR)
 849				event = sctp_intl_order(ulpq, event);
 850		}
 851	} else {
 852		event = sctp_intl_reasm_uo(ulpq, event);
 853		if (event) {
 854			skb_queue_head_init(&temp);
 855			__skb_queue_tail(&temp, sctp_event2skb(event));
 856		}
 857	}
 858
 859	if (event) {
 860		event_eor = (event->msg_flags & MSG_EOR) ? 1 : 0;
 861		sctp_enqueue_event(ulpq, &temp);
 862	}
 863
 864	return event_eor;
 865}
 866
 867static struct sctp_ulpevent *sctp_intl_retrieve_first(struct sctp_ulpq *ulpq)
 868{
 869	struct sctp_stream_in *csin, *sin = NULL;
 870	struct sk_buff *first_frag = NULL;
 871	struct sk_buff *last_frag = NULL;
 872	struct sctp_ulpevent *retval;
 873	struct sk_buff *pos;
 874	__u32 next_fsn = 0;
 875	__u16 sid = 0;
 876
 877	skb_queue_walk(&ulpq->reasm, pos) {
 878		struct sctp_ulpevent *cevent = sctp_skb2event(pos);
 879
 880		csin = sctp_stream_in(&ulpq->asoc->stream, cevent->stream);
 881		if (csin->pd_mode)
 882			continue;
 883
 884		switch (cevent->msg_flags & SCTP_DATA_FRAG_MASK) {
 885		case SCTP_DATA_FIRST_FRAG:
 886			if (first_frag)
 887				goto out;
 888			if (cevent->mid == csin->mid) {
 889				first_frag = pos;
 890				last_frag = pos;
 891				next_fsn = 0;
 892				sin = csin;
 893				sid = cevent->stream;
 894			}
 895			break;
 896		case SCTP_DATA_MIDDLE_FRAG:
 897			if (!first_frag)
 898				break;
 899			if (cevent->stream == sid &&
 900			    cevent->mid == sin->mid &&
 901			    cevent->fsn == next_fsn) {
 902				next_fsn++;
 903				last_frag = pos;
 904			} else {
 905				goto out;
 906			}
 907			break;
 908		case SCTP_DATA_LAST_FRAG:
 909			if (first_frag)
 910				goto out;
 911			break;
 912		default:
 913			break;
 914		}
 915	}
 916
 917	if (!first_frag)
 918		return NULL;
 919
 920out:
 921	retval = sctp_make_reassembled_event(ulpq->asoc->base.net,
 922					     &ulpq->reasm, first_frag,
 923					     last_frag);
 924	if (retval) {
 925		sin->fsn = next_fsn;
 926		sin->pd_mode = 1;
 927	}
 928
 929	return retval;
 930}
 931
 932static void sctp_intl_start_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
 933{
 934	struct sctp_ulpevent *event;
 935	struct sk_buff_head temp;
 936
 937	if (!skb_queue_empty(&ulpq->reasm)) {
 938		do {
 939			event = sctp_intl_retrieve_first(ulpq);
 940			if (event) {
 941				skb_queue_head_init(&temp);
 942				__skb_queue_tail(&temp, sctp_event2skb(event));
 943				sctp_enqueue_event(ulpq, &temp);
 944			}
 945		} while (event);
 946	}
 947
 948	if (!skb_queue_empty(&ulpq->reasm_uo)) {
 949		do {
 950			event = sctp_intl_retrieve_first_uo(ulpq);
 951			if (event) {
 952				skb_queue_head_init(&temp);
 953				__skb_queue_tail(&temp, sctp_event2skb(event));
 954				sctp_enqueue_event(ulpq, &temp);
 955			}
 956		} while (event);
 957	}
 958}
 959
 960static void sctp_renege_events(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
 961			       gfp_t gfp)
 962{
 963	struct sctp_association *asoc = ulpq->asoc;
 964	__u32 freed = 0;
 965	__u16 needed;
 966
 967	needed = ntohs(chunk->chunk_hdr->length) -
 968		 sizeof(struct sctp_idata_chunk);
 969
 970	if (skb_queue_empty(&asoc->base.sk->sk_receive_queue)) {
 971		freed = sctp_ulpq_renege_list(ulpq, &ulpq->lobby, needed);
 972		if (freed < needed)
 973			freed += sctp_ulpq_renege_list(ulpq, &ulpq->reasm,
 974						       needed);
 975		if (freed < needed)
 976			freed += sctp_ulpq_renege_list(ulpq, &ulpq->reasm_uo,
 977						       needed);
 978	}
 979
 980	if (freed >= needed && sctp_ulpevent_idata(ulpq, chunk, gfp) <= 0)
 981		sctp_intl_start_pd(ulpq, gfp);
 982
 983	sk_mem_reclaim(asoc->base.sk);
 984}
 985
 986static void sctp_intl_stream_abort_pd(struct sctp_ulpq *ulpq, __u16 sid,
 987				      __u32 mid, __u16 flags, gfp_t gfp)
 988{
 989	struct sock *sk = ulpq->asoc->base.sk;
 990	struct sctp_ulpevent *ev = NULL;
 991
 992	if (!sctp_ulpevent_type_enabled(ulpq->asoc->subscribe,
 993					SCTP_PARTIAL_DELIVERY_EVENT))
 994		return;
 995
 996	ev = sctp_ulpevent_make_pdapi(ulpq->asoc, SCTP_PARTIAL_DELIVERY_ABORTED,
 997				      sid, mid, flags, gfp);
 998	if (ev) {
 999		struct sctp_sock *sp = sctp_sk(sk);
1000
1001		__skb_queue_tail(&sk->sk_receive_queue, sctp_event2skb(ev));
1002
1003		if (!sp->data_ready_signalled) {
1004			sp->data_ready_signalled = 1;
1005			sk->sk_data_ready(sk);
1006		}
1007	}
1008}
1009
1010static void sctp_intl_reap_ordered(struct sctp_ulpq *ulpq, __u16 sid)
1011{
1012	struct sctp_stream *stream = &ulpq->asoc->stream;
1013	struct sctp_ulpevent *cevent, *event = NULL;
1014	struct sk_buff_head *lobby = &ulpq->lobby;
1015	struct sk_buff *pos, *tmp;
1016	struct sk_buff_head temp;
1017	__u16 csid;
1018	__u32 cmid;
1019
1020	skb_queue_head_init(&temp);
1021	sctp_skb_for_each(pos, lobby, tmp) {
1022		cevent = (struct sctp_ulpevent *)pos->cb;
1023		csid = cevent->stream;
1024		cmid = cevent->mid;
1025
1026		if (csid > sid)
1027			break;
1028
1029		if (csid < sid)
1030			continue;
1031
1032		if (!MID_lt(cmid, sctp_mid_peek(stream, in, csid)))
1033			break;
1034
1035		__skb_unlink(pos, lobby);
1036		if (!event)
1037			event = sctp_skb2event(pos);
1038
1039		__skb_queue_tail(&temp, pos);
1040	}
1041
1042	if (!event && pos != (struct sk_buff *)lobby) {
1043		cevent = (struct sctp_ulpevent *)pos->cb;
1044		csid = cevent->stream;
1045		cmid = cevent->mid;
1046
1047		if (csid == sid && cmid == sctp_mid_peek(stream, in, csid)) {
1048			sctp_mid_next(stream, in, csid);
1049			__skb_unlink(pos, lobby);
1050			__skb_queue_tail(&temp, pos);
1051			event = sctp_skb2event(pos);
1052		}
1053	}
1054
1055	if (event) {
1056		sctp_intl_retrieve_ordered(ulpq, event);
1057		sctp_enqueue_event(ulpq, &temp);
1058	}
1059}
1060
1061static void sctp_intl_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp)
1062{
1063	struct sctp_stream *stream = &ulpq->asoc->stream;
1064	__u16 sid;
1065
1066	for (sid = 0; sid < stream->incnt; sid++) {
1067		struct sctp_stream_in *sin = SCTP_SI(stream, sid);
1068		__u32 mid;
1069
1070		if (sin->pd_mode_uo) {
1071			sin->pd_mode_uo = 0;
1072
1073			mid = sin->mid_uo;
1074			sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x1, gfp);
1075		}
1076
1077		if (sin->pd_mode) {
1078			sin->pd_mode = 0;
1079
1080			mid = sin->mid;
1081			sctp_intl_stream_abort_pd(ulpq, sid, mid, 0, gfp);
1082			sctp_mid_skip(stream, in, sid, mid);
1083
1084			sctp_intl_reap_ordered(ulpq, sid);
1085		}
1086	}
1087
1088	/* intl abort pd happens only when all data needs to be cleaned */
1089	sctp_ulpq_flush(ulpq);
1090}
1091
1092static inline int sctp_get_skip_pos(struct sctp_ifwdtsn_skip *skiplist,
1093				    int nskips, __be16 stream, __u8 flags)
1094{
1095	int i;
1096
1097	for (i = 0; i < nskips; i++)
1098		if (skiplist[i].stream == stream &&
1099		    skiplist[i].flags == flags)
1100			return i;
1101
1102	return i;
1103}
1104
1105#define SCTP_FTSN_U_BIT	0x1
1106static void sctp_generate_iftsn(struct sctp_outq *q, __u32 ctsn)
1107{
1108	struct sctp_ifwdtsn_skip ftsn_skip_arr[10];
1109	struct sctp_association *asoc = q->asoc;
1110	struct sctp_chunk *ftsn_chunk = NULL;
1111	struct list_head *lchunk, *temp;
1112	int nskips = 0, skip_pos;
1113	struct sctp_chunk *chunk;
1114	__u32 tsn;
1115
1116	if (!asoc->peer.prsctp_capable)
1117		return;
1118
1119	if (TSN_lt(asoc->adv_peer_ack_point, ctsn))
1120		asoc->adv_peer_ack_point = ctsn;
1121
1122	list_for_each_safe(lchunk, temp, &q->abandoned) {
1123		chunk = list_entry(lchunk, struct sctp_chunk, transmitted_list);
1124		tsn = ntohl(chunk->subh.data_hdr->tsn);
1125
1126		if (TSN_lte(tsn, ctsn)) {
1127			list_del_init(lchunk);
1128			sctp_chunk_free(chunk);
1129		} else if (TSN_lte(tsn, asoc->adv_peer_ack_point + 1)) {
1130			__be16 sid = chunk->subh.idata_hdr->stream;
1131			__be32 mid = chunk->subh.idata_hdr->mid;
1132			__u8 flags = 0;
1133
1134			if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
1135				flags |= SCTP_FTSN_U_BIT;
1136
1137			asoc->adv_peer_ack_point = tsn;
1138			skip_pos = sctp_get_skip_pos(&ftsn_skip_arr[0], nskips,
1139						     sid, flags);
1140			ftsn_skip_arr[skip_pos].stream = sid;
1141			ftsn_skip_arr[skip_pos].reserved = 0;
1142			ftsn_skip_arr[skip_pos].flags = flags;
1143			ftsn_skip_arr[skip_pos].mid = mid;
1144			if (skip_pos == nskips)
1145				nskips++;
1146			if (nskips == 10)
1147				break;
1148		} else {
1149			break;
1150		}
1151	}
1152
1153	if (asoc->adv_peer_ack_point > ctsn)
1154		ftsn_chunk = sctp_make_ifwdtsn(asoc, asoc->adv_peer_ack_point,
1155					       nskips, &ftsn_skip_arr[0]);
1156
1157	if (ftsn_chunk) {
1158		list_add_tail(&ftsn_chunk->list, &q->control_chunk_list);
1159		SCTP_INC_STATS(asoc->base.net, SCTP_MIB_OUTCTRLCHUNKS);
1160	}
1161}
1162
1163#define _sctp_walk_ifwdtsn(pos, chunk, end) \
1164	for (pos = chunk->subh.ifwdtsn_hdr->skip; \
1165	     (void *)pos < (void *)chunk->subh.ifwdtsn_hdr->skip + (end); pos++)
1166
1167#define sctp_walk_ifwdtsn(pos, ch) \
1168	_sctp_walk_ifwdtsn((pos), (ch), ntohs((ch)->chunk_hdr->length) - \
1169					sizeof(struct sctp_ifwdtsn_chunk))
1170
1171static bool sctp_validate_fwdtsn(struct sctp_chunk *chunk)
1172{
1173	struct sctp_fwdtsn_skip *skip;
1174	__u16 incnt;
1175
1176	if (chunk->chunk_hdr->type != SCTP_CID_FWD_TSN)
1177		return false;
1178
1179	incnt = chunk->asoc->stream.incnt;
1180	sctp_walk_fwdtsn(skip, chunk)
1181		if (ntohs(skip->stream) >= incnt)
1182			return false;
1183
1184	return true;
1185}
1186
1187static bool sctp_validate_iftsn(struct sctp_chunk *chunk)
1188{
1189	struct sctp_ifwdtsn_skip *skip;
1190	__u16 incnt;
1191
1192	if (chunk->chunk_hdr->type != SCTP_CID_I_FWD_TSN)
1193		return false;
1194
1195	incnt = chunk->asoc->stream.incnt;
1196	sctp_walk_ifwdtsn(skip, chunk)
1197		if (ntohs(skip->stream) >= incnt)
1198			return false;
1199
1200	return true;
1201}
1202
1203static void sctp_report_fwdtsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1204{
1205	/* Move the Cumulattive TSN Ack ahead. */
1206	sctp_tsnmap_skip(&ulpq->asoc->peer.tsn_map, ftsn);
1207	/* purge the fragmentation queue */
1208	sctp_ulpq_reasm_flushtsn(ulpq, ftsn);
1209	/* Abort any in progress partial delivery. */
1210	sctp_ulpq_abort_pd(ulpq, GFP_ATOMIC);
1211}
1212
1213static void sctp_intl_reasm_flushtsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1214{
1215	struct sk_buff *pos, *tmp;
1216
1217	skb_queue_walk_safe(&ulpq->reasm, pos, tmp) {
1218		struct sctp_ulpevent *event = sctp_skb2event(pos);
1219		__u32 tsn = event->tsn;
1220
1221		if (TSN_lte(tsn, ftsn)) {
1222			__skb_unlink(pos, &ulpq->reasm);
1223			sctp_ulpevent_free(event);
1224		}
1225	}
1226
1227	skb_queue_walk_safe(&ulpq->reasm_uo, pos, tmp) {
1228		struct sctp_ulpevent *event = sctp_skb2event(pos);
1229		__u32 tsn = event->tsn;
1230
1231		if (TSN_lte(tsn, ftsn)) {
1232			__skb_unlink(pos, &ulpq->reasm_uo);
1233			sctp_ulpevent_free(event);
1234		}
1235	}
1236}
1237
1238static void sctp_report_iftsn(struct sctp_ulpq *ulpq, __u32 ftsn)
1239{
1240	/* Move the Cumulattive TSN Ack ahead. */
1241	sctp_tsnmap_skip(&ulpq->asoc->peer.tsn_map, ftsn);
1242	/* purge the fragmentation queue */
1243	sctp_intl_reasm_flushtsn(ulpq, ftsn);
1244	/* abort only when it's for all data */
1245	if (ftsn == sctp_tsnmap_get_max_tsn_seen(&ulpq->asoc->peer.tsn_map))
1246		sctp_intl_abort_pd(ulpq, GFP_ATOMIC);
1247}
1248
1249static void sctp_handle_fwdtsn(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk)
1250{
1251	struct sctp_fwdtsn_skip *skip;
1252
1253	/* Walk through all the skipped SSNs */
1254	sctp_walk_fwdtsn(skip, chunk)
1255		sctp_ulpq_skip(ulpq, ntohs(skip->stream), ntohs(skip->ssn));
1256}
1257
1258static void sctp_intl_skip(struct sctp_ulpq *ulpq, __u16 sid, __u32 mid,
1259			   __u8 flags)
1260{
1261	struct sctp_stream_in *sin = sctp_stream_in(&ulpq->asoc->stream, sid);
1262	struct sctp_stream *stream  = &ulpq->asoc->stream;
1263
1264	if (flags & SCTP_FTSN_U_BIT) {
1265		if (sin->pd_mode_uo && MID_lt(sin->mid_uo, mid)) {
1266			sin->pd_mode_uo = 0;
1267			sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x1,
1268						  GFP_ATOMIC);
1269		}
1270		return;
1271	}
1272
1273	if (MID_lt(mid, sctp_mid_peek(stream, in, sid)))
1274		return;
1275
1276	if (sin->pd_mode) {
1277		sin->pd_mode = 0;
1278		sctp_intl_stream_abort_pd(ulpq, sid, mid, 0x0, GFP_ATOMIC);
1279	}
1280
1281	sctp_mid_skip(stream, in, sid, mid);
1282
1283	sctp_intl_reap_ordered(ulpq, sid);
1284}
1285
1286static void sctp_handle_iftsn(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk)
1287{
1288	struct sctp_ifwdtsn_skip *skip;
1289
1290	/* Walk through all the skipped MIDs and abort stream pd if possible */
1291	sctp_walk_ifwdtsn(skip, chunk)
1292		sctp_intl_skip(ulpq, ntohs(skip->stream),
1293			       ntohl(skip->mid), skip->flags);
1294}
1295
1296static int do_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event)
1297{
1298	struct sk_buff_head temp;
1299
1300	skb_queue_head_init(&temp);
1301	__skb_queue_tail(&temp, sctp_event2skb(event));
1302	return sctp_ulpq_tail_event(ulpq, &temp);
1303}
1304
1305static struct sctp_stream_interleave sctp_stream_interleave_0 = {
1306	.data_chunk_len		= sizeof(struct sctp_data_chunk),
1307	.ftsn_chunk_len		= sizeof(struct sctp_fwdtsn_chunk),
1308	/* DATA process functions */
1309	.make_datafrag		= sctp_make_datafrag_empty,
1310	.assign_number		= sctp_chunk_assign_ssn,
1311	.validate_data		= sctp_validate_data,
1312	.ulpevent_data		= sctp_ulpq_tail_data,
1313	.enqueue_event		= do_ulpq_tail_event,
1314	.renege_events		= sctp_ulpq_renege,
1315	.start_pd		= sctp_ulpq_partial_delivery,
1316	.abort_pd		= sctp_ulpq_abort_pd,
1317	/* FORWARD-TSN process functions */
1318	.generate_ftsn		= sctp_generate_fwdtsn,
1319	.validate_ftsn		= sctp_validate_fwdtsn,
1320	.report_ftsn		= sctp_report_fwdtsn,
1321	.handle_ftsn		= sctp_handle_fwdtsn,
1322};
1323
1324static int do_sctp_enqueue_event(struct sctp_ulpq *ulpq,
1325				 struct sctp_ulpevent *event)
1326{
1327	struct sk_buff_head temp;
1328
1329	skb_queue_head_init(&temp);
1330	__skb_queue_tail(&temp, sctp_event2skb(event));
1331	return sctp_enqueue_event(ulpq, &temp);
1332}
1333
1334static struct sctp_stream_interleave sctp_stream_interleave_1 = {
1335	.data_chunk_len		= sizeof(struct sctp_idata_chunk),
1336	.ftsn_chunk_len		= sizeof(struct sctp_ifwdtsn_chunk),
1337	/* I-DATA process functions */
1338	.make_datafrag		= sctp_make_idatafrag_empty,
1339	.assign_number		= sctp_chunk_assign_mid,
1340	.validate_data		= sctp_validate_idata,
1341	.ulpevent_data		= sctp_ulpevent_idata,
1342	.enqueue_event		= do_sctp_enqueue_event,
1343	.renege_events		= sctp_renege_events,
1344	.start_pd		= sctp_intl_start_pd,
1345	.abort_pd		= sctp_intl_abort_pd,
1346	/* I-FORWARD-TSN process functions */
1347	.generate_ftsn		= sctp_generate_iftsn,
1348	.validate_ftsn		= sctp_validate_iftsn,
1349	.report_ftsn		= sctp_report_iftsn,
1350	.handle_ftsn		= sctp_handle_iftsn,
1351};
1352
1353void sctp_stream_interleave_init(struct sctp_stream *stream)
1354{
1355	struct sctp_association *asoc;
1356
1357	asoc = container_of(stream, struct sctp_association, stream);
1358	stream->si = asoc->peer.intl_capable ? &sctp_stream_interleave_1
1359					     : &sctp_stream_interleave_0;
1360}