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

📄 sm_statefuns.c

📁 一种在UDP协议中实现了拥赛控制和重传机制的协议
💻 C
📖 第 1 页 / 共 5 页
字号:
	 */	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.	 */	ev = sctp_ulpevent_make_assoc_change(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 (asoc->peer.adaption_ind) {		ev = sctp_ulpevent_make_adaption_indication(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:	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;	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(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;		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;			sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,					SCTP_ULPEVENT(ev));		}	}	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, 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());	return SCTP_DISPOSITION_CONSUME;nomem:	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;	skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) -		 sizeof(sctp_chunkhdr_t));	/* 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:			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);		};	}	/* Compare the tie_tag in cookie with the verification tag of	 * current association.	 */	action = sctp_tietags_compare(new_asoc, asoc);	switch (action) {	case 'A': /* Association restart. */		retval = sctp_sf_do_dupcook_a(ep, asoc, chunk, commands,					      new_asoc);		break;	case 'B': /* Collision case B. */		retval = sctp_sf_do_dupcook_b(ep, asoc, chunk, commands,					      new_asoc);		break;	case 'C': /* Collision case C. */		retval = sctp_sf_do_dupcook_c(ep, asoc, chunk, commands,					      new_asoc);		break;	case 'D': /* Collision case D. */		retval = sctp_sf_do_dupcook_d(ep, asoc, chunk, commands,					      new_asoc);		break;	default: /* Discard packet for all others. */		retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands);		break;        };	/* Delete the tempory new association. */	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());	return retval;nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Process an ABORT.  (SHUTDOWN-PENDING state) * * See sctp_sf_do_9_1_abort(). */sctp_disposition_t sctp_sf_shutdown_pending_abort(	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;	if (!sctp_vtag_verify_either(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the ABORT chunk has a valid length.	 * Since this is an ABORT chunk, we have to discard it	 * because of the following text:	 * RFC 2960, Section 3.3.7	 *    If an endpoint receives an ABORT with a format error or for an	 *    association that doesn't exist, it MUST silently discard it.	 * Becasue the length is "invalid", we can't really discard just	 * as we do not know its true length.  So, to be safe, discard the	 * packet.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Stop the T5-shutdown guard timer.  */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));	return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);}/* * Process an ABORT.  (SHUTDOWN-SENT state) * * See sctp_sf_do_9_1_abort(). */sctp_disposition_t sctp_sf_shutdown_sent_abort(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;	if (!sctp_vtag_verify_either(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the ABORT chunk has a valid length.	 * Since this is an ABORT chunk, we have to discard it	 * because of the following text:	 * RFC 2960, Section 3.3.7	 *    If an endpoint receives an ABORT with a format error or for an	 *    association that doesn't exist, it MUST silently discard it.	 * Becasue the length is "invalid", we can't really discard just	 * as we do not know its true length.  So, to be safe, discard the	 * packet.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t)))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Stop the T2-shutdown timer. */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));	/* Stop the T5-shutdown guard timer.  */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD));	return sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands);}/* * Process an ABORT.  (SHUTDOWN-ACK-SENT state) * * See sctp_sf_do_9_1_abort(). */sctp_disposition_t sctp_sf_shutdown_ack_sent_abort(	const struct sctp_endpoint *ep,	const struct sctp_association *asoc,	const sctp_subtype_t type,	void *arg,	sctp_cmd_seq_t *commands){	/* The same T2 timer, so we should be able to use	 * common function with the SHUTDOWN-SENT state.	 */	return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands);}/* * Handle an Error received in COOKIE_ECHOED state. * * Only handle the error type of stale COOKIE Error, the other errors will * be ignored. * * 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_cookie_echoed_err(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_errhdr_t *err;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the ERROR chunk has a valid length.	 * The parameter walking depends on this as well.	 */	if (!sctp_chunk_length_valid(ch

⌨️ 快捷键说明

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