patch-2.3.4 linux/net/ipv4/tcp_input.c
Next file: linux/net/ipv4/tcp_ipv4.c
Previous file: linux/net/ipv4/tcp.c
Back to the patch index
Back to the overall index
- Lines: 125
- Date:
Mon May 31 22:07:43 1999
- Orig file:
v2.3.3/linux/net/ipv4/tcp_input.c
- Orig date:
Sat May 15 23:46:05 1999
diff -u --recursive --new-file v2.3.3/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.165 1999/05/14 23:10:08 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.167 1999/05/29 22:37:54 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -914,8 +914,11 @@
extern void tcp_tw_reschedule(struct tcp_tw_bucket *tw);
extern void tcp_tw_deschedule(struct tcp_tw_bucket *tw);
+/* Must be called only from BH context. */
void tcp_timewait_kill(struct tcp_tw_bucket *tw)
{
+ SOCKHASH_LOCK_WRITE_BH();
+
/* Unlink from various places. */
if(tw->bind_next)
tw->bind_next->bind_pprev = tw->bind_pprev;
@@ -933,6 +936,8 @@
tw->sklist_next->sklist_prev = tw->sklist_prev;
tw->sklist_prev->sklist_next = tw->sklist_next;
+ SOCKHASH_UNLOCK_WRITE_BH();
+
/* Ok, now free it up. */
kmem_cache_free(tcp_timewait_cachep, tw);
}
@@ -963,6 +968,7 @@
struct sock *sk;
struct tcp_func *af_specific = tw->af_specific;
__u32 isn;
+ int ret;
isn = tw->rcv_nxt + 128000;
if(isn == 0)
@@ -971,14 +977,25 @@
tcp_timewait_kill(tw);
sk = af_specific->get_sock(skb, th);
if(sk == NULL ||
- !ipsec_sk_policy(sk,skb) ||
- atomic_read(&sk->sock_readers) != 0)
+ !ipsec_sk_policy(sk,skb))
return 0;
+
+ bh_lock_sock(sk);
+
+ /* Default is to discard the frame. */
+ ret = 0;
+
+ if(sk->lock.users)
+ goto out_unlock;
+
skb_set_owner_r(skb, sk);
af_specific = sk->tp_pinfo.af_tcp.af_specific;
+
if(af_specific->conn_request(sk, skb, isn) < 0)
- return 1; /* Toss a reset back. */
- return 0; /* Discard the frame. */
+ ret = 1; /* Toss a reset back. */
+ out_unlock:
+ bh_unlock_sock(sk);
+ return ret;
}
/* Check RST or SYN */
@@ -1031,7 +1048,7 @@
sk->prot->inuse--;
/* Step 4: Hash TW into TIMEWAIT half of established hash table. */
- head = &tcp_established_hash[sk->hashent + (TCP_HTABLE_SIZE/2)];
+ head = &tcp_ehash[sk->hashent + (tcp_ehash_size >> 1)];
sktw = (struct sock *)tw;
if((sktw->next = *head) != NULL)
(*head)->pprev = &sktw->next;
@@ -1069,7 +1086,9 @@
}
#endif
/* Linkage updates. */
+ SOCKHASH_LOCK_WRITE();
tcp_tw_hashdance(sk, tw);
+ SOCKHASH_UNLOCK_WRITE();
/* Get the TIME_WAIT timeout firing. */
tcp_tw_schedule(tw);
@@ -1819,7 +1838,7 @@
}
}
- flg = *(((u32 *)th) + 3) & ~htonl(0x8 << 16);
+ flg = *(((u32 *)th) + 3) & ~htonl(0xFC8 << 16);
/* pred_flags is 0xS?10 << 16 + snd_wnd
* if header_predition is to be made
@@ -2049,8 +2068,26 @@
/* These use the socket TOS..
* might want to be the received TOS
*/
- if(th->ack)
- return 1;
+ if(th->ack) {
+ struct sock *realsk;
+ int ret;
+
+ realsk = tp->af_specific->get_sock(skb, th);
+ if(realsk == sk)
+ return 1;
+
+ bh_lock_sock(realsk);
+ ret = 0;
+ if(realsk->lock.users != 0) {
+ skb_orphan(skb);
+ sk_add_backlog(realsk, skb);
+ } else {
+ ret = tcp_rcv_state_process(realsk, skb,
+ skb->h.th, skb->len);
+ }
+ bh_unlock_sock(realsk);
+ return ret;
+ }
if(th->syn) {
if(tp->af_specific->conn_request(sk, skb, 0) < 0)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)