cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stream_interleave.c (32206B)


      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}