0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0025
0026 #include <net/sctp/sctp.h>
0027 #include <net/sctp/sm.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/slab.h>
0030
0031
0032 void sctp_inq_init(struct sctp_inq *queue)
0033 {
0034 INIT_LIST_HEAD(&queue->in_chunk_list);
0035 queue->in_progress = NULL;
0036
0037
0038 INIT_WORK(&queue->immediate, NULL);
0039 }
0040
0041
0042 void sctp_inq_free(struct sctp_inq *queue)
0043 {
0044 struct sctp_chunk *chunk, *tmp;
0045
0046
0047 list_for_each_entry_safe(chunk, tmp, &queue->in_chunk_list, list) {
0048 list_del_init(&chunk->list);
0049 sctp_chunk_free(chunk);
0050 }
0051
0052
0053
0054
0055 if (queue->in_progress) {
0056 sctp_chunk_free(queue->in_progress);
0057 queue->in_progress = NULL;
0058 }
0059 }
0060
0061
0062
0063
0064 void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
0065 {
0066
0067 if (chunk->rcvr->dead) {
0068 sctp_chunk_free(chunk);
0069 return;
0070 }
0071
0072
0073
0074
0075
0076
0077 list_add_tail(&chunk->list, &q->in_chunk_list);
0078 if (chunk->asoc)
0079 chunk->asoc->stats.ipackets++;
0080 q->immediate.func(&q->immediate);
0081 }
0082
0083
0084 struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *queue)
0085 {
0086 struct sctp_chunk *chunk;
0087 struct sctp_chunkhdr *ch = NULL;
0088
0089 chunk = queue->in_progress;
0090
0091 if (chunk->singleton ||
0092 chunk->end_of_packet ||
0093 chunk->pdiscard)
0094 return NULL;
0095
0096 ch = (struct sctp_chunkhdr *)chunk->chunk_end;
0097
0098 return ch;
0099 }
0100
0101
0102
0103
0104
0105
0106
0107 struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
0108 {
0109 struct sctp_chunk *chunk;
0110 struct sctp_chunkhdr *ch = NULL;
0111
0112
0113
0114
0115
0116 chunk = queue->in_progress;
0117 if (chunk) {
0118
0119
0120
0121 if (chunk->singleton ||
0122 chunk->end_of_packet ||
0123 chunk->pdiscard) {
0124 if (chunk->head_skb == chunk->skb) {
0125 chunk->skb = skb_shinfo(chunk->skb)->frag_list;
0126 goto new_skb;
0127 }
0128 if (chunk->skb->next) {
0129 chunk->skb = chunk->skb->next;
0130 goto new_skb;
0131 }
0132
0133 if (chunk->head_skb)
0134 chunk->skb = chunk->head_skb;
0135 sctp_chunk_free(chunk);
0136 chunk = queue->in_progress = NULL;
0137 } else {
0138
0139 ch = (struct sctp_chunkhdr *)chunk->chunk_end;
0140
0141 skb_pull(chunk->skb, chunk->chunk_end - chunk->skb->data);
0142
0143 }
0144 }
0145
0146
0147 if (!chunk) {
0148 struct list_head *entry;
0149
0150 next_chunk:
0151
0152 entry = sctp_list_dequeue(&queue->in_chunk_list);
0153 if (!entry)
0154 return NULL;
0155
0156 chunk = list_entry(entry, struct sctp_chunk, list);
0157
0158 if (skb_is_gso(chunk->skb) && skb_is_gso_sctp(chunk->skb)) {
0159
0160
0161
0162 if (skb_shinfo(chunk->skb)->frag_list)
0163 chunk->head_skb = chunk->skb;
0164
0165
0166 if (chunk->head_skb && chunk->skb->data_len == chunk->skb->len)
0167 chunk->skb = skb_shinfo(chunk->skb)->frag_list;
0168
0169 if (WARN_ON(!chunk->skb)) {
0170 __SCTP_INC_STATS(dev_net(chunk->skb->dev), SCTP_MIB_IN_PKT_DISCARDS);
0171 sctp_chunk_free(chunk);
0172 goto next_chunk;
0173 }
0174 }
0175
0176 if (chunk->asoc)
0177 sock_rps_save_rxhash(chunk->asoc->base.sk, chunk->skb);
0178
0179 queue->in_progress = chunk;
0180
0181 new_skb:
0182
0183 ch = (struct sctp_chunkhdr *)chunk->skb->data;
0184 chunk->singleton = 1;
0185 chunk->data_accepted = 0;
0186 chunk->pdiscard = 0;
0187 chunk->auth = 0;
0188 chunk->has_asconf = 0;
0189 chunk->end_of_packet = 0;
0190 if (chunk->head_skb) {
0191 struct sctp_input_cb
0192 *cb = SCTP_INPUT_CB(chunk->skb),
0193 *head_cb = SCTP_INPUT_CB(chunk->head_skb);
0194
0195 cb->chunk = head_cb->chunk;
0196 cb->af = head_cb->af;
0197 }
0198 }
0199
0200 chunk->chunk_hdr = ch;
0201 chunk->chunk_end = ((__u8 *)ch) + SCTP_PAD4(ntohs(ch->length));
0202 skb_pull(chunk->skb, sizeof(*ch));
0203 chunk->subh.v = NULL;
0204
0205 if (chunk->chunk_end + sizeof(*ch) <= skb_tail_pointer(chunk->skb)) {
0206
0207 chunk->singleton = 0;
0208 } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {
0209
0210 chunk->pdiscard = 1;
0211 chunk->chunk_end = skb_tail_pointer(chunk->skb);
0212 } else {
0213
0214
0215
0216 chunk->end_of_packet = 1;
0217 }
0218
0219 pr_debug("+++sctp_inq_pop+++ chunk:%p[%s], length:%d, skb->len:%d\n",
0220 chunk, sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)),
0221 ntohs(chunk->chunk_hdr->length), chunk->skb->len);
0222
0223 return chunk;
0224 }
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback)
0235 {
0236 INIT_WORK(&q->immediate, callback);
0237 }