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

Next file: linux/net/ipv4/arp.c
Previous file: linux/net/core/rtnetlink.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.10/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
@@ -5,7 +5,7 @@
  *
  *		PF_INET protocol family socket handler.
  *
- * Version:	$Id: af_inet.c,v 1.87.2.1 1999/05/29 04:32:01 davem Exp $
+ * Version:	$Id: af_inet.c,v 1.87.2.5 1999/08/08 08:43:10 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -187,7 +187,6 @@
 			atomic_read(&sk->rmem_alloc),
 			atomic_read(&sk->wmem_alloc)));
 
-	sk->destroy = 1;
 	sk->ack_backlog = 0;
 	release_sock(sk);
 	net_reset_timer(sk, TIME_DESTROY, SOCK_DESTROY_TIME);
@@ -202,9 +201,11 @@
   	 */
   	net_delete_timer(sk);
 
-	if (sk->prot->destroy)
+	if (sk->prot->destroy && !sk->destroy)
 		sk->prot->destroy(sk);
 
+	sk->destroy = 1;
+
 	kill_sk_queues(sk);
 
 	/* Now if everything is gone we can free the socket
@@ -262,8 +263,7 @@
 {
 	/* We may need to bind the socket. */
 	if (sk->num == 0) {
-		sk->num = sk->prot->good_socknum();
-		if (sk->num == 0) 
+		if (sk->prot->get_port(sk, 0) != 0)
 			return(-EAGAIN);
 		sk->sport = htons(sk->num);
 		sk->prot->hash(sk);
@@ -279,28 +279,41 @@
 int inet_listen(struct socket *sock, int backlog)
 {
 	struct sock *sk = sock->sk;
+	unsigned char old_state;
 
 	if (sock->state != SS_UNCONNECTED || sock->type != SOCK_STREAM)
 		return(-EINVAL);
 
-	if (inet_autobind(sk) != 0)
-		return -EAGAIN;
-
-	/* We might as well re use these. */ 
 	if ((unsigned) backlog == 0)	/* BSDism */
 		backlog = 1;
 	if ((unsigned) backlog > SOMAXCONN)
 		backlog = SOMAXCONN;
 	sk->max_ack_backlog = backlog;
-	if (sk->state != TCP_LISTEN) {
-		sk->ack_backlog = 0;
+
+	/* Really, if the socket is already in listen state
+	 * we can only allow the backlog to be adjusted.
+	 */
+	old_state = sk->state;
+	if (old_state != TCP_LISTEN) {
 		sk->state = TCP_LISTEN;
+		sk->ack_backlog = 0;
+		if (sk->num == 0) {
+			if (sk->prot->get_port(sk, 0) != 0) {
+				sk->state = old_state;
+				return -EAGAIN;
+			}
+			sk->sport = htons(sk->num);
+			add_to_prot_sklist(sk);
+		} else {
+			if (sk->prev)
+				((struct tcp_bind_bucket*)sk->prev)->fastreuse = 0;
+		}
+
 		dst_release(xchg(&sk->dst_cache, NULL));
-		sk->prot->rehash(sk);
-		add_to_prot_sklist(sk);
+		sk->prot->hash(sk);
+		sk->socket->flags |= SO_ACCEPTCON;
 	}
-	sk->socket->flags |= SO_ACCEPTCON;
-	return(0);
+	return 0;
 }
 
 /*
@@ -471,11 +484,9 @@
 		 */
 		timeout = 0;
 		if (sk->linger && !(current->flags & PF_EXITING)) {
-			timeout = MAX_SCHEDULE_TIMEOUT;
-
-			/* XXX This makes no sense whatsoever... -DaveM */
-			if (!sk->lingertime)
-				timeout = HZ*sk->lingertime;
+			timeout = HZ * sk->lingertime;
+			if (!timeout)
+				timeout = MAX_SCHEDULE_TIMEOUT;
 		}
 		sock->sk = NULL;
 		sk->socket = NULL;
@@ -528,20 +539,17 @@
 	if((snum >= PORT_MASQ_BEGIN) && (snum <= PORT_MASQ_END))
 		return -EADDRINUSE;
 #endif		 
-	if (snum == 0) 
-		snum = sk->prot->good_socknum();
-	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+	if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
 		return(-EACCES);
 	
 	/* Make sure we are allowed to bind here. */
-	if(sk->prot->verify_bind(sk, snum))
+	if (sk->prot->get_port(sk, snum) != 0)
 		return -EADDRINUSE;
 
-	sk->num = snum;
-	sk->sport = htons(snum);
+	sk->sport = htons(sk->num);
 	sk->daddr = 0;
 	sk->dport = 0;
-	sk->prot->rehash(sk);
+	sk->prot->hash(sk);
 	add_to_prot_sklist(sk);
 	dst_release(sk->dst_cache);
 	sk->dst_cache=NULL;
@@ -611,11 +619,13 @@
 		if (flags & O_NONBLOCK)
 			return -EALREADY;
 	} else {
+		if (sk->prot->connect == NULL) 
+			return(-EOPNOTSUPP);
+
 		/* We may need to bind the socket. */
 		if (inet_autobind(sk) != 0)
 			return(-EAGAIN);
-		if (sk->prot->connect == NULL) 
-			return(-EOPNOTSUPP);
+
 		err = sk->prot->connect(sk, uaddr, addr_len);
 		/* Note: there is a theoretical race here when an wake up
 		   occurred before inet_wait_for_connect is entered. In 2.3
@@ -789,7 +799,7 @@
 		return sock_error(sk);
 
 	/* We may need to bind the socket. */
-	if(inet_autobind(sk) != 0)
+	if (inet_autobind(sk) != 0)
 		return -EAGAIN;
 
 	return sk->prot->sendmsg(sk, msg, size);
@@ -808,9 +818,11 @@
 		       2->3 */
 	if ((how & ~SHUTDOWN_MASK) || how==0)	/* MAXINT->0 */
 		return(-EINVAL);
+	if (!sk)
+		return(-ENOTCONN);
 	if (sock->state == SS_CONNECTING && sk->state == TCP_ESTABLISHED)
 		sock->state = SS_CONNECTED;
-	if (!sk || !tcp_connected(sk->state)) 
+	if (!tcp_connected(sk->state)) 
 		return(-ENOTCONN);
 	sk->shutdown |= how;
 	if (sk->prot->shutdown)

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