patch-2.1.9 linux/net/ipv4/tcp_ipv4.c

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

diff -u --recursive --new-file v2.1.8/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
@@ -934,6 +934,86 @@
 	return newsk;
 }
 
+struct sock *tcp_v4_check_req(struct sock *sk, struct sk_buff *skb)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	struct open_request *req;
+
+
+	/*
+	 *	assumption: the socket is not in use.
+	 *	as we checked the user count on tcp_rcv and we're
+	 *	running from a soft interrupt.
+	 */
+		
+	req = tp->syn_wait_queue;
+	
+
+	if (!req)
+	{
+		return sk;
+	}
+	
+	do {
+		struct tcp_v4_open_req *af_req;
+
+		af_req = (struct tcp_v4_open_req *) req;
+
+		if (af_req->rmt_addr == skb->saddr &&
+		    af_req->loc_addr == skb->daddr &&
+		    req->rmt_port == skb->h.th->source)
+		{
+			u32 flg;
+				
+			if (req->sk)
+			{
+				printk(KERN_DEBUG "BUG: syn_recv:"
+				       "socket exists\n");
+				break;
+			}
+
+			/* match */
+
+			/*
+			 *	Check for syn retransmission
+			 */
+			flg = *(((u32 *)skb->h.th) + 3);
+			flg &= __constant_htonl(0x002f0000);
+				
+			if ((flg == __constant_htonl(0x00020000)) &&
+			    (!after(skb->seq, req->rcv_isn)))
+			{
+				/*
+				 *	retransmited syn
+				 *	FIXME: must send an ack
+				 */
+				return NULL;
+			}
+
+			atomic_sub(skb->truesize, &sk->rmem_alloc);
+			sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+
+			tcp_dec_slow_timer(TCP_SLT_SYNACK);
+
+			if (sk == NULL)
+			{
+				return NULL;
+			}
+
+			atomic_add(skb->truesize, &sk->rmem_alloc);
+			req->expires = 0UL;
+			req->sk = sk;
+			skb->sk = sk;
+			break;
+		}
+
+		req = req->dl_next;
+	} while (req != tp->syn_wait_queue);
+	
+
+	return sk;
+}
+
 /*
  *	From tcp_input.c
  */
@@ -1027,53 +1107,14 @@
 
 	if (sk->state == TCP_LISTEN)
 	{
-		struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
-		struct open_request *req;
-		struct tcp_v4_open_req *af_req;
-
 		/*
-		 *	assumption: the socket is not in use.
-		 *	as we checked the user count above and we're
-		 *	running from a soft interrupt.
+		 *	find possible connection requests
 		 */
-		
-		req = tp->syn_wait_queue;
-		af_req = (struct tcp_v4_open_req *) req;
-		
-		if (req)
-		{
-			do {
-				if (af_req->rmt_addr == saddr &&
-				    af_req->loc_addr == daddr &&
-				    req->rmt_port == th->source)
-				{
-					if (req->sk)
-					{
-						printk(KERN_DEBUG "bug: syn_recv socket "
-						       "exists\n");
-						break;
-					}
-
-					/* match */
-
-					atomic_sub(skb->truesize, &sk->rmem_alloc);
-					sk = tp->af_specific->syn_recv_sock(sk, skb, req);
-
-					tcp_dec_slow_timer(TCP_SLT_SYNACK);
-
-					if (sk == NULL)
-					{
-						goto no_tcp_socket;
-					}
-					
-					atomic_add(skb->truesize, &sk->rmem_alloc);
-					req->sk = sk;
-					skb->sk = sk;
-					break;
-				}
+		sk = tcp_v4_check_req(sk, skb);
 
-				req = req->dl_next;
-			} while (req != tp->syn_wait_queue);
+		if (sk == NULL)
+		{
+			goto discard_it;
 		}
 	}
 	
@@ -1257,7 +1298,7 @@
 	 */
 	sk->cong_window = 1;
 	sk->ssthresh = 0x7fffffff;
-
+	
 	sk->priority = 1;
 	sk->state = TCP_CLOSE;
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov