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

📄 sm_statefuns.c

📁 在linux环境下的流控制传输协议(sctp)的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));	/* Queue the ASSOC_CHANGE event */	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));	/* Send up the Adaptation Layer Indication event */	if (ai_ev)		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,				SCTP_ULPEVENT(ai_ev));	return SCTP_DISPOSITION_CONSUME;nomem_aiev:	sctp_ulpevent_free(ev);nomem_ev:	sctp_chunk_free(repl);nomem_init:	sctp_association_free(new_asoc);nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Respond to a normal COOKIE ACK chunk. * We are the side that is being asked for an association. * * RFC 2960 5.1 Normal Establishment of an Association * * E) Upon reception of the COOKIE ACK, endpoint "A" will move from the *    COOKIE-ECHOED state to the ESTABLISHED state, stopping the T1-cookie *    timer. It may also notify its ULP about the successful *    establishment of the association with a Communication Up *    notification (see Section 10). * * Verification Tag: * 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_1E_ca(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_ulpevent *ev;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Verify that the chunk length for the COOKIE-ACK is OK.	 * If we don't do this, any bundled chunks may be junked.	 */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	/* Reset init error count upon receipt of COOKIE-ACK,	 * to avoid problems with the managemement of this	 * counter in stale cookie situations when a transition back	 * from the COOKIE-ECHOED state to the COOKIE-WAIT	 * state is performed.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL());	/* RFC 2960 5.1 Normal Establishment of an Association	 *	 * E) Upon reception of the COOKIE ACK, endpoint "A" will move	 * from the COOKIE-ECHOED state to the ESTABLISHED state,	 * stopping the T1-cookie timer.	 */	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_INC_STATS(SCTP_MIB_ACTIVEESTABS);	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL());	if (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());	/* It may also notify its ULP about the successful	 * establishment of the association with a Communication Up	 * notification (see Section 10).	 */	ev = sctp_ulpevent_make_assoc_change(asoc, 0, SCTP_COMM_UP,					     0, asoc->c.sinit_num_ostreams,					     asoc->c.sinit_max_instreams,					     NULL, 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 Adaptation Layer Indication parameter , SCTP	 * delivers this notification to inform the application that of the	 * peers requested adaptation layer.	 */	if (asoc->peer.adaptation_ind) {		ev = sctp_ulpevent_make_adaptation_indication(asoc, GFP_ATOMIC);		if (!ev)			goto nomem;		sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,				SCTP_ULPEVENT(ev));	}	return SCTP_DISPOSITION_CONSUME;nomem:	return SCTP_DISPOSITION_NOMEM;}/* Generate and sendout a heartbeat packet.  */static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep,					    const struct sctp_association *asoc,					    const sctp_subtype_t type,					    void *arg,					    sctp_cmd_seq_t *commands){	struct sctp_transport *transport = (struct sctp_transport *) arg;	struct sctp_chunk *reply;	sctp_sender_hb_info_t hbinfo;	size_t paylen = 0;	hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO;	hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t));	hbinfo.daddr = transport->ipaddr;	hbinfo.sent_at = jiffies;	hbinfo.hb_nonce = transport->hb_nonce;	/* Send a heartbeat to our peer.  */	paylen = sizeof(sctp_sender_hb_info_t);	reply = sctp_make_heartbeat(asoc, transport, &hbinfo, paylen);	if (!reply)		return SCTP_DISPOSITION_NOMEM;	/* Set rto_pending indicating that an RTT measurement	 * is started with this heartbeat chunk.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_RTO_PENDING,			SCTP_TRANSPORT(transport));	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));	return SCTP_DISPOSITION_CONSUME;}/* Generate a HEARTBEAT packet on the given transport.  */sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep,					const struct sctp_association *asoc,					const sctp_subtype_t type,					void *arg,					sctp_cmd_seq_t *commands){	struct sctp_transport *transport = (struct sctp_transport *) arg;	if (asoc->overall_error_count > asoc->max_retrans) {		sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,				SCTP_ERROR(ETIMEDOUT));		/* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */		sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,				SCTP_PERR(SCTP_ERROR_NO_ERROR));		SCTP_INC_STATS(SCTP_MIB_ABORTEDS);		SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);		return SCTP_DISPOSITION_DELETE_TCB;	}	/* Section 3.3.5.	 * The Sender-specific Heartbeat Info field should normally include	 * information about the sender's current time when this HEARTBEAT	 * chunk is sent and the destination transport address to which this	 * HEARTBEAT is sent (see Section 8.3).	 */	if (transport->param_flags & SPP_HB_ENABLE) {		if (SCTP_DISPOSITION_NOMEM ==				sctp_sf_heartbeat(ep, asoc, type, arg,						  commands))			return SCTP_DISPOSITION_NOMEM;		/* Set transport error counter and association error counter		 * when sending heartbeat.		 */		sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_RESET,				SCTP_TRANSPORT(transport));	}	sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMER_UPDATE,			SCTP_TRANSPORT(transport));	return SCTP_DISPOSITION_CONSUME;}/* * Process an heartbeat request. * * Section: 8.3 Path Heartbeat * The receiver of the HEARTBEAT should immediately respond with a * HEARTBEAT ACK that contains the Heartbeat Information field copied * from the received HEARTBEAT chunk. * * Verification Tag:  8.5 Verification Tag [Normal verification] * When receiving an SCTP packet, the endpoint MUST ensure that the * value in the Verification Tag field of the received SCTP packet * matches its own Tag. If the received Verification Tag value does not * match the receiver's own tag value, the receiver shall silently * discard the packet and shall not process it any further except for * those cases listed in Section 8.5.1 below. * * 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_beat_8_3(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_chunk *reply;	size_t paylen = 0;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the HEARTBEAT chunk has a valid length. */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	/* 8.3 The receiver of the HEARTBEAT should immediately	 * respond with a HEARTBEAT ACK that contains the Heartbeat	 * Information field copied from the received HEARTBEAT chunk.	 */	chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;	paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);	if (!pskb_pull(chunk->skb, paylen))		goto nomem;	reply = sctp_make_heartbeat_ack(asoc, chunk,					chunk->subh.hb_hdr, paylen);	if (!reply)		goto nomem;	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply));	return SCTP_DISPOSITION_CONSUME;nomem:	return SCTP_DISPOSITION_NOMEM;}/* * Process the returning HEARTBEAT ACK. * * Section: 8.3 Path Heartbeat * Upon the receipt of the HEARTBEAT ACK, the sender of the HEARTBEAT * should clear the error counter of the destination transport * address to which the HEARTBEAT was sent, and mark the destination * transport address as active if it is not so marked. The endpoint may * optionally report to the upper layer when an inactive destination * address is marked as active due to the reception of the latest * HEARTBEAT ACK. The receiver of the HEARTBEAT ACK must also * clear the association overall error count as well (as defined * in section 8.1). * * The receiver of the HEARTBEAT ACK should also perform an RTT * measurement for that destination transport address using the time * value carried in the HEARTBEAT ACK chunk. * * Verification Tag:  8.5 Verification Tag [Normal verification] * * 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_backbeat_8_3(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;	union sctp_addr from_addr;	struct sctp_transport *link;	sctp_sender_hb_info_t *hbinfo;	unsigned long max_interval;	if (!sctp_vtag_verify(chunk, asoc))		return sctp_sf_pdiscard(ep, asoc, type, arg, commands);	/* Make sure that the HEARTBEAT-ACK chunk has a valid length.  */	if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t)))		return sctp_sf_violation_chunklen(ep, asoc, type, arg,						  commands);	hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data;	/* Make sure that the length of the parameter is what we expect */	if (ntohs(hbinfo->param_hdr.length) !=				    sizeof(sctp_sender_hb_info_t)) {		return SCTP_DISPOSITION_DISCARD;	}	from_addr = hbinfo->daddr;	link = sctp_assoc_lookup_paddr(asoc, &from_addr);	/* This should never happen, but lets log it if so.  */	if (unlikely(!link)) {		if (from_addr.sa.sa_family == AF_INET6) {			if (net_ratelimit())				printk(KERN_WARNING				    "%s association %p could not find address "				    NIP6_FMT "\n",				    __FUNCTION__,				    asoc,				    NIP6(from_addr.v6.sin6_addr));		} else {			if (net_ratelimit())				printk(KERN_WARNING				    "%s association %p could not find address "				    NIPQUAD_FMT "\n",				    __FUNCTION__,				    asoc,				    NIPQUAD(from_addr.v4.sin_addr.s_addr));		}		return SCTP_DISPOSITION_DISCARD;	}	/* Validate the 64-bit random nonce. */	if (hbinfo->hb_nonce != link->hb_nonce)		return SCTP_DISPOSITION_DISCARD;	max_interval = link->hbinterval + link->rto;	/* Check if the timestamp looks valid.  */	if (time_after(hbinfo->sent_at, jiffies) ||	    time_after(jiffies, hbinfo->sent_at + max_interval)) {		SCTP_DEBUG_PRINTK("%s: HEARTBEAT ACK with invalid timestamp "				  "received for transport: %p\n",				   __FUNCTION__, link);		return SCTP_DISPOSITION_DISCARD;	}	/* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of	 * the HEARTBEAT should clear the error counter of the	 * destination transport address to which the HEARTBEAT was	 * sent and mark the destination transport address as active if	 * it is not so marked.	 */	sctp_add_cmd_sf(commands, SCTP_CMD_TRANSPORT_ON, SCTP_TRANSPORT(link));	return SCTP_DISPOSITION_CONSUME;}/* Helper function to send out an abort for the restart * condition. */static int sctp_sf_send_restart_abort(union sctp_addr *ssa,				      struct sctp_chunk *init,				      sctp_cmd_seq_t *commands){	int len;	struct sctp_packet *pkt;	union sctp_addr_param *addrparm;	struct sctp_errhdr *errhdr;	struct sctp_endpoint *ep;	char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)];	struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family);	/* Build the error on the stack.   We are way to malloc crazy	 * throughout the code today.	 */	errhdr = (struct sctp_errhdr *)buffer;	addrparm = (union sctp_addr_param *)errhdr->variable;	/* Copy into a parm format. */	len = af->to_addr_param(ssa, addrparm);	len += sizeof(sctp_errhdr_t);	errhdr->cause = SCTP_ERROR_RESTART;	errhdr->length = htons(len);	/* Assign to the control socket. */	ep = sctp_sk((sctp_get_ctl_sock()))->ep;	/* Association is NULL since this may be a restart attack and we	 * want to send back the attacker's vtag.

⌨️ 快捷键说明

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