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

📄 sm_statefuns.c

📁 一种在UDP协议中实现了拥赛控制和重传机制的协议
💻 C
📖 第 1 页 / 共 5 页
字号:
 *    the T1-cookie timer, and enter the COOKIE-ECHOED state. * *    Note: The COOKIE ECHO chunk can be bundled with any pending outbound *    DATA chunks, but it MUST be the first chunk in the packet and *    until the COOKIE ACK is returned the sender MUST NOT send any *    other packets to the peer. * * Verification Tag: 3.3.3 *   If the value of the Initiate Tag in a received INIT ACK chunk is *   found to be 0, the receiver MUST treat it as an error and close the *   association by transmitting an ABORT. * * 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_1C_ack(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;	sctp_init_chunk_t *initchunk;	__u32 init_tag;	struct sctp_chunk *err_chunk;	struct sctp_packet *packet;	sctp_disposition_t ret;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the INIT-ACK chunk has a valid length */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	/* 6.10 Bundling	 * An endpoint MUST NOT bundle INIT, INIT ACK or	 * SHUTDOWN COMPLETE with any other chunks.	 */	if (!chunk->singleton)		return SCTP_DISPOSITION_VIOLATION;	/* Grab the INIT header.  */	chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;	init_tag = ntohl(chunk->subh.init_hdr->init_tag);	/* Verification Tag: 3.3.3	 *   If the value of the Initiate Tag in a received INIT ACK	 *   chunk is found to be 0, the receiver MUST treat it as an	 *   error and close the association by transmitting an ABORT.	 */	if (!init_tag) {		struct sctp_chunk *reply = sctp_make_abort(asoc, chunk, 0);		if (!reply)			goto nomem;		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));		sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,				SCTP_STATE(SCTP_STATE_CLOSED));		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);		sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());		return SCTP_DISPOSITION_DELETE_TCB;	}	/* 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)) {		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);		/* 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);				sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,						SCTP_STATE(SCTP_STATE_CLOSED));				sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,						SCTP_NULL());				return SCTP_DISPOSITION_CONSUME;			} else {				sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,						SCTP_STATE(SCTP_STATE_CLOSED));				sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,						SCTP_NULL());				return SCTP_DISPOSITION_NOMEM;			}		} else {			ret = sctp_sf_tabort_8_4_8(ep, asoc, type, arg,						   commands);			sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,					SCTP_STATE(SCTP_STATE_CLOSED));			sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB,					SCTP_NULL());			return ret;		}	}	/* Tag the variable length parameters.  Note that we never	 * convert the parameters in an INIT chunk.	 */	chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));	initchunk = (sctp_init_chunk_t *) chunk->chunk_hdr;	sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,			SCTP_PEER_INIT(initchunk));	/* 5.1 C) "A" shall stop the T1-init timer and leave	 * COOKIE-WAIT state.  "A" shall then ... start the T1-cookie	 * timer, and enter the COOKIE-ECHOED state.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,			SCTP_STATE(SCTP_STATE_COOKIE_ECHOED));	/* 5.1 C) "A" shall then send the State Cookie received in the	 * INIT ACK chunk in a COOKIE ECHO chunk, ...	 */	/* If there is any errors to report, send the ERROR chunk generated	 * for unknown parameters as well.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_GEN_COOKIE_ECHO,			SCTP_CHUNK(err_chunk));	return SCTP_DISPOSITION_CONSUME;nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Respond to a normal COOKIE ECHO chunk. * We are the side that is being asked for an association. * * Section: 5.1 Normal Establishment of an Association, D * D) Upon reception of the COOKIE ECHO chunk, Endpoint "Z" will reply *    with a COOKIE ACK chunk after building a TCB and moving to *    the ESTABLISHED state. A COOKIE ACK chunk may be bundled with *    any pending DATA chunks (and/or SACK chunks), but the COOKIE ACK *    chunk MUST be the first chunk in the packet. * *   IMPLEMENTATION NOTE: An implementation may choose to send the *   Communication Up notification to the SCTP user upon reception *   of a valid COOKIE ECHO chunk. * * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules * D) Rules for packet carrying a COOKIE ECHO * * - When sending a COOKIE ECHO, the endpoint MUST use the value of the *   Initial Tag received in the INIT ACK. * * - The receiver of a COOKIE ECHO follows the procedures in Section 5. * * 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_1D_ce(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_association *new_asoc;	sctp_init_chunk_t *peer_init;	struct sctp_chunk *repl;	struct sctp_ulpevent *ev;	int error = 0;	struct sctp_chunk *err_chk_p;	/* 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_ootb(ep, asoc, type, arg, commands);	/* Make sure that the COOKIE_ECHO chunk has a valid length.	 * In this case, we check that we have enough for at least a	 * chunk header.  More detailed verification is done	 * in sctp_unpack_cookie().	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* "Decode" the chunk.  We have no optional parameters so we	 * are in good shape.	 */        chunk->subh.cookie_hdr =		(struct sctp_signed_cookie *)chunk->skb->data;	skb_pull(chunk->skb,		 ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t));	/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint	 * "Z" will reply with a COOKIE ACK chunk after building a TCB	 * and moving to the ESTABLISHED state.	 */	new_asoc = sctp_unpack_cookie(ep, asoc, chunk, GFP_ATOMIC, &error,				      &err_chk_p);	/* FIXME:	 * If the re-build failed, what is the proper error path	 * from here?	 *	 * [We should abort the association. --piggy]	 */	if (!new_asoc) {		/* FIXME: Several errors are possible.  A bad cookie should		 * be silently discarded, but think about logging it too.		 */		switch (error) {		case -SCTP_IERROR_NOMEM:			goto nomem;		case -SCTP_IERROR_STALE_COOKIE:			sctp_send_stale_cookie_err(ep, asoc, chunk, commands,						   err_chk_p);			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);		case -SCTP_IERROR_BAD_SIG:		default:			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);		};	}	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,			SCTP_STATE(SCTP_STATE_ESTABLISHED));	SCTP_INC_STATS(SCTP_MIB_CURRESTAB);	SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS);	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());	if (new_asoc->autoclose)		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	/* Re-build the bind address for the association is done in	 * the sctp_unpack_cookie() already.	 */	/* This is a brand-new association, so these are not yet side	 * effects--it is safe to run them here.	 */	peer_init = &chunk->subh.cookie_hdr->c.peer_init[0];	if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,			       &chunk->subh.cookie_hdr->c.peer_addr,			       peer_init, GFP_ATOMIC))		goto nomem_init;	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem_repl;	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	/* RFC 2960 5.1 Normal Establishment of an Association	 *	 * D) IMPLEMENTATION NOTE: An implementation may choose to	 * send the Communication Up notification to the SCTP user	 * upon reception of a valid COOKIE ECHO chunk.	 */	ev = sctp_ulpevent_make_assoc_change(new_asoc, 0, SCTP_COMM_UP, 0,					     new_asoc->c.sinit_num_ostreams,					     new_asoc->c.sinit_max_instreams,					     GFP_ATOMIC);	if (!ev)		goto nomem_ev;	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));	/* Sockets API Draft Section 5.3.1.6 		 * When a peer sends a Adaption Layer Indication parameter , SCTP	 * delivers this notification to inform the application that of the	 * peers requested adaption layer.	 */	if (new_asoc->peer.adaption_ind) {		ev = sctp_ulpevent_make_adaption_indication(new_asoc,							    GFP_ATOMIC);		if (!ev)			goto nomem_ev;		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,				SCTP_ULPEVENT(ev));	}	return SCTP_DISPOSITION_CONSUME;nomem_ev:	sctp_chunk_free(repl);nomem_repl:nomem_init:	sctp_association_free(new_asoc);nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Respond to a normal COOKIE ACK chunk. * We are the side that is being asked for an association. * * RFC 2960 5.1 Normal Establishment of an Association * * E) Upon reception of the COOKIE ACK, endpoint "A" will move from the *    COOKIE-ECHOED state to the ESTABLISHED state, stopping the T1-cookie *    timer. It may also notify its ULP about the successful *    establishment of the association with a Communication Up *    notification (see Section 10). * * Verification Tag: * 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_1E_ca(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(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Verify that the chunk length for the COOKIE-ACK is OK.	 * If we don't do this, any bundled chunks may be junked.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	/* Reset init error count upon receipt of COOKIE-ACK,	 * to avoid problems with the managemement of this	 * counter in stale cookie situations when a transition back	 * from the COOKIE-ECHOED state to the COOKIE-WAIT	 * state is performed.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_RESET,	                SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));	/* RFC 2960 5.1 Normal Establishment of an Association	 *	 * E) Upon reception of the COOKIE ACK, endpoint "A" will move	 * from the COOKIE-ECHOED state to the ESTABLISHED state,	 * stopping the T1-cookie timer.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,			SCTP_STATE(SCTP_STATE_ESTABLISHED));	SCTP_INC_STATS(SCTP_MIB_CURRESTAB);	SCTP_INC_STATS(SCTP_MIB_ACTIVEESTABS);	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());	if (asoc->autoclose)		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	/* It may also notify its ULP about the successful	 * establishment of the association with a Communication Up	 * notification (see Section 10).	 */	ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP,					     0, asoc->c.sinit_num_ostreams,					     asoc->c.sinit_max_instreams,					     GFP_ATOMIC);	if (!ev)		goto nomem;	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));	/* Sockets API Draft Section 5.3.1.6	 * When a peer sends a Adaption Layer Indication parameter , SCTP	 * delivers this notification to inform the application that of the	 * peers requested adaption layer.

⌨️ 快捷键说明

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