patch-2.2.11 linux/net/ipv4/tcp_input.c

Next file: linux/net/ipv4/tcp_ipv4.c
Previous file: linux/net/ipv4/tcp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.164.2.3 1999/06/02 04:15:06 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.164.2.6 1999/08/08 08:43:18 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -213,21 +213,19 @@
 extern __inline__ void tcp_replace_ts_recent(struct sock *sk, struct tcp_opt *tp,
 					     __u32 start_seq, __u32 end_seq)
 {
-	/* From draft-ietf-tcplw-high-performance: the correct
-	 * test is last_ack_sent <= end_seq.
-	 * (RFC1323 stated last_ack_sent < end_seq.)
-	 *
-	 * HOWEVER: The current check contradicts the draft statements.
-	 * It has been done for good reasons.
-	 * The implemented check improves security and eliminates
-	 * unnecessary RTT overestimation.
-	 *		1998/06/27  Andrey V. Savochkin <saw@msu.ru>
+	/* It is start_seq <= last_ack_seq combined
+	   with in window check. If start_seq<=last_ack_seq<=rcv_nxt,
+	   then segment is in window if end_seq>=rcv_nxt.
 	 */
-	if (!before(end_seq, tp->last_ack_sent - sk->rcvbuf) &&
-	    !after(start_seq, tp->rcv_wup + tp->rcv_wnd)) {
+	if (!after(start_seq, tp->last_ack_sent) &&
+	    !before(end_seq, tp->rcv_nxt)) {
 		/* PAWS bug workaround wrt. ACK frames, the PAWS discard
 		 * extra check below makes sure this can only happen
 		 * for pure ACK frames.  -DaveM
+		 *
+		 * Plus: expired timestamps.
+		 *
+		 * Plus: resets failing PAWS.
 		 */
 		if((s32)(tp->rcv_tsval - tp->ts_recent) >= 0) {
 			tp->ts_recent = tp->rcv_tsval;
@@ -240,11 +238,10 @@
 
 extern __inline__ int tcp_paws_discard(struct tcp_opt *tp, struct tcphdr *th, unsigned len)
 {
-	/* ts_recent must be younger than 24 days */
-	return (((s32)(tcp_time_stamp - tp->ts_recent_stamp) >= PAWS_24DAYS) ||
-		(((s32)(tp->rcv_tsval - tp->ts_recent) < 0) &&
-		 /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
-		 (len != (th->doff * 4))));
+	return ((s32)(tp->rcv_tsval - tp->ts_recent) < 0 &&
+		(s32)(tcp_time_stamp - tp->ts_recent_stamp) < PAWS_24DAYS &&
+		/* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM */
+		len != (th->doff * 4));
 }
 
 
@@ -916,13 +913,20 @@
 
 void tcp_timewait_kill(struct tcp_tw_bucket *tw)
 {
-	/* Unlink from various places. */
+	struct tcp_bind_bucket *tb = tw->tb;
+
+	/* Disassociate with bind bucket. */
 	if(tw->bind_next)
 		tw->bind_next->bind_pprev = tw->bind_pprev;
 	*(tw->bind_pprev) = tw->bind_next;
-	if(tw->tb->owners == NULL)
-		tcp_inc_slow_timer(TCP_SLT_BUCKETGC);
+	if (tb->owners == NULL) {
+		if (tb->next)
+			tb->next->pprev = tb->pprev;
+		*(tb->pprev) = tb->next;
+		kmem_cache_free(tcp_bucket_cachep, tb);
+	}
 
+	/* Unlink from established hashes. */
 	if(tw->next)
 		tw->next->pprev = tw->pprev;
 	*tw->pprev = tw->next;
@@ -939,11 +943,13 @@
 
 /* We come here as a special case from the AF specific TCP input processing,
  * and the SKB has no owner.  Essentially handling this is very simple,
- * we just keep silently eating rx'd packets until none show up for the
- * entire timeout period.  The only special cases are for BSD TIME_WAIT
- * reconnects and SYN/RST bits being set in the TCP header.
+ * we just keep silently eating rx'd packets, acking them if necessary,
+ * until none show up for the entire timeout period. 
+ *
+ * Return 0, TCP_TW_ACK, TCP_TW_RST
  */
-int tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
+enum tcp_tw_status 
+tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
 			       struct tcphdr *th, unsigned len)
 {
 	/*	RFC 1122:
@@ -964,7 +970,7 @@
 		struct tcp_func *af_specific = tw->af_specific;
 		__u32 isn;
 
-		isn = tw->rcv_nxt + 128000;
+		isn = tw->snd_nxt + 128000;
 		if(isn == 0)
 			isn++;
 		tcp_tw_deschedule(tw);
@@ -977,7 +983,7 @@
 		skb_set_owner_r(skb, sk);
 		af_specific = sk->tp_pinfo.af_tcp.af_specific;
 		if(af_specific->conn_request(sk, skb, isn) < 0)
-			return 1; /* Toss a reset back. */
+			return TCP_TW_RST; /* Toss a reset back. */
 		return 0; /* Discard the frame. */
 	}
 
@@ -992,13 +998,17 @@
 			tcp_timewait_kill(tw);
 		}
 		if(!th->rst)
-			return 1; /* toss a reset back */
+			return TCP_TW_RST; /* toss a reset back */
+		return 0;
 	} else {
 		/* In this case we must reset the TIMEWAIT timer. */
 		if(th->ack)
 			tcp_tw_reschedule(tw);
 	}
-	return 0; /* Discard the frame. */
+	/* Ack old packets if necessary */ 
+	if (!after(TCP_SKB_CB(skb)->end_seq, tw->rcv_nxt)) 
+		return TCP_TW_ACK; 
+	return 0; 
 }
 
 /* Enter the time wait state.  This is always called from BH
@@ -1023,6 +1033,7 @@
 		sk->bind_next->bind_pprev = &tw->bind_next;
 	tw->bind_pprev = sk->bind_pprev;
 	*sk->bind_pprev = (struct sock *)tw;
+	sk->prev = NULL;
 
 	/* Step 3: Same for the protocol sklist. */
 	(tw->sklist_next = sk->sklist_next)->sklist_prev = (struct sock *)tw;
@@ -1056,6 +1067,7 @@
 		tw->family	= sk->family;
 		tw->reuse	= sk->reuse;
 		tw->rcv_nxt	= sk->tp_pinfo.af_tcp.rcv_nxt;
+		tw->snd_nxt = sk->tp_pinfo.af_tcp.snd_nxt;
 		tw->af_specific	= sk->tp_pinfo.af_tcp.af_specific;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -1527,7 +1539,6 @@
 	 * Now tell the user we may have some data.
 	 */
 	if (!sk->dead) {
-		SOCK_DEBUG(sk, "Data wakeup.\n");
 		sk->data_ready(sk,0);
 	}
 	return(1);
@@ -1967,7 +1978,7 @@
 	flg &= __constant_htonl(0x00170000);
 	/* Only SYN set? */
 	if (flg == __constant_htonl(0x00020000)) {
-		if (!after(TCP_SKB_CB(skb)->seq, req->rcv_isn)) {
+		if (TCP_SKB_CB(skb)->seq == req->rcv_isn) {
 			/*	retransmited syn.
 			 */
 			req->class->rtx_syn_ack(sk, req); 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)