patch-2.4.0-test7 linux/net/unix/af_unix.c

Next file: linux/scripts/Menuconfig
Previous file: linux/net/sunrpc/sched.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test6/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.102 2000/07/26 01:04:21 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.105 2000/08/16 10:58:22 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -306,6 +306,27 @@
 	read_unlock(&sk->callback_lock);
 }
 
+/* When dgram socket disconnects (or changes its peer), we clear its receive
+ * queue of packets arrived from previous peer. First, it allows to do
+ * flow control based only on wmem_alloc; second, sk connected to peer
+ * may receive messages only from that peer. */
+static void unix_dgram_disconnected(struct sock *sk, struct sock *other)
+{
+	if (skb_queue_len(&sk->receive_queue)) {
+		skb_queue_purge(&sk->receive_queue);
+		wake_up_interruptible_all(&sk->protinfo.af_unix.peer_wait);
+
+		/* If one link of bidirectional dgram pipe is disconnected,
+		 * we signal error. Messages are lost. Do not make this,
+		 * when peer was not connected to us.
+		 */
+		if (!other->dead && unix_peer(other) == sk) {
+			other->err = ECONNRESET;
+			other->error_report(other);
+		}
+	}
+}
+
 static void unix_sock_destructor(struct sock *sk)
 {
 	skb_queue_purge(&sk->receive_queue);
@@ -572,7 +593,8 @@
 	int err = 0;
 	
 	if (sunname->sun_path[0]) {
-		if (path_init(sunname->sun_path, LOOKUP_POSITIVE, &nd))
+		if (path_init(sunname->sun_path, 
+			      LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd))
 			err = path_walk(sunname->sun_path, &nd);
 		if (err)
 			goto fail;
@@ -788,6 +810,8 @@
 		unix_peer(sk)=other;
 		unix_state_wunlock(sk);
 
+		if (other != old_peer)
+			unix_dgram_disconnected(sk, old_peer);
 		sock_put(old_peer);
 	} else {
 		unix_peer(sk)=other;
@@ -1203,6 +1227,7 @@
 			unix_peer(sk)=NULL;
 			unix_state_wunlock(sk);
 
+			unix_dgram_disconnected(sk, other);
 			sock_put(other);
 			err = -ECONNREFUSED;
 		} else {
@@ -1219,7 +1244,8 @@
 	if (other->shutdown&RCV_SHUTDOWN)
 		goto out_unlock;
 
-	if (skb_queue_len(&other->receive_queue) > other->max_ack_backlog) {
+	if (unix_peer(other) != sk &&
+	    skb_queue_len(&other->receive_queue) > other->max_ack_backlog) {
 		if (!timeo) {
 			err = -EAGAIN;
 			goto out_unlock;
@@ -1640,7 +1666,6 @@
 	return 0;
 }
 
-		
 static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
@@ -1736,7 +1761,7 @@
 			s->socket ?
 			(s->state == TCP_ESTABLISHED ? SS_CONNECTED : SS_UNCONNECTED) :
 			(s->state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
-			s->socket ? s->socket->inode->i_ino : 0);
+			sock_i_ino(s));
 
 		if (s->protinfo.af_unix.addr)
 		{

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