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

📄 sm_statefuns.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 */	pkt = sctp_abort_pkt_new(ep, NULL, init, errhdr, len);	if (!pkt)		goto out;	sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt));	SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);	/* Discard the rest of the inbound packet. */	sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());out:	/* Even if there is no memory, treat as a failure so	 * the packet will get dropped.	 */	return 0;}/* A restart is occurring, check to make sure no new addresses * are being added as we may be under a takeover attack. */static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,				       const struct sctp_association *asoc,				       struct sctp_chunk *init,				       sctp_cmd_seq_t *commands){	struct sctp_transport *new_addr, *addr;	struct list_head *pos, *pos2;	int found;	/* Implementor's Guide - Sectin 5.2.2	 * ...	 * Before responding the endpoint MUST check to see if the	 * unexpected INIT adds new addresses to the association. If new	 * addresses are added to the association, the endpoint MUST respond	 * with an ABORT..	 */	/* Search through all current addresses and make sure	 * we aren't adding any new ones.	 */	new_addr = NULL;	found = 0;	list_for_each(pos, &new_asoc->peer.transport_addr_list) {		new_addr = list_entry(pos, struct sctp_transport, transports);		found = 0;		list_for_each(pos2, &asoc->peer.transport_addr_list) {			addr = list_entry(pos2, struct sctp_transport,					  transports);			if (sctp_cmp_addr_exact(&new_addr->ipaddr,						&addr->ipaddr)) {				found = 1;				break;			}		}		if (!found)			break;	}	/* If a new address was added, ABORT the sender. */	if (!found && new_addr) {		sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands);	}	/* Return success if all addresses were found. */	return found;}/* Populate the verification/tie tags based on overlapping INIT * scenario. * * Note: Do not use in CLOSED or SHUTDOWN-ACK-SENT state. */static void sctp_tietags_populate(struct sctp_association *new_asoc,				  const struct sctp_association *asoc){	switch (asoc->state) {	/* 5.2.1 INIT received in COOKIE-WAIT or COOKIE-ECHOED State */	case SCTP_STATE_COOKIE_WAIT:		new_asoc->c.my_vtag     = asoc->c.my_vtag;		new_asoc->c.my_ttag     = asoc->c.my_vtag;		new_asoc->c.peer_ttag   = 0;		break;	case SCTP_STATE_COOKIE_ECHOED:		new_asoc->c.my_vtag     = asoc->c.my_vtag;		new_asoc->c.my_ttag     = asoc->c.my_vtag;		new_asoc->c.peer_ttag   = asoc->c.peer_vtag;		break;	/* 5.2.2 Unexpected INIT in States Other than CLOSED, COOKIE-ECHOED,	 * COOKIE-WAIT and SHUTDOWN-ACK-SENT	 */	default:		new_asoc->c.my_ttag   = asoc->c.my_vtag;		new_asoc->c.peer_ttag = asoc->c.peer_vtag;		break;	}	/* 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.	 */	new_asoc->rwnd                  = asoc->rwnd;	new_asoc->c.sinit_num_ostreams  = asoc->c.sinit_num_ostreams;	new_asoc->c.sinit_max_instreams = asoc->c.sinit_max_instreams;	new_asoc->c.initial_tsn         = asoc->c.initial_tsn;}/* * Compare vtag/tietag values to determine unexpected COOKIE-ECHO * handling action. * * RFC 2960 5.2.4 Handle a COOKIE ECHO when a TCB exists. * * Returns value representing action to be taken.   These action values * correspond to Action/Description values in RFC 2960, Table 2. */static char sctp_tietags_compare(struct sctp_association *new_asoc,				 const struct sctp_association *asoc){	/* In this case, the peer may have restarted.  */	if ((asoc->c.my_vtag != new_asoc->c.my_vtag) &&	    (asoc->c.peer_vtag != new_asoc->c.peer_vtag) &&	    (asoc->c.my_vtag == new_asoc->c.my_ttag) &&	    (asoc->c.peer_vtag == new_asoc->c.peer_ttag))		return 'A';	/* Collision case B. */	if ((asoc->c.my_vtag == new_asoc->c.my_vtag) &&	    ((asoc->c.peer_vtag != new_asoc->c.peer_vtag) ||	     (0 == asoc->c.peer_vtag))) {		return 'B';	}	/* Collision case D. */	if ((asoc->c.my_vtag == new_asoc->c.my_vtag) &&	    (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))		goto nomem;	/* 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 nomem_retval;		}	}	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;	return retval;nomem:	retval = SCTP_DISPOSITION_NOMEM;nomem_retval:	if (new_asoc)		sctp_association_free(new_asoc);cleanup:	if (err_chunk)		sctp_chunk_free(err_chunk);	return retval;}/* * 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

⌨️ 快捷键说明

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