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

📄 sm_statefuns.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * existing parameters of the association (e.g. number of outbound * streams) into the INIT ACK and cookie. * * After sending out the INIT ACK, the endpoint shall take no further * actions, i.e., the existing association, including its current state, * and the corresponding TCB MUST NOT be changed. * * Note: Only when a TCB exists and the association is not in a COOKIE- * WAIT state are the Tie-Tags populated.  For a normal association INIT * (i.e. the endpoint is in a COOKIE-WAIT state), the Tie-Tags MUST be * set to 0 (indicating that no previous TCB existed).  The INIT ACK and * State Cookie are populated as specified in section 5.2.1. * * Verification Tag: Not specified, but an INIT has no way of knowing * what the verification tag could be, so we ignore it. * * 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_2_2_dupinit(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands){	/* Call helper to do the real work for both simulataneous and	 * duplicate INIT chunk handling.	 */	return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands);}/* * Unexpected INIT-ACK handler. * * Section 5.2.3 * If an INIT ACK received by an endpoint in any state other than the * COOKIE-WAIT state, the endpoint should discard the INIT ACK chunk. * An unexpected INIT ACK usually indicates the processing of an old or * duplicated INIT chunk.*/sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep,					    const struct sctp_association *asoc,					    const sctp_subtype_t type,					    void *arg, sctp_cmd_seq_t *commands){	/* Per the above section, we'll discard the chunk if we have an	 * endpoint.  If this is an OOTB INIT-ACK, treat it as such.	 */	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)		return sctp_sf_ootb(ep, asoc, type, arg, commands);	else		return sctp_sf_discard_chunk(ep, asoc, type, arg, commands);}/* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A') * * Section 5.2.4 *  A)  In this case, the peer may have restarted. */static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					struct sctp_chunk *chunk,					sctp_cmd_seq_t *commands,					struct sctp_association *new_asoc){	sctp_init_chunk_t *peer_init;	struct sctp_ulpevent *ev;	struct sctp_chunk *repl;	struct sctp_chunk *err;	sctp_disposition_t disposition;	/* new_asoc 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,			       sctp_source(chunk), peer_init,			       GFP_ATOMIC))		goto nomem;	/* Make sure no new addresses are being added during the	 * restart.  Though this is a pretty complicated attack	 * since you'd have to get inside the cookie.	 */	if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk, commands)) {		return SCTP_DISPOSITION_CONSUME;	}	/* If the endpoint is in the SHUTDOWN-ACK-SENT state and recognizes	 * the peer has restarted (Action A), it MUST NOT setup a new	 * association but instead resend the SHUTDOWN ACK and send an ERROR	 * chunk with a "Cookie Received while Shutting Down" error cause to	 * its peer.	*/	if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) {		disposition = sctp_sf_do_9_2_reshutack(ep, asoc,				SCTP_ST_CHUNK(chunk->chunk_hdr->type),				chunk, commands);		if (SCTP_DISPOSITION_NOMEM == disposition)			goto nomem;		err = sctp_make_op_error(asoc, chunk,					 SCTP_ERROR_COOKIE_IN_SHUTDOWN,					 NULL, 0);		if (err)			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,					SCTP_CHUNK(err));		return SCTP_DISPOSITION_CONSUME;	}	/* For now, fail any unsent/unacked data.  Consider the optional	 * choice of resending of this data.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_PURGE_OUTQUEUE, SCTP_NULL());	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem;	/* Report association restart to upper layer. */	ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_RESTART, 0,					     new_asoc->c.sinit_num_ostreams,					     new_asoc->c.sinit_max_instreams,					     NULL, GFP_ATOMIC);	if (!ev)		goto nomem_ev;	/* Update the content of current association. */	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));	return SCTP_DISPOSITION_CONSUME;nomem_ev:	sctp_chunk_free(repl);nomem:	return SCTP_DISPOSITION_NOMEM;}/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'B') * * Section 5.2.4 *   B) In this case, both sides may be attempting to start an association *      at about the same time but the peer endpoint started its INIT *      after responding to the local endpoint's INIT *//* This case represents an initialization collision.  */static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					struct sctp_chunk *chunk,					sctp_cmd_seq_t *commands,					struct sctp_association *new_asoc){	sctp_init_chunk_t *peer_init;	struct sctp_chunk *repl;	/* new_asoc 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,			       sctp_source(chunk), peer_init,			       GFP_ATOMIC))		goto nomem;	/* Update the content of current association.  */	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, 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_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem;	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	/* 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.	 *	 * Sadly, this needs to be implemented as a side-effect, because	 * we are not guaranteed to have set the association id of the real	 * association and so these notifications need to be delayed until	 * the association id is allocated.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_CHANGE, SCTP_U8(SCTP_COMM_UP));	/* Sockets API Draft Section 5.3.1.6	 * When a peer sends a Adaptation Layer Indication parameter , SCTP	 * delivers this notification to inform the application that of the	 * peers requested adaptation layer.	 *	 * This also needs to be done as a side effect for the same reason as	 * above.	 */	if (asoc->peer.adaptation_ind)		sctp_add_cmd_sf(commands, SCTP_CMD_ADAPTATION_IND, SCTP_NULL());	return SCTP_DISPOSITION_CONSUME;nomem:	return SCTP_DISPOSITION_NOMEM;}/* Unexpected COOKIE-ECHO handler for setup collision (Table 2, action 'C') * * Section 5.2.4 *  C) In this case, the local endpoint's cookie has arrived late. *     Before it arrived, the local endpoint sent an INIT and received an *     INIT-ACK and finally sent a COOKIE ECHO with the peer's same tag *     but a new tag of its own. *//* This case represents an initialization collision.  */static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					struct sctp_chunk *chunk,					sctp_cmd_seq_t *commands,					struct sctp_association *new_asoc){	/* The cookie should be silently discarded.	 * The endpoint SHOULD NOT change states and should leave	 * any timers running.	 */	return SCTP_DISPOSITION_DISCARD;}/* Unexpected COOKIE-ECHO handler lost chunk (Table 2, action 'D') * * Section 5.2.4 * * D) When both local and remote tags match the endpoint should always *    enter the ESTABLISHED state, if it has not already done so. *//* This case represents an initialization collision.  */static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					struct sctp_chunk *chunk,					sctp_cmd_seq_t *commands,					struct sctp_association *new_asoc){	struct sctp_ulpevent *ev = NULL, *ai_ev = NULL;	struct sctp_chunk *repl;	/* Clarification from Implementor's Guide:	 * D) When both local and remote tags match the endpoint should	 * enter the ESTABLISHED state, if it is in the COOKIE-ECHOED state.	 * It should stop any cookie timer that may be running and send	 * a COOKIE ACK.	 */	/* Don't accidentally move back into established state. */	if (asoc->state < SCTP_STATE_ESTABLISHED) {		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_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START,				SCTP_NULL());		/* 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(asoc, 0,					     SCTP_COMM_UP, 0,					     asoc->c.sinit_num_ostreams,					     asoc->c.sinit_max_instreams,					     NULL, GFP_ATOMIC);		if (!ev)			goto nomem;		/* Sockets API Draft Section 5.3.1.6		 * When a peer sends a Adaptation Layer Indication parameter,		 * SCTP delivers this notification to inform the application		 * that of the peers requested adaptation layer.		 */		if (asoc->peer.adaptation_ind) {			ai_ev = sctp_ulpevent_make_adaptation_indication(asoc,								 GFP_ATOMIC);			if (!ai_ev)				goto nomem;		}	}	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem;	if (ev)		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,				SCTP_ULPEVENT(ev));	if (ai_ev)		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,					SCTP_ULPEVENT(ai_ev));	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	return SCTP_DISPOSITION_CONSUME;nomem:	if (ai_ev)		sctp_ulpevent_free(ai_ev);	if (ev)		sctp_ulpevent_free(ev);	return SCTP_DISPOSITION_NOMEM;}/* * Handle a duplicate COOKIE-ECHO.  This usually means a cookie-carrying * chunk was retransmitted and then delayed in the network. * * Section: 5.2.4 Handle a COOKIE ECHO when a TCB exists * * Verification Tag: None.  Do cookie validation. * * 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_2_4_dupcook(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands){	sctp_disposition_t retval;	struct sctp_chunk *chunk = arg;	struct sctp_association *new_asoc;	int error = 0;	char action;	struct sctp_chunk *err_chk_p;	/* Make sure that the chunk has a valid length from the protocol	 * perspective.  In this case check to make sure we have at least	 * enough for the chunk header.  Cookie length verification is	 * done later.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_violation_chunklen(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;	if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -					sizeof(sctp_chunkhdr_t)))		goto nomem;	/* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie	 * of a duplicate COOKIE ECHO match the Verification Tags of the	 * current association, consider the State Cookie valid even if	 * the lifespan is exceeded.	 */	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:

⌨️ 快捷键说明

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