/* SCTP kernel implementation1* Copyright (c) 1999-2000 Cisco, Inc.2* Copyright (c) 1999-2001 Motorola, Inc.3* Copyright (c) 2002 International Business Machines, Corp.4*5* This file is part of the SCTP kernel implementation6*7* These functions are the methods for accessing the SCTP inqueue.8*9* An SCTP inqueue is a queue into which you push SCTP packets10* (which might be bundles or fragments of chunks) and out of which you11* pop SCTP whole chunks.12*13* This SCTP implementation is free software;14* you can redistribute it and/or modify it under the terms of15* the GNU General Public License as published by16* the Free Software Foundation; either version 2, or (at your option)17* any later version.18*19* This SCTP implementation is distributed in the hope that it20* will be useful, but WITHOUT ANY WARRANTY; without even the implied21* ************************22* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.23* See the GNU General Public License for more details.24*25* You should have received a copy of the GNU General Public License26* along with GNU CC; see the file COPYING. If not, write to27* the Free Software Foundation, 59 Temple Place - Suite 330,28* Boston, MA 02111-1307, USA.29*30* Please send any bug reports or fixes you make to the31* email address(es):32* lksctp developers <[email protected]>33*34* Or submit a bug report through the following website:35* http://www.sf.net/projects/lksctp36*37* Written or modified by:38* La Monte H.P. Yarroll <[email protected]>39* Karl Knutson <[email protected]>40*41* Any bugs reported given to us we will try to fix... any fixes shared will42* be incorporated into the next SCTP release.43*/4445#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt4647#include <net/sctp/sctp.h>48#include <net/sctp/sm.h>49#include <linux/interrupt.h>50#include <linux/slab.h>5152/* Initialize an SCTP inqueue. */53void sctp_inq_init(struct sctp_inq *queue)54{55INIT_LIST_HEAD(&queue->in_chunk_list);56queue->in_progress = NULL;5758/* Create a task for delivering data. */59INIT_WORK(&queue->immediate, NULL);6061queue->malloced = 0;62}6364/* Release the memory associated with an SCTP inqueue. */65void sctp_inq_free(struct sctp_inq *queue)66{67struct sctp_chunk *chunk, *tmp;6869/* Empty the queue. */70list_for_each_entry_safe(chunk, tmp, &queue->in_chunk_list, list) {71list_del_init(&chunk->list);72sctp_chunk_free(chunk);73}7475/* If there is a packet which is currently being worked on,76* free it as well.77*/78if (queue->in_progress) {79sctp_chunk_free(queue->in_progress);80queue->in_progress = NULL;81}8283if (queue->malloced) {84/* Dump the master memory segment. */85kfree(queue);86}87}8889/* Put a new packet in an SCTP inqueue.90* We assume that packet->sctp_hdr is set and in host byte order.91*/92void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)93{94/* Directly call the packet handling routine. */95if (chunk->rcvr->dead) {96sctp_chunk_free(chunk);97return;98}99100/* We are now calling this either from the soft interrupt101* or from the backlog processing.102* Eventually, we should clean up inqueue to not rely103* on the BH related data structures.104*/105list_add_tail(&chunk->list, &q->in_chunk_list);106q->immediate.func(&q->immediate);107}108109/* Peek at the next chunk on the inqeue. */110struct sctp_chunkhdr *sctp_inq_peek(struct sctp_inq *queue)111{112struct sctp_chunk *chunk;113sctp_chunkhdr_t *ch = NULL;114115chunk = queue->in_progress;116/* If there is no more chunks in this packet, say so */117if (chunk->singleton ||118chunk->end_of_packet ||119chunk->pdiscard)120return NULL;121122ch = (sctp_chunkhdr_t *)chunk->chunk_end;123124return ch;125}126127128/* Extract a chunk from an SCTP inqueue.129*130* WARNING: If you need to put the chunk on another queue, you need to131* make a shallow copy (clone) of it.132*/133struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)134{135struct sctp_chunk *chunk;136sctp_chunkhdr_t *ch = NULL;137138/* The assumption is that we are safe to process the chunks139* at this time.140*/141142if ((chunk = queue->in_progress)) {143/* There is a packet that we have been working on.144* Any post processing work to do before we move on?145*/146if (chunk->singleton ||147chunk->end_of_packet ||148chunk->pdiscard) {149sctp_chunk_free(chunk);150chunk = queue->in_progress = NULL;151} else {152/* Nothing to do. Next chunk in the packet, please. */153ch = (sctp_chunkhdr_t *) chunk->chunk_end;154155/* Force chunk->skb->data to chunk->chunk_end. */156skb_pull(chunk->skb,157chunk->chunk_end - chunk->skb->data);158159/* Verify that we have at least chunk headers160* worth of buffer left.161*/162if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) {163sctp_chunk_free(chunk);164chunk = queue->in_progress = NULL;165}166}167}168169/* Do we need to take the next packet out of the queue to process? */170if (!chunk) {171struct list_head *entry;172173/* Is the queue empty? */174if (list_empty(&queue->in_chunk_list))175return NULL;176177entry = queue->in_chunk_list.next;178chunk = queue->in_progress =179list_entry(entry, struct sctp_chunk, list);180list_del_init(entry);181182/* This is the first chunk in the packet. */183chunk->singleton = 1;184ch = (sctp_chunkhdr_t *) chunk->skb->data;185chunk->data_accepted = 0;186}187188chunk->chunk_hdr = ch;189chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));190/* In the unlikely case of an IP reassembly, the skb could be191* non-linear. If so, update chunk_end so that it doesn't go past192* the skb->tail.193*/194if (unlikely(skb_is_nonlinear(chunk->skb))) {195if (chunk->chunk_end > skb_tail_pointer(chunk->skb))196chunk->chunk_end = skb_tail_pointer(chunk->skb);197}198skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));199chunk->subh.v = NULL; /* Subheader is no longer valid. */200201if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) {202/* This is not a singleton */203chunk->singleton = 0;204} else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {205/* RFC 2960, Section 6.10 Bundling206*207* Partial chunks MUST NOT be placed in an SCTP packet.208* If the receiver detects a partial chunk, it MUST drop209* the chunk.210*211* Since the end of the chunk is past the end of our buffer212* (which contains the whole packet, we can freely discard213* the whole packet.214*/215sctp_chunk_free(chunk);216chunk = queue->in_progress = NULL;217218return NULL;219} else {220/* We are at the end of the packet, so mark the chunk221* in case we need to send a SACK.222*/223chunk->end_of_packet = 1;224}225226SCTP_DEBUG_PRINTK("+++sctp_inq_pop+++ chunk %p[%s],"227" length %d, skb->len %d\n",chunk,228sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)),229ntohs(chunk->chunk_hdr->length), chunk->skb->len);230return chunk;231}232233/* Set a top-half handler.234*235* Originally, we the top-half handler was scheduled as a BH. We now236* call the handler directly in sctp_inq_push() at a time that237* we know we are lock safe.238* The intent is that this routine will pull stuff out of the239* inqueue and process it.240*/241void sctp_inq_set_th_handler(struct sctp_inq *q, work_func_t callback)242{243INIT_WORK(&q->immediate, callback);244}245246247248