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

📄 input.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	 *		processing continues in Step 9 * /	*/	if (dh->dccph_type == DCCP_PKT_RESPONSE) {		const struct inet_connection_sock *icsk = inet_csk(sk);		struct dccp_sock *dp = dccp_sk(sk);		long tstamp = dccp_timestamp();		/* Stop the REQUEST timer */		inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS);		BUG_TRAP(sk->sk_send_head != NULL);		__kfree_skb(sk->sk_send_head);		sk->sk_send_head = NULL;		if (!between48(DCCP_SKB_CB(skb)->dccpd_ack_seq,			       dp->dccps_awl, dp->dccps_awh)) {			dccp_pr_debug("invalid ackno: S.AWL=%llu, "				      "P.ackno=%llu, S.AWH=%llu \n",				      (unsigned long long)dp->dccps_awl,			   (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq,				      (unsigned long long)dp->dccps_awh);			goto out_invalid_packet;		}		if (dccp_parse_options(sk, skb))			goto out_invalid_packet;		/* Obtain usec RTT sample from SYN exchange (used by CCID 3) */		if (likely(dp->dccps_options_received.dccpor_timestamp_echo))			dp->dccps_syn_rtt = dccp_sample_rtt(sk, 10 * (tstamp -			    dp->dccps_options_received.dccpor_timestamp_echo));		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 out_invalid_packet; /* FIXME: change error code */		dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq;		dccp_update_gsr(sk, dp->dccps_isr);		/*		 * SWL and AWL are initially adjusted so that they are not less than		 * the initial Sequence Numbers received and sent, respectively:		 *	SWL := max(GSR + 1 - floor(W/4), ISR),		 *	AWL := max(GSS - W' + 1, ISS).		 * These adjustments MUST be applied only at the beginning of the		 * connection.		 *		 * AWL was adjusted in dccp_v4_connect -acme		 */		dccp_set_seqno(&dp->dccps_swl,			       max48(dp->dccps_swl, dp->dccps_isr));		dccp_sync_mss(sk, icsk->icsk_pmtu_cookie);		/*		 *    Step 10: Process REQUEST state (second part)		 *       If S.state == REQUEST,		 *	  / * If we get here, P is a valid Response from the		 *	      server (see Step 4), and we should move to		 *	      PARTOPEN state. PARTOPEN means send an Ack,		 *	      don't send Data packets, retransmit Acks		 *	      periodically, and always include any Init Cookie		 *	      from the Response * /		 *	  S.state := PARTOPEN		 *	  Set PARTOPEN timer		 *	  Continue with S.state == PARTOPEN		 *	  / * Step 12 will send the Ack completing the		 *	      three-way handshake * /		 */		dccp_set_state(sk, DCCP_PARTOPEN);		/* Make sure socket is routed, for correct metrics. */		icsk->icsk_af_ops->rebuild_header(sk);		if (!sock_flag(sk, SOCK_DEAD)) {			sk->sk_state_change(sk);			sk_wake_async(sk, 0, POLL_OUT);		}		if (sk->sk_write_pending || icsk->icsk_ack.pingpong ||		    icsk->icsk_accept_queue.rskq_defer_accept) {			/* Save one ACK. Data will be ready after			 * several ticks, if write_pending is set.			 *			 * It may be deleted, but with this feature tcpdumps			 * look so _wonderfully_ clever, that I was not able			 * to stand against the temptation 8)     --ANK			 */			/*			 * OK, in DCCP we can as well do a similar trick, its			 * even in the draft, but there is no need for us to			 * schedule an ack here, as dccp_sendmsg does this for			 * us, also stated in the draft. -acme			 */			__kfree_skb(skb);			return 0;		}		dccp_send_ack(sk);		return -1;	}out_invalid_packet:	/* dccp_v4_do_rcv will send a reset */	DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR;	return 1;}static int dccp_rcv_respond_partopen_state_process(struct sock *sk,						   struct sk_buff *skb,						   const struct dccp_hdr *dh,						   const unsigned len){	int queued = 0;	switch (dh->dccph_type) {	case DCCP_PKT_RESET:		inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);		break;	case DCCP_PKT_DATA:		if (sk->sk_state == DCCP_RESPOND)			break;	case DCCP_PKT_DATAACK:	case DCCP_PKT_ACK:		/*		 * FIXME: we should be reseting the PARTOPEN (DELACK) timer		 * here but only if we haven't used the DELACK timer for		 * something else, like sending a delayed ack for a TIMESTAMP		 * echo, etc, for now were not clearing it, sending an extra		 * ACK when there is nothing else to do in DELACK is not a big		 * deal after all.		 */		/* Stop the PARTOPEN timer */		if (sk->sk_state == DCCP_PARTOPEN)			inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK);		dccp_sk(sk)->dccps_osr = DCCP_SKB_CB(skb)->dccpd_seq;		dccp_set_state(sk, DCCP_OPEN);		if (dh->dccph_type == DCCP_PKT_DATAACK ||		    dh->dccph_type == DCCP_PKT_DATA) {			__dccp_rcv_established(sk, skb, dh, len);			queued = 1; /* packet was queued				       (by __dccp_rcv_established) */		}		break;	}	return queued;}int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb,			   struct dccp_hdr *dh, unsigned len){	struct dccp_sock *dp = dccp_sk(sk);	struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb);	const int old_state = sk->sk_state;	int queued = 0;	/*	 *  Step 3: Process LISTEN state	 *	 *     If S.state == LISTEN,	 *	 If P.type == Request or P contains a valid Init Cookie option,	 *	      (* Must scan the packet's options to check for Init	 *		 Cookies.  Only Init Cookies are processed here,	 *		 however; other options are processed in Step 8.  This	 *		 scan need only be performed if the endpoint uses Init	 *		 Cookies *)	 *	      (* Generate a new socket and switch to that socket *)	 *	      Set S := new socket for this port pair	 *	      S.state = RESPOND	 *	      Choose S.ISS (initial seqno) or set from Init Cookies	 *	      Initialize S.GAR := S.ISS	 *	      Set S.ISR, S.GSR, S.SWL, S.SWH from packet or Init	 *	      Cookies Continue with S.state == RESPOND	 *	      (* A Response packet will be generated in Step 11 *)	 *	 Otherwise,	 *	      Generate Reset(No Connection) unless P.type == Reset	 *	      Drop packet and return	 */	if (sk->sk_state == DCCP_LISTEN) {		if (dh->dccph_type == DCCP_PKT_REQUEST) {			if (inet_csk(sk)->icsk_af_ops->conn_request(sk,								    skb) < 0)				return 1;			/* FIXME: do congestion control initialization */			goto discard;		}		if (dh->dccph_type == DCCP_PKT_RESET)			goto discard;		/* Caller (dccp_v4_do_rcv) will send Reset */		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;		return 1;	}	if (sk->sk_state != DCCP_REQUESTING) {		if (dccp_check_seqno(sk, skb))			goto discard;		/*		 * Step 8: Process options and mark acknowledgeable		 */		if (dccp_parse_options(sk, skb))			goto discard;		if (dcb->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);	}	/*	 *  Step 9: Process Reset	 *	If P.type == Reset,	 *		Tear down connection	 *		S.state := TIMEWAIT	 *		Set TIMEWAIT timer	 *		Drop packet and return	*/	if (dh->dccph_type == DCCP_PKT_RESET) {		dccp_rcv_reset(sk, skb);		return 0;		/*		 *   Step 7: Check for unexpected packet types		 *      If (S.is_server and P.type == CloseReq)		 *	    or (S.is_server and P.type == Response)		 *	    or (S.is_client and P.type == Request)		 *	    or (S.state == RESPOND and P.type == Data),		 *	  Send Sync packet acknowledging P.seqno		 *	  Drop packet and return		 */	} else if ((dp->dccps_role != DCCP_ROLE_CLIENT &&		    (dh->dccph_type == DCCP_PKT_RESPONSE ||		     dh->dccph_type == DCCP_PKT_CLOSEREQ)) ||		    (dp->dccps_role == DCCP_ROLE_CLIENT &&		     dh->dccph_type == DCCP_PKT_REQUEST) ||		    (sk->sk_state == DCCP_RESPOND &&		     dh->dccph_type == DCCP_PKT_DATA)) {		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNC);		goto discard;	} else if (dh->dccph_type == DCCP_PKT_CLOSEREQ) {		dccp_rcv_closereq(sk, skb);		goto discard;	} else if (dh->dccph_type == DCCP_PKT_CLOSE) {		dccp_rcv_close(sk, skb);		return 0;	}	switch (sk->sk_state) {	case DCCP_CLOSED:		dcb->dccpd_reset_code = DCCP_RESET_CODE_NO_CONNECTION;		return 1;	case DCCP_REQUESTING:		/* FIXME: do congestion control initialization */		queued = dccp_rcv_request_sent_state_process(sk, skb, dh, len);		if (queued >= 0)			return queued;		__kfree_skb(skb);		return 0;	case DCCP_RESPOND:	case DCCP_PARTOPEN:		queued = dccp_rcv_respond_partopen_state_process(sk, skb,								 dh, len);		break;	}	if (dh->dccph_type == DCCP_PKT_ACK ||	    dh->dccph_type == DCCP_PKT_DATAACK) {		switch (old_state) {		case DCCP_PARTOPEN:			sk->sk_state_change(sk);			sk_wake_async(sk, 0, POLL_OUT);			break;		}	} else if (unlikely(dh->dccph_type == DCCP_PKT_SYNC)) {		dccp_send_sync(sk, dcb->dccpd_seq, DCCP_PKT_SYNCACK);		goto discard;	}	if (!queued) {discard:		__kfree_skb(skb);	}	return 0;}EXPORT_SYMBOL_GPL(dccp_rcv_state_process);/** *  dccp_sample_rtt  -  Validate and finalise computation of RTT sample *  @delta:	number of microseconds between packet and acknowledgment *  The routine is kept generic to work in different contexts. It should be *  called immediately when the ACK used for the RTT sample arrives. */u32 dccp_sample_rtt(struct sock *sk, long delta){	/* dccpor_elapsed_time is either zeroed out or set and > 0 */	delta -= dccp_sk(sk)->dccps_options_received.dccpor_elapsed_time * 10;	if (unlikely(delta <= 0)) {		DCCP_WARN("unusable RTT sample %ld, using min\n", delta);		return DCCP_SANE_RTT_MIN;	}	if (unlikely(delta > DCCP_SANE_RTT_MAX)) {		DCCP_WARN("RTT sample %ld too large, using max\n", delta);		return DCCP_SANE_RTT_MAX;	}	return delta;}EXPORT_SYMBOL_GPL(dccp_sample_rtt);

⌨️ 快捷键说明

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