patch-2.2.4 linux/net/ipv4/af_inet.c
Next file: linux/net/ipv4/arp.c
Previous file: linux/net/ipv4/Config.in
Back to the patch index
Back to the overall index
- Lines: 99
- Date:
Sun Mar 21 07:22:00 1999
- Orig file:
v2.2.3/linux/net/ipv4/af_inet.c
- Orig date:
Tue Feb 23 15:21:35 1999
diff -u --recursive --new-file v2.2.3/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.83 1999/02/22 13:54:18 davem Exp $
+ * Version: $Id: af_inet.c,v 1.85 1999/03/21 05:22:28 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -53,6 +53,7 @@
* David S. Miller : New socket lookup architecture.
* Some other random speedups.
* Cyrus Durgin : Cleaned up file for kmod hacks.
+ * Andi Kleen : Fix inet_stream_connect TCP race.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -175,8 +176,6 @@
if(sk->opt)
kfree(sk->opt);
dst_release(sk->dst_cache);
- if (atomic_read(&sk->omem_alloc))
- printk(KERN_DEBUG "kill_sk_now: optmem leakage (%d bytes) detected.\n", atomic_read(&sk->omem_alloc));
sk_free(sk);
}
@@ -613,15 +612,16 @@
}
if(sock->state == SS_CONNECTING) {
+ /* Note: tcp_connected contains SYN_RECV, which may cause
+ bogus results here. -AK */
if(tcp_connected(sk->state)) {
sock->state = SS_CONNECTED;
return 0;
}
- if(sk->protocol == IPPROTO_TCP && (flags & O_NONBLOCK)) {
- if(sk->err)
- return sock_error(sk);
+ if (sk->zapped || sk->err)
+ goto sock_error;
+ if (flags & O_NONBLOCK)
return -EALREADY;
- }
} else {
/* We may need to bind the socket. */
if (inet_autobind(sk) != 0)
@@ -629,15 +629,17 @@
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
+ the wait queue setup should be moved before the low level
+ connect call. -AK*/
if (err < 0)
return(err);
sock->state = SS_CONNECTING;
}
- if (sk->state > TCP_FIN_WAIT2 && sock->state == SS_CONNECTING) {
- sock->state = SS_UNCONNECTED;
- return sock_error(sk);
- }
+ if (sk->state > TCP_FIN_WAIT2 && sock->state == SS_CONNECTING)
+ goto sock_error;
if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
return (-EINPROGRESS);
@@ -649,17 +651,19 @@
}
sock->state = SS_CONNECTED;
- if ((sk->state != TCP_ESTABLISHED) && sk->err) {
- /* This is ugly but needed to fix a race in the ICMP error handler */
- if (sk->protocol == IPPROTO_TCP && sk->zapped) {
- lock_sock(sk);
- tcp_set_state(sk, TCP_CLOSE);
- release_sock(sk);
- }
- sock->state = SS_UNCONNECTED;
- return sock_error(sk);
- }
+ if ((sk->state != TCP_ESTABLISHED) && sk->err)
+ goto sock_error;
return(0);
+
+sock_error:
+ /* This is ugly but needed to fix a race in the ICMP error handler */
+ if (sk->zapped && sk->state != TCP_CLOSE) {
+ lock_sock(sk);
+ tcp_set_state(sk, TCP_CLOSE);
+ release_sock(sk);
+ }
+ sock->state = SS_UNCONNECTED;
+ return sock_error(sk);
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)