⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sm_statefuns.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* SCTP kernel implementation * (C) Copyright IBM Corp. 2001, 2004 * Copyright (c) 1999-2000 Cisco, Inc. * Copyright (c) 1999-2001 Motorola, Inc. * Copyright (c) 2001-2002 Intel Corp. * Copyright (c) 2002      Nokia Corp. * * This is part of the SCTP Linux Kernel Implementation. * * These are the state functions for the state machine. * * This SCTP implementation is free software; * you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This SCTP implementation is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied *                 ************************ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU CC; see the file COPYING.  If not, write to * the Free Software Foundation, 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Please send any bug reports or fixes you make to the * email address(es): *    lksctp developers <lksctp-developers@lists.sourceforge.net> * * Or submit a bug report through the following website: *    http://www.sf.net/projects/lksctp * * Written or modified by: *    La Monte H.P. Yarroll <piggy@acm.org> *    Karl Knutson          <karl@athena.chicago.il.us> *    Mathew Kotowsky       <kotowsky@sctp.org> *    Sridhar Samudrala     <samudrala@us.ibm.com> *    Jon Grimm             <jgrimm@us.ibm.com> *    Hui Huang 	    <hui.huang@nokia.com> *    Dajiang Zhang 	    <dajiang.zhang@nokia.com> *    Daisy Chang	    <daisyc@us.ibm.com> *    Ardelle Fan	    <ardelle.fan@intel.com> *    Ryan Layer	    <rmlayer@us.ibm.com> *    Kevin Gao		    <kevin.gao@intel.com> * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */#include <linux/types.h>#include <linux/kernel.h>#include <linux/ip.h>#include <linux/ipv6.h>#include <linux/net.h>#include <linux/inet.h>#include <net/sock.h>#include <net/inet_ecn.h>#include <linux/skbuff.h>#include <net/sctp/sctp.h>#include <net/sctp/sm.h>#include <net/sctp/structs.h>static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep,				  const struct sctp_association *asoc,				  struct sctp_chunk *chunk,				  const void *payload,				  size_t paylen);static int sctp_eat_data(const struct sctp_association *asoc,			 struct sctp_chunk *chunk,			 sctp_cmd_seq_t *commands);static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc,					     const struct sctp_chunk *chunk);static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep,				       const struct sctp_association *asoc,				       const struct sctp_chunk *chunk,				       sctp_cmd_seq_t *commands,				       struct sctp_chunk *err_chunk);static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep,						 const struct sctp_association *asoc,						 const sctp_subtype_t type,						 void *arg,						 sctp_cmd_seq_t *commands);static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,					     const struct sctp_association *asoc,					     const sctp_subtype_t type,					     void *arg,					     sctp_cmd_seq_t *commands);static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands);static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,					   __be16 error, int sk_err,					   const struct sctp_association *asoc,					   struct sctp_transport *transport);static sctp_disposition_t sctp_sf_abort_violation(				     const struct sctp_endpoint *ep,				     const struct sctp_association *asoc,				     void *arg,				     sctp_cmd_seq_t *commands,				     const __u8 *payload,				     const size_t paylen);static sctp_disposition_t sctp_sf_violation_chunklen(				     const struct sctp_endpoint *ep,				     const struct sctp_association *asoc,				     const sctp_subtype_t type,				     void *arg,				     sctp_cmd_seq_t *commands);static sctp_disposition_t sctp_sf_violation_paramlen(				     const struct sctp_endpoint *ep,				     const struct sctp_association *asoc,				     const sctp_subtype_t type,				     void *arg,				     sctp_cmd_seq_t *commands);static sctp_disposition_t sctp_sf_violation_ctsn(				     const struct sctp_endpoint *ep,				     const struct sctp_association *asoc,				     const sctp_subtype_t type,				     void *arg,				     sctp_cmd_seq_t *commands);static sctp_disposition_t sctp_sf_violation_chunk(				     const struct sctp_endpoint *ep,				     const struct sctp_association *asoc,				     const sctp_subtype_t type,				     void *arg,				     sctp_cmd_seq_t *commands);static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep,				    const struct sctp_association *asoc,				    const sctp_subtype_t type,				    struct sctp_chunk *chunk);static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands);/* Small helper function that checks if the chunk length * is of the appropriate length.  The 'required_length' argument * is set to be the size of a specific chunk we are testing. * Return Values:  1 = Valid length * 		   0 = Invalid length * */static inline intsctp_chunk_length_valid(struct sctp_chunk *chunk,			   __u16 required_length){	__u16 chunk_length = ntohs(chunk->chunk_hdr->length);	if (unlikely(chunk_length < required_length))		return 0;	return 1;}/********************************************************** * These are the state functions for handling chunk events. **********************************************************//* * Process the final SHUTDOWN COMPLETE. * * Section: 4 (C) (diagram), 9.2 * Upon reception of the SHUTDOWN COMPLETE chunk the endpoint will verify * that it is in SHUTDOWN-ACK-SENT state, if it is not the chunk should be * discarded. If the endpoint is in the SHUTDOWN-ACK-SENT state the endpoint * should stop the T2-shutdown timer and remove all knowledge of the * association (and thus the association enters the CLOSED state). * * Verification Tag: 8.5.1(C), sctpimpguide 2.41. * C) Rules for packet carrying SHUTDOWN COMPLETE: * ... * - The receiver of a SHUTDOWN COMPLETE shall accept the packet *   if the Verification Tag field of the packet matches its own tag and *   the T bit is not set *   OR *   it is set to its peer's tag and the T bit is set in the Chunk *   Flags. *   Otherwise, the receiver MUST silently discard the packet *   and take no further action.  An endpoint MUST ignore the *   SHUTDOWN COMPLETE if it is not in the SHUTDOWN-ACK-SENT state. * * Inputs * (endpoint, asoc, chunk) * * Outputs * (asoc, reply_msg, msg_up, timers, counters) * * The return value is the disposition of the chunk. */sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,				  const struct sctp_association *asoc,				  const sctp_subtype_t type,				  void *arg,				  sctp_cmd_seq_t *commands){	struct sctp_chunk *chunk = arg;	struct sctp_ulpevent *ev;	if (!sctp_vtag_verify_either(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* RFC 2960 6.10 Bundling	 *	 * An endpoint MUST NOT bundle INIT, INIT ACK or	 * SHUTDOWN COMPLETE with any other chunks.	 */	if (!chunk->singleton)		return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);	/* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	/* RFC 2960 10.2 SCTP-to-ULP	 *	 * H) SHUTDOWN COMPLETE notification	 *	 * When SCTP completes the shutdown procedures (section 9.2) this	 * notification is passed to the upper layer.	 */	ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_SHUTDOWN_COMP,					     0, 0, 0, NULL, GFP_ATOMIC);	if (ev)		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,				SCTP_ULPEVENT(ev));	/* Upon reception of the SHUTDOWN COMPLETE chunk the endpoint	 * will verify that it is in SHUTDOWN-ACK-SENT state, if it is	 * not the chunk should be discarded. If the endpoint is in	 * the SHUTDOWN-ACK-SENT state the endpoint should stop the	 * T2-shutdown timer and remove all knowledge of the	 * association (and thus the association enters the CLOSED	 * state).	 */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,			SCTP_STATE(SCTP_STATE_CLOSED));	SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS);	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());	return SCTP_DISPOSITION_DELETE_TCB;}/* * Respond to a normal INIT chunk. * We are the side that is being asked for an association. * * Section: 5.1 Normal Establishment of an Association, B * B) "Z" shall respond immediately with an INIT ACK chunk.  The *    destination IP address of the INIT ACK MUST be set to the source *    IP address of the INIT to which this INIT ACK is responding.  In *    the response, besides filling in other parameters, "Z" must set the *    Verification Tag field to Tag_A, and also provide its own *    Verification Tag (Tag_Z) in the Initiate Tag field. * * Verification Tag: Must be 0. * * Inputs * (endpoint, asoc, chunk) * * Outputs * (asoc, reply_msg, msg_up, timers, counters) * * The return value is the disposition of the chunk. */sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands){	struct sctp_chunk *chunk = arg;	struct sctp_chunk *repl;	struct sctp_association *new_asoc;	struct sctp_chunk *err_chunk;	struct sctp_packet *packet;	sctp_unrecognized_param_t *unk_param;	int len;	/* 6.10 Bundling	 * An endpoint MUST NOT bundle INIT, INIT ACK or	 * SHUTDOWN COMPLETE with any other chunks.	 *	 * IG Section 2.11.2	 * Furthermore, we require that the receiver of an INIT chunk MUST	 * enforce these rules by silently discarding an arriving packet	 * with an INIT chunk that is bundled with other chunks.	 */	if (!chunk->singleton)		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* If the packet is an OOTB packet which is temporarily on the	 * control endpoint, respond with an ABORT.	 */	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);	/* 3.1 A packet containing an INIT chunk MUST have a zero Verification	 * Tag.	 */	if (chunk->sctp_hdr->vtag != 0)		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);	/* Make sure that the INIT chunk has a valid length.	 * Normally, this would cause an ABORT with a Protocol Violation	 * error, but since we don't have an association, we'll	 * just discard the packet.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Verify the INIT chunk before processing it. */	err_chunk = NULL;	if (!sctp_verify_init(asoc, chunk->chunk_hdr->type,			      (sctp_init_chunk_t *)chunk->chunk_hdr, chunk,			      &err_chunk)) {		/* This chunk contains fatal error. It is to be discarded.		 * Send an ABORT, with causes if there is any.		 */		if (err_chunk) {			packet = sctp_abort_pkt_new(ep, asoc, arg,					(__u8 *)(err_chunk->chunk_hdr) +					sizeof(sctp_chunkhdr_t),					ntohs(err_chunk->chunk_hdr->length) -					sizeof(sctp_chunkhdr_t));			sctp_chunk_free(err_chunk);			if (packet) {				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,						SCTP_PACKET(packet));				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);				return SCTP_DISPOSITION_CONSUME;			} else {				return SCTP_DISPOSITION_NOMEM;			}		} else {			return sctp_sf_tabort_8_4_8(ep, asoc, type, arg,						    commands);		}	}	/* Grab the INIT header.  */	chunk->subh.init_hdr = (sctp_inithdr_t *)chunk->skb->data;	/* Tag the variable length parameters.  */	chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));	new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC);	if (!new_asoc)		goto nomem;	/* The call, sctp_process_init(), can fail on memory allocation.  */	if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,			       sctp_source(chunk),			       (sctp_init_chunk_t *)chunk->chunk_hdr,			       GFP_ATOMIC))		goto nomem_init;	/* B) "Z" shall respond immediately with an INIT ACK chunk.  */	/* If there are errors need to be reported for unknown parameters,	 * make sure to reserve enough room in the INIT ACK for them.	 */	len = 0;	if (err_chunk)		len = ntohs(err_chunk->chunk_hdr->length) -			sizeof(sctp_chunkhdr_t);	if (sctp_assoc_set_bind_addr_from_ep(new_asoc, GFP_ATOMIC) < 0)		goto nomem_init;	repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);	if (!repl)		goto nomem_init;	/* If there are errors need to be reported for unknown parameters,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -