patch-1.3.38 linux/net/ipv4/tcp.c

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

diff -u --recursive --new-file v1.3.37/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -176,6 +176,7 @@
  *		Marc Tamsky	:	Closing in closing fixes.
  *		Mike Shaver	:	RFC1122 verifications.
  *		Alan Cox	:	rcv_saddr errors.
+ *		Alan Cox	:	Block double connect()
  *
  *
  * To Fix:
@@ -1697,9 +1698,7 @@
 				release_sock(sk);
 				if (copied) 
 					return(copied);
-				tmp = -sk->err;
-				sk->err = 0;
-				return(tmp);
+				return sock_error(sk);
 			}
 
 			/*
@@ -1727,9 +1726,7 @@
 					release_sock(sk);
 					if (copied) 
 						return(copied);
-					tmp = -sk->err;
-					sk->err = 0;
-					return(tmp);
+					return sock_error(sk);
 				}		
 	
 				if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV) 
@@ -1739,11 +1736,7 @@
 						return(copied);
 	
 					if (sk->err) 
-					{	
-						tmp = -sk->err;
-						sk->err = 0;
-						return(tmp);
-					}
+						return sock_error(sk);
 
 					if (sk->keepopen) 
 					{
@@ -1996,30 +1989,6 @@
 	return(copied);
 }
 
-static int tcp_sendto(struct sock *sk, const unsigned char *ubuf, int size, int noblock, unsigned flags,
-		struct sockaddr_in *sin, int addr_len)
-{
-	struct iovec iov;
-	struct msghdr msg;
-
-	iov.iov_base = (void *)ubuf;
-	iov.iov_len  = size;
-
-	msg.msg_name      = (void *)sin;
-	msg.msg_namelen   = addr_len;
-	msg.msg_accrights = NULL;
-	msg.msg_iov       = &iov;
-	msg.msg_iovlen    = 1;
-
-	return tcp_sendmsg(sk, &msg, size, noblock, flags);
-}
-
-static int tcp_write(struct sock *sk, const unsigned char *ubuf, int size, int noblock, unsigned flags)
-{
-	return tcp_sendto(sk,ubuf,size,noblock,flags,NULL,0);
-}
-
-
 /*
  *	Send an ack if one is backlogged at this point. Ought to merge
  *	this with tcp_send_ack().
@@ -2205,12 +2174,8 @@
 		return -EINVAL;	/* Yes this is right ! */
 		
 	if (sk->err) 
-	{
-		int tmp = -sk->err;
-		sk->err = 0;
-		return tmp;
-	}
-
+		return sock_error(sk);
+		
 	if (sk->state == TCP_CLOSE || sk->done) 
 	{
 		if (!sk->done) 
@@ -2341,8 +2306,7 @@
 
 		if (sk->err) 
 		{
-			copied = -sk->err;
-			sk->err = 0;
+			copied = -xchg(&sk->err,0);
 			break;
 		}
 
@@ -2500,32 +2464,6 @@
 }
 
 
-static int tcp_recvfrom(struct sock *sk, unsigned char *ubuf, int size, int noblock, unsigned flags,
-		struct sockaddr_in *sa, int *addr_len)
-{
-	struct iovec iov;
-	struct msghdr msg;
-
-	iov.iov_base = (void *)ubuf;
-	iov.iov_len  = size;
-
-	msg.msg_name      = (void *)sa;
-	msg.msg_namelen   = 0;
-	if (addr_len)
-		msg.msg_namelen = *addr_len;
-	msg.msg_accrights = NULL;
-	msg.msg_iov       = &iov;
-	msg.msg_iovlen    = 1;
-
-	return tcp_recvmsg(sk, &msg, size, noblock, flags, addr_len);
-}
-
-int tcp_read(struct sock *sk, unsigned char *buff, int len, int noblock,
-	 unsigned flags)
-{
-	return(tcp_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
-}
-
 
 /*
  *	State processing on a close. This implements the state shift for
@@ -4531,9 +4469,14 @@
 	struct rtable *rt;
 
 	if (sk->state != TCP_CLOSE) 
-	{
 		return(-EISCONN);
-	}
+
+	/*
+	 *	Don't allow a double connect.
+	 */
+	 	
+	if(sk->daddr)
+		return -EINVAL;
 	
 	if (addr_len < 8) 
 		return(-EINVAL);
@@ -4580,9 +4523,9 @@
 	 */
 	 
 	if (sk->localroute)
-	  rt=ip_rt_local(sk->daddr, NULL, sk->saddr ? NULL : &sk->saddr);
+		rt=ip_rt_local(sk->daddr, NULL, sk->saddr ? NULL : &sk->saddr);
 	else
-	  rt=ip_rt_route(sk->daddr, NULL, sk->saddr ? NULL : &sk->saddr);
+		rt=ip_rt_route(sk->daddr, NULL, sk->saddr ? NULL : &sk->saddr);
 
 	/*
 	 *	When we connect we enforce receive requirements too.
@@ -4674,8 +4617,9 @@
 		sk->rto = TCP_TIMEOUT_INIT;
 	sk->retransmit_timer.function=&retransmit_timer;
 	sk->retransmit_timer.data = (unsigned long)sk;
-	reset_xmit_timer(sk, TIME_WRITE, sk->rto);	/* Timer for repeating the SYN until an answer */
-	sk->retransmits = 0;	/* Now works the right way instead of a hacked initial setting */
+	reset_xmit_timer(sk, TIME_WRITE, sk->rto);	/* Timer for repeating the SYN until an answer  */
+	sk->retransmits = 0;				/* Now works the right way instead of a hacked 
+											initial setting */
 
 	sk->prot->queue_xmit(sk, dev, buff, 0);  
 	reset_xmit_timer(sk, TIME_WRITE, sk->rto);
@@ -4687,7 +4631,10 @@
 }
 
 
-/* This functions checks to see if the tcp header is actually acceptable. */
+/*
+ *	This functions checks to see if the tcp header is actually acceptable. 
+ */
+ 
 extern __inline__ int tcp_sequence(struct sock *sk, struct tcphdr *th, short len,
 	     struct options *opt, unsigned long saddr, struct device *dev)
 {
@@ -4868,7 +4815,6 @@
 			return(0);
 		}
 
-/*		skb->len = len;*/
 		skb->acked = 0;
 		skb->used = 0;
 		skb->free = 0;
@@ -4909,13 +4855,6 @@
 	 *	Charge the memory to the socket. 
 	 */
 	 
-	if (sk->rmem_alloc + skb->truesize >= sk->rcvbuf) 
-	{
-		kfree_skb(skb, FREE_READ);
-		release_sock(sk);
-		return(0);
-	}
-
 	skb->sk=sk;
 	sk->rmem_alloc += skb->truesize;
 
@@ -5152,6 +5091,20 @@
 rfc_step6:		/* I'll clean this up later */
 
 	/*
+	 *	If the accepted buffer put us over our queue size we
+	 *	now drop it (we must process the ack first to avoid
+	 *	deadlock cases).
+	 */
+	 
+	if (sk->rmem_alloc  >= sk->rcvbuf) 
+	{
+		kfree_skb(skb, FREE_READ);
+		release_sock(sk);
+		return(0);
+	}
+
+
+	/*
 	 *	Process urgent data
 	 */
 	 	
@@ -5162,7 +5115,6 @@
 		return 0;
 	}
 	
-	
 	/*
 	 *	Process the encapsulated data
 	 */
@@ -5500,10 +5452,6 @@
 
 struct proto tcp_prot = {
 	tcp_close,
-	tcp_read,
-	tcp_write,
-	tcp_sendto,
-	tcp_recvfrom,
 	ip_build_header,
 	tcp_connect,
 	tcp_accept,
@@ -5520,6 +5468,7 @@
 	tcp_getsockopt,
 	tcp_sendmsg,
 	tcp_recvmsg,
+	NULL,		/* No special bind() */
 	128,
 	0,
 	"TCP",

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this