Skip to content
Snippets Groups Projects
tcp_input.c 172 KiB
Newer Older
  • Learn to ignore specific revisions
  • Linus Torvalds's avatar
    Linus Torvalds committed
    
    		case TCP_LAST_ACK:
    			if (tp->snd_una == tp->write_seq) {
    				tcp_update_metrics(sk);
    				tcp_done(sk);
    				goto discard;
    			}
    			break;
    		}
    	} else
    		goto discard;
    
    	/* step 6: check the URG bit */
    	tcp_urg(sk, skb, th);
    
    	/* step 7: process the segment text */
    	switch (sk->sk_state) {
    	case TCP_CLOSE_WAIT:
    	case TCP_CLOSING:
    	case TCP_LAST_ACK:
    		if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt))
    			break;
    	case TCP_FIN_WAIT1:
    	case TCP_FIN_WAIT2:
    		/* RFC 793 says to queue data in these states,
    
    		 * RFC 1122 says we MUST send a reset.
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		 * BSD 4.4 also does reset.
    		 */
    		if (sk->sk_shutdown & RCV_SHUTDOWN) {
    			if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
    			    after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
    
    				NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONDATA);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    				tcp_reset(sk);
    				return 1;
    			}
    		}
    		/* Fall through */
    
    	case TCP_ESTABLISHED:
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		tcp_data_queue(sk, skb);
    		queued = 1;
    		break;
    	}
    
    	/* tcp_data could move socket to TIME-WAIT */
    	if (sk->sk_state != TCP_CLOSE) {
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		tcp_ack_snd_check(sk);
    	}
    
    
    	if (!queued) {
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    discard:
    		__kfree_skb(skb);
    	}
    	return 0;
    }
    EXPORT_SYMBOL(tcp_rcv_state_process);