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

📄 sm_statefuns.c

📁 一种在UDP协议中实现了拥赛控制和重传机制的协议
💻 C
📖 第 1 页 / 共 5 页
字号:
	    (asoc->c.peer_vtag == new_asoc->c.peer_vtag))		return 'D';	/* Collision case C. */	if ((asoc->c.my_vtag != new_asoc->c.my_vtag) &&	    (asoc->c.peer_vtag == new_asoc->c.peer_vtag) &&	    (0 == new_asoc->c.my_ttag) &&	    (0 == new_asoc->c.peer_ttag))		return 'C';	/* No match to any of the special cases; discard this packet. */	return 'E';}/* Common helper routine for both duplicate and simulataneous INIT * chunk handling. */static sctp_disposition_t sctp_sf_do_unexpected_init(	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_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);	/* 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.	 * In this case, we generate a protocol violation since we have	 * an association established.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t)))		return sctp_sf_violation_chunklen(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));	/* 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));			if (packet) {				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,						SCTP_PACKET(packet));				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);				retval = SCTP_DISPOSITION_CONSUME;			} else {				retval = SCTP_DISPOSITION_NOMEM;			}			goto cleanup;		} else {			return sctp_sf_tabort_8_4_8(ep, asoc, type, arg,						    commands);		}	}	/*	 * Other parameters for the endpoint SHOULD be copied from the	 * existing parameters of the association (e.g. number of	 * outbound streams) into the INIT ACK and cookie.	 * FIXME:  We are copying parameters from the endpoint not the	 * association.	 */	new_asoc = sctp_make_temp_asoc(ep, chunk, GFP_ATOMIC);	if (!new_asoc)		goto nomem;	/* In the outbound INIT ACK the endpoint MUST copy its current	 * Verification Tag and Peers Verification tag into a reserved	 * place (local tie-tag and per tie-tag) within the state cookie.	 */	if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type,			       sctp_source(chunk),			       (sctp_init_chunk_t *)chunk->chunk_hdr,			       GFP_ATOMIC)) {		retval = SCTP_DISPOSITION_NOMEM;		goto nomem_init;	}	/* Make sure no new addresses are being added during the	 * restart.   Do not do this check for COOKIE-WAIT state,	 * since there are no peer addresses to check against.	 * Upon return an ABORT will have been sent if needed.	 */	if (!sctp_state(asoc, COOKIE_WAIT)) {		if (!sctp_sf_check_restart_addrs(new_asoc, asoc, chunk,						 commands)) {			retval = SCTP_DISPOSITION_CONSUME;			goto cleanup_asoc;		}	}	sctp_tietags_populate(new_asoc, asoc);	/* 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;	repl = sctp_make_init_ack(new_asoc, chunk, GFP_ATOMIC, len);	if (!repl)		goto nomem;	/* If there are errors need to be reported for unknown parameters,	 * include them in the outgoing INIT ACK as "Unrecognized parameter"	 * parameter.	 */	if (err_chunk) {		/* Get the "Unrecognized parameter" parameter(s) out of the		 * ERROR chunk generated by sctp_verify_init(). Since the		 * error cause code for "unknown parameter" and the		 * "Unrecognized parameter" type is the same, we can		 * construct the parameters in INIT ACK by copying the		 * ERROR causes over.		 */		unk_param = (sctp_unrecognized_param_t *)			    ((__u8 *)(err_chunk->chunk_hdr) +			    sizeof(sctp_chunkhdr_t));		/* Replace the cause code with the "Unrecognized parameter"		 * parameter type.		 */		sctp_addto_chunk(repl, len, unk_param);	}	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	/*	 * Note: After sending out INIT ACK with the State Cookie parameter,	 * "Z" MUST NOT allocate any resources for this new association.	 * Otherwise, "Z" will be vulnerable to resource attacks.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());	retval = SCTP_DISPOSITION_CONSUME;cleanup:	if (err_chunk)		sctp_chunk_free(err_chunk);	return retval;nomem:	retval = SCTP_DISPOSITION_NOMEM;	goto cleanup;nomem_init:cleanup_asoc:	sctp_association_free(new_asoc);	goto cleanup;}/* * Handle simultanous INIT. * This means we started an INIT and then we got an INIT request from * our peer. * * Section: 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State (Item B) * This usually indicates an initialization collision, i.e., each * endpoint is attempting, at about the same time, to establish an * association with the other endpoint. * * Upon receipt of an INIT in the COOKIE-WAIT or COOKIE-ECHOED state, an * endpoint MUST respond with an INIT ACK using the same parameters it * sent in its original INIT chunk (including its Verification Tag, * unchanged). These original parameters are combined with those from the * newly received INIT chunk. The endpoint shall also generate a State * Cookie with the INIT ACK. The endpoint uses the parameters sent in its * INIT to calculate the State Cookie. * * After that, the endpoint MUST NOT change its state, the T1-init * timer shall be left running and the corresponding TCB MUST NOT be * destroyed. The normal procedures for handling State Cookies when * a TCB exists will resolve the duplicate INITs to a single association. * * For an endpoint that is in the COOKIE-ECHOED state it MUST populate * its Tie-Tags with the Tag information of itself and its peer (see * section 5.2.2 for a description of the Tie-Tags). * * Verification Tag: Not explicit, but an INIT can not have a valid * verification tag, so we skip the check. * * 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_1_siminit(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);}/* * Handle duplicated INIT messages.  These are usually delayed * restransmissions. * * Section: 5.2.2 Unexpected INIT in States Other than CLOSED, * COOKIE-ECHOED and COOKIE-WAIT * * Unless otherwise stated, upon reception of an unexpected INIT for * this association, the endpoint shall generate an INIT ACK with a * State Cookie.  In the outbound INIT ACK the endpoint MUST copy its * current Verification Tag and peer's Verification Tag into a reserved * place within the state cookie.  We shall refer to these locations as * the Peer's-Tie-Tag and the Local-Tie-Tag.  The outbound SCTP packet * containing this INIT ACK MUST carry a Verification Tag value equal to * the Initiation Tag found in the unexpected INIT.  And the INIT ACK * MUST contain a new Initiation Tag (randomly generated see Section * 5.3.1).  Other parameters for the endpoint SHOULD be copied from the * 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 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());	/* Update the content of current association. */	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem;	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	/* 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,					     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 '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_ulpevent *ev;	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.

⌨️ 快捷键说明

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