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

📄 sm_statefuns.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
					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;	/* "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);	/* 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);	/* 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;	/* Process the error here */	/* FUTURE FIXME:  When PR-SCTP related and other optional	 * parms are emitted, this will have to change to handle multiple	 * errors.	 */	sctp_walk_errors(err, chunk->chunk_hdr) {		if (SCTP_ERROR_STALE_COOKIE == err->cause)			return sctp_sf_do_5_2_6_stale(ep, asoc, type, 							arg, commands);	}	return sctp_sf_pdiscard(ep, asoc, type, arg, commands);}/* * Handle a Stale COOKIE Error * * Section: 5.2.6 Handle Stale COOKIE Error * If the association is in the COOKIE-ECHOED state, the endpoint may elect * one of the following three alternatives. * ... * 3) Send a new INIT chunk to the endpoint, adding a Cookie *    Preservative parameter requesting an extension to the lifetime of *    the State Cookie. When calculating the time extension, an *    implementation SHOULD use the RTT information measured based on the *    previous COOKIE ECHO / ERROR exchange, and should add no more *    than 1 second beyond the measured RTT, due to long State Cookie *    lifetimes making the endpoint more subject to a replay attack. * * Verification Tag:  Not explicit, but safe to ignore. * * 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_6_stale(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;	time_t stale;	sctp_cookie_preserve_param_t bht;	sctp_errhdr_t *err;	struct sctp_chunk *reply;	struct sctp_bind_addr *bp;	int attempts;	attempts = asoc->counters[SCTP_COUNTER_INIT_ERROR] + 1;	if (attempts >= asoc->max_init_attempts) {		sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,				SCTP_U32(SCTP_ERROR_STALE_COOKIE));		return SCTP_DISPOSITION_DELETE_TCB;	}	err = (sctp_errhdr_t *)(chunk->skb->data);	/* When calculating the time extension, an implementation	 * SHOULD use the RTT information measured based on the	 * previous COOKIE ECHO / ERROR exchange, and should add no	 * more than 1 second beyond the measured RTT, due to long	 * State Cookie lifetimes making the endpoint more subject to	 * a replay attack.	 * Measure of Staleness's unit is usec. (1/1000000 sec)	 * Suggested Cookie Life-span Increment's unit is msec.	 * (1/1000 sec)	 * In general, if you use the suggested cookie life, the value	 * found in the field of measure of staleness should be doubled	 * to give ample time to retransmit the new cookie and thus	 * yield a higher probability of success on the reattempt.	 */	stale = ntohl(*(suseconds_t *)((u8 *)err + sizeof(sctp_errhdr_t)));	stale = (stale * 2) / 1000;	bht.param_hdr.type = SCTP_PARAM_COOKIE_PRESERVATIVE;	bht.param_hdr.length = htons(sizeof(bht));	bht.lifespan_increment = htonl(stale);	/* Build that new INIT chunk.  */	bp = (struct sctp_bind_addr *) &asoc->base.bind_addr;	reply = sctp_make_init(asoc, bp, GFP_ATOMIC, sizeof(bht));	if (!reply)		goto nomem;	sctp_addto_chunk(reply, sizeof(bht), &bht);	/* Clear peer's init_tag cached in assoc as we are sending a new INIT */	sctp_add_cmd_sf(commands, SCTP_CMD_CLEAR_INIT_TAG, SCTP_NULL());	/* Stop pending T3-rtx and heartbeat timers */	sctp_add_cmd_sf(commands, SCTP_CMD_T3_RTX_TIMERS_STOP, SCTP_NULL());	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_STOP, SCTP_NULL());	/* Delete non-primary peer ip addresses since we are transitioning	 * back to the COOKIE-WAIT state	 */	sctp_add_cmd_sf(commands, SCTP_CMD_DEL_NON_PRIMARY, SCTP_NULL());	/* If we've sent any data bundled with COOKIE-ECHO we will need to 	 * resend 	 */	sctp_add_cmd_sf(commands, SCTP_CMD_RETRAN, 			SCTP_TRANSPORT(asoc->peer.primary_path));	/* Cast away the const modifier, as we want to just	 * rerun it through as a sideffect.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_COUNTER_INC,			SCTP_COUNTER(SCTP_COUNTER_INIT_ERROR));	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_COOKIE_WAIT));	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));	return SCTP_DISPOSITION_CONSUME;nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Process an ABORT. * * Section: 9.1 * After checking the Verification Tag, the receiving endpoint shall * remove the association from its record, and shall report the * termination to its upper layer. * * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules * B) Rules for packet carrying ABORT: * *  - The endpoint shall always fill in the Verification Tag field of the *    outbound packet with the destination endpoint's tag value if it *    is known. * *  - If the ABORT is sent in response to an OOTB packet, the endpoint *    MUST follow the procedure described in Section 8.4. * *  - The receiver MUST accept the packet if the Verification Tag *    matches either its own tag, OR the tag of its peer. Otherwise, the *    receiver MUST silently discard the packet and take no further *    action. * * 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_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){	struct sctp_chunk *chunk = arg;	unsigned len;	__u16 error = SCTP_ERROR_NO_ERROR;	if (!sctp_vtag_verify_either(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Check that chunk header looks valid.  */	len = ntohs(chunk->chunk_hdr->length);	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))		error = ((sctp_errhdr_t *)chunk->skb->data)->cause; 	/* ASSOC_FAILED will DELETE_TCB. */	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_U32(error));	SCTP_INC_STATS(SCTP_MIB_ABORTEDS);	SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);	return SCTP_DISPOSITION_ABORT;}/* * Process an ABORT.  (COOKIE-WAIT state) * * See sctp_sf_do_9_1_abort() above. */sctp_disposition_t sctp_sf_cookie_wait_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;	unsigned len;	__u16 error = SCTP_ERROR_NO_ERROR;	if (!sctp_vtag_verify_either(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	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_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));	/* Check that chunk header looks valid.  */	len = ntohs(chunk->chunk_hdr->length);	if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr))		error = ((sctp_errhdr_t *)chunk->skb->data)->cause;	/* CMD_INIT_FAILED will DELETE_TCB. */	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED, SCTP_U32(error));	return SCTP_DISPOSITION_ABORT;}/* * Process an ABORT.  (COOKIE-ECHOED state) * * See sctp_sf_do_9_1_abort() above. */sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep,					       const struct sctp_association *asoc,					       const sctp_subtype_t type,					       void *

⌨️ 快捷键说明

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