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