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

📄 sm_statefuns.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * 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_chunk_free(err_chunk);	}	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, nor keep any states for the	 * new association.  Otherwise, "Z" will be vulnerable to resource	 * attacks.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());	return SCTP_DISPOSITION_DELETE_TCB;nomem_init:	sctp_association_free(new_asoc);nomem:	if (err_chunk)		sctp_chunk_free(err_chunk);	return SCTP_DISPOSITION_NOMEM;}/* * Respond to a normal INIT ACK chunk. * We are the side that is initiating the association. * * Section: 5.1 Normal Establishment of an Association, C * C) Upon reception of the INIT ACK from "Z", "A" shall stop the T1-init *    timer and leave COOKIE-WAIT state. "A" shall then send the State *    Cookie received in the INIT ACK chunk in a COOKIE ECHO chunk, start *    the T1-cookie timer, and enter the COOKIE-ECHOED state. * *    Note: The COOKIE ECHO chunk can be bundled with any pending outbound *    DATA chunks, but it MUST be the first chunk in the packet and *    until the COOKIE ACK is returned the sender MUST NOT send any *    other packets to the peer. * * Verification Tag: 3.3.3 *   If the value of the Initiate Tag in a received INIT ACK chunk is *   found to be 0, the receiver MUST treat it as an error and close the *   association by transmitting an ABORT. * * 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_1C_ack(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_init_chunk_t *initchunk;	struct sctp_chunk *err_chunk;	struct sctp_packet *packet;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* 6.10 Bundling	 * An endpoint MUST NOT bundle INIT, INIT ACK or	 * SHUTDOWN COMPLETE with any other chunks.	 */	if (!chunk->singleton)		return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);	/* Make sure that the INIT-ACK chunk has a valid length */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_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;	/* 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)) {		sctp_error_t error = SCTP_ERROR_NO_RESOURCE;		/* This chunk contains fatal error. It is to be discarded.		 * Send an ABORT, with causes.  If there are no causes,		 * then there wasn't enough memory.  Just terminate		 * the association.		 */		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));			sctp_chunk_free(err_chunk);			if (packet) {				sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,						SCTP_PACKET(packet));				SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);				error = SCTP_ERROR_INV_PARAM;			}		}		/* SCTP-AUTH, Section 6.3:		 *    It should be noted that if the receiver wants to tear		 *    down an association in an authenticated way only, the		 *    handling of malformed packets should not result in		 *    tearing down the association.		 *		 * This means that if we only want to abort associations		 * in an authenticated way (i.e AUTH+ABORT), then we		 * can't destroy this association just becuase the packet		 * was malformed.		 */		if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);		return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED,						asoc, chunk->transport);	}	/* Tag the variable length parameters.  Note that we never	 * convert the parameters in an INIT chunk.	 */	chunk->param_hdr.v = skb_pull(chunk->skb, sizeof(sctp_inithdr_t));	initchunk = (sctp_init_chunk_t *) chunk->chunk_hdr;	sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT,			SCTP_PEER_INIT(initchunk));	/* Reset init error count upon receipt of INIT-ACK.  */	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());	/* 5.1 C) "A" shall stop the T1-init timer and leave	 * COOKIE-WAIT state.  "A" shall then ... start the T1-cookie	 * timer, and enter the COOKIE-ECHOED state.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));	sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,			SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE));	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,			SCTP_STATE(SCTP_STATE_COOKIE_ECHOED));	/* SCTP-AUTH: genereate the assocition shared keys so that	 * we can potentially signe the COOKIE-ECHO.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL());	/* 5.1 C) "A" shall then send the State Cookie received in the	 * INIT ACK chunk in a COOKIE ECHO chunk, ...	 */	/* If there is any errors to report, send the ERROR chunk generated	 * for unknown parameters as well.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_GEN_COOKIE_ECHO,			SCTP_CHUNK(err_chunk));	return SCTP_DISPOSITION_CONSUME;}/* * Respond to a normal COOKIE ECHO chunk. * We are the side that is being asked for an association. * * Section: 5.1 Normal Establishment of an Association, D * D) Upon reception of the COOKIE ECHO chunk, Endpoint "Z" will reply *    with a COOKIE ACK chunk after building a TCB and moving to *    the ESTABLISHED state. A COOKIE ACK chunk may be bundled with *    any pending DATA chunks (and/or SACK chunks), but the COOKIE ACK *    chunk MUST be the first chunk in the packet. * *   IMPLEMENTATION NOTE: An implementation may choose to send the *   Communication Up notification to the SCTP user upon reception *   of a valid COOKIE ECHO chunk. * * Verification Tag: 8.5.1 Exceptions in Verification Tag Rules * D) Rules for packet carrying a COOKIE ECHO * * - When sending a COOKIE ECHO, the endpoint MUST use the value of the *   Initial Tag received in the INIT ACK. * * - The receiver of a COOKIE ECHO follows the procedures in Section 5. * * 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_1D_ce(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;	struct sctp_association *new_asoc;	sctp_init_chunk_t *peer_init;	struct sctp_chunk *repl;	struct sctp_ulpevent *ev, *ai_ev = NULL;	int error = 0;	struct sctp_chunk *err_chk_p;	struct sock *sk;	/* If the packet is an OOTB packet which is temporarily on the	 * control endpoint, respond with an ABORT.	 */	if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)		return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);	/* Make sure that the COOKIE_ECHO chunk has a valid length.	 * In this case, we check that we have enough for at least a	 * chunk header.  More detailed verification is done	 * in sctp_unpack_cookie().	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* If the endpoint is not listening or if the number of associations	 * on the TCP-style socket exceed the max backlog, respond with an	 * ABORT.	 */	sk = ep->base.sk;	if (!sctp_sstate(sk, LISTENING) ||	    (sctp_style(sk, TCP) && sk_acceptq_is_full(sk)))		return sctp_sf_tabort_8_4_8(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;	/* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint	 * "Z" will reply with a COOKIE ACK chunk after building a TCB	 * and moving to the ESTABLISHED state.	 */	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);		}	}	/* Delay state machine commands until later.	 *	 * Re-build the bind address for the association is done in	 * the sctp_unpack_cookie() already.	 */	/* This 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,			       &chunk->subh.cookie_hdr->c.peer_addr,			       peer_init, GFP_ATOMIC))		goto nomem_init;	/* SCTP-AUTH:  Now that we've populate required fields in	 * sctp_process_init, set up the assocaition shared keys as	 * necessary so that we can potentially authenticate the ACK	 */	error = sctp_auth_asoc_init_active_key(new_asoc, GFP_ATOMIC);	if (error)		goto nomem_init;	/* SCTP-AUTH:  auth_chunk pointer is only set when the cookie-echo	 * is supposed to be authenticated and we have to do delayed	 * authentication.  We've just recreated the association using	 * the information in the cookie and now it's much easier to	 * do the authentication.	 */	if (chunk->auth_chunk) {		struct sctp_chunk auth;		sctp_ierror_t ret;		/* set-up our fake chunk so that we can process it */		auth.skb = chunk->auth_chunk;		auth.asoc = chunk->asoc;		auth.sctp_hdr = chunk->sctp_hdr;		auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,					    sizeof(sctp_chunkhdr_t));		skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));		auth.transport = chunk->transport;		ret = sctp_sf_authenticate(ep, new_asoc, type, &auth);		/* We can now safely free the auth_chunk clone */		kfree_skb(chunk->auth_chunk);		if (ret != SCTP_IERROR_NO_ERROR) {			sctp_association_free(new_asoc);			return sctp_sf_pdiscard(ep, asoc, type, arg, commands);		}	}	repl = sctp_make_cookie_ack(new_asoc, chunk);	if (!repl)		goto nomem_init;	/* 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,					     NULL, GFP_ATOMIC);	if (!ev)		goto nomem_ev;	/* 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 (new_asoc->peer.adaptation_ind) {		ai_ev = sctp_ulpevent_make_adaptation_indication(new_asoc,							    GFP_ATOMIC);		if (!ai_ev)			goto nomem_aiev;	}	/* Add all the state machine commands now since we've created	 * everything.  This way we don't introduce memory corruptions	 * during side-effect processing and correclty count established	 * associations.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, 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_INC_STATS(SCTP_MIB_PASSIVEESTABS);	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());	if (new_asoc->autoclose)		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START,				SCTP_TO(SCTP_EVENT_TIMEOUT_AUTOCLOSE));	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSMIT, SCTP_NULL());	/* This will send the COOKIE ACK */

⌨️ 快捷键说明

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