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

📄 input.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  net/dccp/input.c * *  An implementation of the DCCP protocol *  Arnaldo Carvalho de Melo <acme@conectiva.com.br> * *	This program is free software; you can redistribute it and/or *	modify it under the terms of the GNU General Public License *	as published by the Free Software Foundation; either version *	2 of the License, or (at your option) any later version. */#include <linux/dccp.h>#include <linux/skbuff.h>#include <net/sock.h>#include "ackvec.h"#include "ccid.h"#include "dccp.h"/* rate-limit for syncs in reply to sequence-invalid packets; RFC 4340, 7.5.4 */int sysctl_dccp_sync_ratelimit	__read_mostly = HZ / 8;static void dccp_fin(struct sock *sk, struct sk_buff *skb){	sk->sk_shutdown |= RCV_SHUTDOWN;	sock_set_flag(sk, SOCK_DONE);	__skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4);	__skb_queue_tail(&sk->sk_receive_queue, skb);	skb_set_owner_r(skb, sk);	sk->sk_data_ready(sk, 0);}static void dccp_rcv_close(struct sock *sk, struct sk_buff *skb){	dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED);	dccp_fin(sk, skb);	dccp_set_state(sk, DCCP_CLOSED);	sk_wake_async(sk, 1, POLL_HUP);}static void dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb){	/*	 *   Step 7: Check for unexpected packet types	 *      If (S.is_server and P.type == CloseReq)	 *	  Send Sync packet acknowledging P.seqno	 *	  Drop packet and return	 */	if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) {		dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC);		return;	}	if (sk->sk_state != DCCP_CLOSING)		dccp_set_state(sk, DCCP_CLOSING);	dccp_send_close(sk, 0);}static u8 dccp_reset_code_convert(const u8 code){	const u8 error_code[] = {	[DCCP_RESET_CODE_CLOSED]	     = 0,	/* normal termination */	[DCCP_RESET_CODE_UNSPECIFIED]	     = 0,	/* nothing known */	[DCCP_RESET_CODE_ABORTED]	     = ECONNRESET,	[DCCP_RESET_CODE_NO_CONNECTION]	     = ECONNREFUSED,	[DCCP_RESET_CODE_CONNECTION_REFUSED] = ECONNREFUSED,	[DCCP_RESET_CODE_TOO_BUSY]	     = EUSERS,	[DCCP_RESET_CODE_AGGRESSION_PENALTY] = EDQUOT,	[DCCP_RESET_CODE_PACKET_ERROR]	     = ENOMSG,	[DCCP_RESET_CODE_BAD_INIT_COOKIE]    = EBADR,	[DCCP_RESET_CODE_BAD_SERVICE_CODE]   = EBADRQC,	[DCCP_RESET_CODE_OPTION_ERROR]	     = EILSEQ,	[DCCP_RESET_CODE_MANDATORY_ERROR]    = EOPNOTSUPP,	};	return code >= DCCP_MAX_RESET_CODES ? 0 : error_code[code];}static void dccp_rcv_reset(struct sock *sk, struct sk_buff *skb){	u8 err = dccp_reset_code_convert(dccp_hdr_reset(skb)->dccph_reset_code);	sk->sk_err = err;	/* Queue the equivalent of TCP fin so that dccp_recvmsg exits the loop */	dccp_fin(sk, skb);	if (err && !sock_flag(sk, SOCK_DEAD))		sk_wake_async(sk, 0, POLL_ERR);	dccp_time_wait(sk, DCCP_TIME_WAIT, 0);}static void dccp_event_ack_recv(struct sock *sk, struct sk_buff *skb){	struct dccp_sock *dp = dccp_sk(sk);	if (dccp_msk(sk)->dccpms_send_ack_vector)		dccp_ackvec_check_rcv_ackno(dp->dccps_hc_rx_ackvec, sk,					    DCCP_SKB_CB(skb)->dccpd_ack_seq);}static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb){	const struct dccp_hdr *dh = dccp_hdr(skb);	struct dccp_sock *dp = dccp_sk(sk);	u64 lswl, lawl, seqno = DCCP_SKB_CB(skb)->dccpd_seq,			ackno = DCCP_SKB_CB(skb)->dccpd_ack_seq;	/*	 *   Step 5: Prepare sequence numbers for Sync	 *     If P.type == Sync or P.type == SyncAck,	 *	  If S.AWL <= P.ackno <= S.AWH and P.seqno >= S.SWL,	 *	     / * P is valid, so update sequence number variables	 *		 accordingly.  After this update, P will pass the tests	 *		 in Step 6.  A SyncAck is generated if necessary in	 *		 Step 15 * /	 *	     Update S.GSR, S.SWL, S.SWH	 *	  Otherwise,	 *	     Drop packet and return	 */	if (dh->dccph_type == DCCP_PKT_SYNC ||	    dh->dccph_type == DCCP_PKT_SYNCACK) {		if (between48(ackno, dp->dccps_awl, dp->dccps_awh) &&		    dccp_delta_seqno(dp->dccps_swl, seqno) >= 0)			dccp_update_gsr(sk, seqno);		else			return -1;	}	/*	 *   Step 6: Check sequence numbers	 *      Let LSWL = S.SWL and LAWL = S.AWL	 *      If P.type == CloseReq or P.type == Close or P.type == Reset,	 *	  LSWL := S.GSR + 1, LAWL := S.GAR	 *      If LSWL <= P.seqno <= S.SWH	 *	     and (P.ackno does not exist or LAWL <= P.ackno <= S.AWH),	 *	  Update S.GSR, S.SWL, S.SWH	 *	  If P.type != Sync,	 *	     Update S.GAR	 */	lswl = dp->dccps_swl;	lawl = dp->dccps_awl;	if (dh->dccph_type == DCCP_PKT_CLOSEREQ ||	    dh->dccph_type == DCCP_PKT_CLOSE ||	    dh->dccph_type == DCCP_PKT_RESET) {		lswl = ADD48(dp->dccps_gsr, 1);		lawl = dp->dccps_gar;	}	if (between48(seqno, lswl, dp->dccps_swh) &&	    (ackno == DCCP_PKT_WITHOUT_ACK_SEQ ||	     between48(ackno, lawl, dp->dccps_awh))) {		dccp_update_gsr(sk, seqno);		if (dh->dccph_type != DCCP_PKT_SYNC &&		    (ackno != DCCP_PKT_WITHOUT_ACK_SEQ))			dp->dccps_gar = ackno;	} else {		unsigned long now = jiffies;		/*		 *   Step 6: Check sequence numbers		 *      Otherwise,		 *         If P.type == Reset,		 *            Send Sync packet acknowledging S.GSR		 *         Otherwise,		 *            Send Sync packet acknowledging P.seqno		 *      Drop packet and return		 *		 *   These Syncs are rate-limited as per RFC 4340, 7.5.4:		 *   at most 1 / (dccp_sync_rate_limit * HZ) Syncs per second.		 */		if (time_before(now, (dp->dccps_rate_last +				      sysctl_dccp_sync_ratelimit)))			return 0;		DCCP_WARN("DCCP: Step 6 failed for %s packet, "			  "(LSWL(%llu) <= P.seqno(%llu) <= S.SWH(%llu)) and "			  "(P.ackno %s or LAWL(%llu) <= P.ackno(%llu) <= S.AWH(%llu), "			  "sending SYNC...\n",  dccp_packet_name(dh->dccph_type),			  (unsigned long long) lswl, (unsigned long long) seqno,			  (unsigned long long) dp->dccps_swh,			  (ackno == DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist"							      : "exists",			  (unsigned long long) lawl, (unsigned long long) ackno,			  (unsigned long long) dp->dccps_awh);		dp->dccps_rate_last = now;		if (dh->dccph_type == DCCP_PKT_RESET)			seqno = dp->dccps_gsr;		dccp_send_sync(sk, seqno, DCCP_PKT_SYNC);		return -1;	}	return 0;}static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb,				  const struct dccp_hdr *dh, const unsigned len){	struct dccp_sock *dp = dccp_sk(sk);	switch (dccp_hdr(skb)->dccph_type) {	case DCCP_PKT_DATAACK:	case DCCP_PKT_DATA:		/*		 * FIXME: check if sk_receive_queue is full, schedule DATA_DROPPED		 * option if it is.		 */		__skb_pull(skb, dh->dccph_doff * 4);		__skb_queue_tail(&sk->sk_receive_queue, skb);		skb_set_owner_r(skb, sk);		sk->sk_data_ready(sk, 0);		return 0;	case DCCP_PKT_ACK:		goto discard;	case DCCP_PKT_RESET:		/*		 *  Step 9: Process Reset		 *	If P.type == Reset,		 *		Tear down connection		 *		S.state := TIMEWAIT		 *		Set TIMEWAIT timer		 *		Drop packet and return		 */		dccp_rcv_reset(sk, skb);		return 0;	case DCCP_PKT_CLOSEREQ:		dccp_rcv_closereq(sk, skb);		goto discard;	case DCCP_PKT_CLOSE:		dccp_rcv_close(sk, skb);		return 0;	case DCCP_PKT_REQUEST:		/* Step 7		 *   or (S.is_server and P.type == Response)		 *   or (S.is_client and P.type == Request)		 *   or (S.state >= OPEN and P.type == Request		 *	and P.seqno >= S.OSR)		 *    or (S.state >= OPEN and P.type == Response		 *	and P.seqno >= S.OSR)		 *    or (S.state == RESPOND and P.type == Data),		 *  Send Sync packet acknowledging P.seqno		 *  Drop packet and return		 */		if (dp->dccps_role != DCCP_ROLE_LISTEN)			goto send_sync;		goto check_seq;	case DCCP_PKT_RESPONSE:		if (dp->dccps_role != DCCP_ROLE_CLIENT)			goto send_sync;check_seq:		if (dccp_delta_seqno(dp->dccps_osr,				     DCCP_SKB_CB(skb)->dccpd_seq) >= 0) {send_sync:			dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,				       DCCP_PKT_SYNC);		}		break;	case DCCP_PKT_SYNC:		dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq,			       DCCP_PKT_SYNCACK);		/*		 * From RFC 4340, sec. 5.7		 *		 * As with DCCP-Ack packets, DCCP-Sync and DCCP-SyncAck packets		 * MAY have non-zero-length application data areas, whose		 * contents receivers MUST ignore.		 */		goto discard;	}	DCCP_INC_STATS_BH(DCCP_MIB_INERRS);discard:	__kfree_skb(skb);	return 0;}int dccp_rcv_established(struct sock *sk, struct sk_buff *skb,			 const struct dccp_hdr *dh, const unsigned len){	struct dccp_sock *dp = dccp_sk(sk);	if (dccp_check_seqno(sk, skb))		goto discard;	if (dccp_parse_options(sk, skb))		goto discard;	if (DCCP_SKB_CB(skb)->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ)		dccp_event_ack_recv(sk, skb);	if (dccp_msk(sk)->dccpms_send_ack_vector &&	    dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk,			    DCCP_SKB_CB(skb)->dccpd_seq,			    DCCP_ACKVEC_STATE_RECEIVED))		goto discard;	ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb);	ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb);	return __dccp_rcv_established(sk, skb, dh, len);discard:	__kfree_skb(skb);	return 0;}EXPORT_SYMBOL_GPL(dccp_rcv_established);static int dccp_rcv_request_sent_state_process(struct sock *sk,					       struct sk_buff *skb,					       const struct dccp_hdr *dh,					       const unsigned len){	/*	 *  Step 4: Prepare sequence numbers in REQUEST	 *     If S.state == REQUEST,	 *	  If (P.type == Response or P.type == Reset)	 *		and S.AWL <= P.ackno <= S.AWH,	 *	     / * Set sequence number variables corresponding to the	 *		other endpoint, so P will pass the tests in Step 6 * /	 *	     Set S.GSR, S.ISR, S.SWL, S.SWH	 *	     / * Response processing continues in Step 10; Reset

⌨️ 快捷键说明

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