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

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

diff -u --recursive --new-file v1.3.86/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
@@ -19,63 +19,63 @@
  *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  *		Jorge Cwik, <jorge@laser.satlink.net>
  *
- * Fixes:	
+ * Fixes:
  *		Alan Cox	:	Numerous verify_area() calls
  *		Alan Cox	:	Set the ACK bit on a reset
  *		Alan Cox	:	Stopped it crashing if it closed while
- *					sk->inuse=1 and was trying to connect 
+ *					sk->inuse=1 and was trying to connect
  *					(tcp_err()).
  *		Alan Cox	:	All icmp error handling was broken
  *					pointers passed where wrong and the
  *					socket was looked up backwards. Nobody
  *					tested any icmp error code obviously.
- *		Alan Cox	:	tcp_err() now handled properly. It 
- *					wakes people on errors. select 
+ *		Alan Cox	:	tcp_err() now handled properly. It
+ *					wakes people on errors. select
  *					behaves and the icmp error race
  *					has gone by moving it into sock.c
- *		Alan Cox	:	tcp_send_reset() fixed to work for 
- *					everything not just packets for 
+ *		Alan Cox	:	tcp_send_reset() fixed to work for
+ *					everything not just packets for
  *					unknown sockets.
  *		Alan Cox	:	tcp option processing.
- *		Alan Cox	:	Reset tweaked (still not 100%) [Had 
+ *		Alan Cox	:	Reset tweaked (still not 100%) [Had
  *					syn rule wrong]
  *		Herp Rosmanith  :	More reset fixes
- *		Alan Cox	:	No longer acks invalid rst frames. 
+ *		Alan Cox	:	No longer acks invalid rst frames.
  *					Acking any kind of RST is right out.
- *		Alan Cox	:	Sets an ignore me flag on an rst 
- *					receive otherwise odd bits of prattle 
+ *		Alan Cox	:	Sets an ignore me flag on an rst
+ *					receive otherwise odd bits of prattle
  *					escape still
- *		Alan Cox	:	Fixed another acking RST frame bug. 
+ *		Alan Cox	:	Fixed another acking RST frame bug.
  *					Should stop LAN workplace lockups.
- *		Alan Cox	: 	Some tidyups using the new skb list 
+ *		Alan Cox	: 	Some tidyups using the new skb list
  *					facilities
  *		Alan Cox	:	sk->keepopen now seems to work
  *		Alan Cox	:	Pulls options out correctly on accepts
  *		Alan Cox	:	Fixed assorted sk->rqueue->next errors
  *		Alan Cox	:	PSH doesn't end a TCP read. Switched a
  *					bit to skb ops.
- *		Alan Cox	:	Tidied tcp_data to avoid a potential 
+ *		Alan Cox	:	Tidied tcp_data to avoid a potential
  *					nasty.
- *		Alan Cox	:	Added some better commenting, as the 
+ *		Alan Cox	:	Added some better commenting, as the
  *					tcp is hard to follow
  *		Alan Cox	:	Removed incorrect check for 20 * psh
  *	Michael O'Reilly	:	ack < copied bug fix.
  *	Johannes Stille		:	Misc tcp fixes (not all in yet).
  *		Alan Cox	:	FIN with no memory -> CRASH
- *		Alan Cox	:	Added socket option proto entries. 
+ *		Alan Cox	:	Added socket option proto entries.
  *					Also added awareness of them to accept.
  *		Alan Cox	:	Added TCP options (SOL_TCP)
- *		Alan Cox	:	Switched wakeup calls to callbacks, 
- *					so the kernel can layer network 
+ *		Alan Cox	:	Switched wakeup calls to callbacks,
+ *					so the kernel can layer network
  *					sockets.
  *		Alan Cox	:	Use ip_tos/ip_ttl settings.
  *		Alan Cox	:	Handle FIN (more) properly (we hope).
- *		Alan Cox	:	RST frames sent on unsynchronised 
+ *		Alan Cox	:	RST frames sent on unsynchronised
  *					state ack error.
  *		Alan Cox	:	Put in missing check for SYN bit.
- *		Alan Cox	:	Added tcp_select_window() aka NET2E 
+ *		Alan Cox	:	Added tcp_select_window() aka NET2E
  *					window non shrink trick.
- *		Alan Cox	:	Added a couple of small NET2E timer 
+ *		Alan Cox	:	Added a couple of small NET2E timer
  *					fixes
  *		Charles Hedrick :	TCP fixes
  *		Toomas Tamm	:	TCP window fixes
@@ -89,7 +89,7 @@
  *		Adam Caldwell	:	Assorted timer/timing errors
  *		Matthew Dillon	:	Fixed another RST bug
  *		Alan Cox	:	Move to kernel side addressing changes.
- *		Alan Cox	:	Beginning work on TCP fastpathing 
+ *		Alan Cox	:	Beginning work on TCP fastpathing
  *					(not yet usable)
  *		Arnt Gulbrandsen:	Turbocharged tcp_check() routine.
  *		Alan Cox	:	TCP fast path debugging
@@ -97,21 +97,21 @@
  *		Michael Riepe	:	Bug in tcp_check()
  *		Matt Dillon	:	More TCP improvements and RST bug fixes
  *		Matt Dillon	:	Yet more small nasties remove from the
- *					TCP code (Be very nice to this man if 
+ *					TCP code (Be very nice to this man if
  *					tcp finally works 100%) 8)
- *		Alan Cox	:	BSD accept semantics. 
+ *		Alan Cox	:	BSD accept semantics.
  *		Alan Cox	:	Reset on closedown bug.
  *	Peter De Schrijver	:	ENOTCONN check missing in tcp_sendto().
- *		Michael Pall	:	Handle select() after URG properly in 
+ *		Michael Pall	:	Handle select() after URG properly in
  *					all cases.
- *		Michael Pall	:	Undo the last fix in tcp_read_urg() 
+ *		Michael Pall	:	Undo the last fix in tcp_read_urg()
  *					(multi URG PUSH broke rlogin).
- *		Michael Pall	:	Fix the multi URG PUSH problem in 
- *					tcp_readable(), select() after URG 
+ *		Michael Pall	:	Fix the multi URG PUSH problem in
+ *					tcp_readable(), select() after URG
  *					works now.
- *		Michael Pall	:	recv(...,MSG_OOB) never blocks in the 
+ *		Michael Pall	:	recv(...,MSG_OOB) never blocks in the
  *					BSD api.
- *		Alan Cox	:	Changed the semantics of sk->socket to 
+ *		Alan Cox	:	Changed the semantics of sk->socket to
  *					fix a race and a signal problem with
  *					accept() and async I/O.
  *		Alan Cox	:	Relaxed the rules on tcp_sendto().
@@ -128,23 +128,23 @@
  *		Alan Cox	:	Reset tracing code.
  *		Alan Cox	:	Spurious resets on shutdown.
  *		Alan Cox	:	Giant 15 minute/60 second timer error
- *		Alan Cox	:	Small whoops in selecting before an 
+ *		Alan Cox	:	Small whoops in selecting before an
  *					accept.
- *		Alan Cox	:	Kept the state trace facility since 
+ *		Alan Cox	:	Kept the state trace facility since
  *					it's handy for debugging.
  *		Alan Cox	:	More reset handler fixes.
- *		Alan Cox	:	Started rewriting the code based on 
- *					the RFC's for other useful protocol 
- *					references see: Comer, KA9Q NOS, and 
- *					for a reference on the difference 
+ *		Alan Cox	:	Started rewriting the code based on
+ *					the RFC's for other useful protocol
+ *					references see: Comer, KA9Q NOS, and
+ *					for a reference on the difference
  *					between specifications and how BSD
  *					works see the 4.4lite source.
- *		A.N.Kuznetsov	:	Don't time wait on completion of tidy 
+ *		A.N.Kuznetsov	:	Don't time wait on completion of tidy
  *					close.
  *		Linus Torvalds	:	Fin/Shutdown & copied_seq changes.
  *		Linus Torvalds	:	Fixed BSD port reuse to work first syn
- *		Alan Cox	:	Reimplemented timers as per the RFC 
- *					and using multiple timers for sanity. 
+ *		Alan Cox	:	Reimplemented timers as per the RFC
+ *					and using multiple timers for sanity.
  *		Alan Cox	:	Small bug fixes, and a lot of new
  *					comments.
  *		Alan Cox	:	Fixed dual reader crash by locking
@@ -164,7 +164,7 @@
  *		Alan Cox	:	Per route irtt.
  *		Matt Day	:	Select() match BSD precisely on error
  *		Alan Cox	:	New buffers
- *		Marc Tamsky	:	Various sk->prot->retransmits and 
+ *		Marc Tamsky	:	Various sk->prot->retransmits and
  *					sk->retransmits misupdating fixed.
  *					Fixed tcp_write_timeout: stuck close,
  *					and TCP syn retries gets used now.
@@ -180,14 +180,26 @@
  *		Alan Cox	:	Small hooks for enSKIP.
  *		Alexey Kuznetsov:	Path MTU discovery.
  *		Alan Cox	:	Support soft errors.
- *		Alan Cox	:	Fix MTU discovery pathalogical case
+ *		Alan Cox	:	Fix MTU discovery pathological case
  *					when the remote claims no mtu!
  *		Marc Tamsky	:	TCP_CLOSE fix.
- *		Colin (G3TNE)	:	Send a reset on syn ack replies in 
+ *		Colin (G3TNE)	:	Send a reset on syn ack replies in
  *					window but wrong (fixes NT lpd problems)
  *		Pedro Roque	:	Better TCP window handling, delayed ack.
- *		Joerg Reuter	:	No modification of locked buffers in 
+ *		Joerg Reuter	:	No modification of locked buffers in
  *					tcp_do_retransmit()
+ *		Eric Schenk	:	Changed receiver side silly window
+ *					avoidance algorithm to BSD style
+ *					algorithm. This doubles throughput
+ *					against machines running Solaris,
+ *					and seems to result in general
+ *					improvement.
+ *		Eric Schenk	:	Changed receiver side silly window
+ *					avoidance algorithm to BSD style
+ *					algorithm. This doubles throughput
+ *					against machines running Solaris,
+ *					and seems to result in general
+ *					improvement.
  *
  * To Fix:
  *		Fast path the code. Two things here - fix the window calculation
@@ -209,7 +221,7 @@
  *		tcp_data/tcp_read as well as the window shrink crud.
  *		Separate out duplicated code - tcp_alloc_skb, tcp_build_ack
  *		tcp_queue_skb seem obvious routines to extract.
- *	
+ *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
  *		as published by the Free Software Foundation; either version
@@ -246,7 +258,7 @@
  *	TCP_LAST_ACK		out side has shutdown after remote has
  *				shutdown.  There may still be data in our
  *				buffer that we have to finish sending
- *		
+ *
  *	TCP_CLOSE		socket is finished
  */
 
@@ -256,7 +268,7 @@
  * for violations and the like.  tcp.c is just too big... If I say something
  * "does?" or "doesn't?", it means I'm not sure, and will have to hash it out
  * with Alan. -- MS 950903
- * 
+ *
  * Use of PSH (4.2.2.2)
  *   MAY aggregate data sent without the PSH flag. (does)
  *   MAY queue data received without the PSH flag. (does)
@@ -266,12 +278,12 @@
  *     MUST set PSH on last segment (does)
  *   MAY pass received PSH to application layer (doesn't)
  *   SHOULD send maximum-sized segment whenever possible. (almost always does)
- * 
+ *
  * Window Size (4.2.2.3, 4.2.2.16)
  *   MUST treat window size as an unsigned number (does)
  *   SHOULD treat window size as a 32-bit number (does not)
  *   MUST NOT shrink window once it is offered (does not normally)
- *   
+ *
  * Urgent Pointer (4.2.2.4)
  * **MUST point urgent pointer to last byte of urgent data (not right
  *     after). (doesn't, to be like BSD)
@@ -282,11 +294,11 @@
  * **MUST support urgent data sequence of arbitrary length. (doesn't, but
  *   it's sort of tricky to fix, as urg_ptr is a 16-bit quantity)
  *	[Follows BSD 1 byte of urgent data]
- * 
+ *
  * TCP Options (4.2.2.5)
  *   MUST be able to receive TCP options in any segment. (does)
  *   MUST ignore unsupported options (does)
- *   
+ *
  * Maximum Segment Size Option (4.2.2.6)
  *   MUST implement both sending and receiving MSS. (does)
  *   SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
@@ -295,72 +307,72 @@
  *   MUST calculate "effective send MSS" correctly:
  *     min(physical_MTU, remote_MSS+20) - sizeof(tcphdr) - sizeof(ipopts)
  *     (does - but allows operator override)
- *  
+ *
  * TCP Checksum (4.2.2.7)
  *   MUST generate and check TCP checksum. (does)
- * 
+ *
  * Initial Sequence Number Selection (4.2.2.8)
  *   MUST use the RFC 793 clock selection mechanism.  (doesn't, but it's
  *     OK: RFC 793 specifies a 250KHz clock, while we use 1MHz, which is
  *     necessary for 10Mbps networks - and harder than BSD to spoof!)
- * 
+ *
  * Simultaneous Open Attempts (4.2.2.10)
  *   MUST support simultaneous open attempts (does)
- * 
+ *
  * Recovery from Old Duplicate SYN (4.2.2.11)
  *   MUST keep track of active vs. passive open (does)
- * 
+ *
  * RST segment (4.2.2.12)
  *   SHOULD allow an RST segment to contain data (does, but doesn't do
  *     anything with it, which is standard)
- * 
+ *
  * Closing a Connection (4.2.2.13)
- *   MUST inform application of whether connectin was closed by RST or
+ *   MUST inform application of whether connection was closed by RST or
  *     normal close. (does)
  *   MAY allow "half-duplex" close (treat connection as closed for the
  *     local app, even before handshake is done). (does)
  *   MUST linger in TIME_WAIT for 2 * MSL (does)
- * 
+ *
  * Retransmission Timeout (4.2.2.15)
  *   MUST implement Jacobson's slow start and congestion avoidance
- *     stuff. (does) 
- * 
+ *     stuff. (does)
+ *
  * Probing Zero Windows (4.2.2.17)
  *   MUST support probing of zero windows. (does)
  *   MAY keep offered window closed indefinitely. (does)
  *   MUST allow remote window to stay closed indefinitely. (does)
- * 
+ *
  * Passive Open Calls (4.2.2.18)
  *   MUST NOT let new passive open affect other connections. (doesn't)
  *   MUST support passive opens (LISTENs) concurrently. (does)
- *   
+ *
  * Time to Live (4.2.2.19)
  *   MUST make TCP TTL configurable. (does - IP_TTL option)
- * 
+ *
  * Event Processing (4.2.2.20)
  *   SHOULD queue out-of-order segments. (does)
  *   MUST aggregate ACK segments whenever possible. (does but badly)
- *   
+ *
  * Retransmission Timeout Calculation (4.2.3.1)
  *   MUST implement Karn's algorithm and Jacobson's algorithm for RTO
  *     calculation. (does, or at least explains them in the comments 8*b)
  *  SHOULD initialize RTO to 0 and RTT to 3. (does)
- * 
+ *
  * When to Send an ACK Segment (4.2.3.2)
  *   SHOULD implement delayed ACK. (does)
  *   MUST keep ACK delay < 0.5 sec. (does)
- * 
+ *
  * When to Send a Window Update (4.2.3.3)
  *   MUST implement receiver-side SWS. (does)
- *   
+ *
  * When to Send Data (4.2.3.4)
  *   MUST implement sender-side SWS. (does)
  *   SHOULD implement Nagle algorithm. (does)
- * 
+ *
  * TCP Connection Failures (4.2.3.5)
  *  MUST handle excessive retransmissions "properly" (see the RFC). (does)
  *   SHOULD inform application layer of soft errors. (does)
- *   
+ *
  * TCP Keep-Alives (4.2.3.6)
  *   MAY provide keep-alives. (does)
  *   MUST make keep-alives configurable on a per-connection basis. (does)
@@ -370,19 +382,19 @@
  *   MUST NOT interpret failure to ACK keep-alive packet as dead
  *     connection. (doesn't)
  *   SHOULD send keep-alive with no data. (does)
- * 
+ *
  * TCP Multihoming (4.2.3.7)
  *   MUST get source address from IP layer before sending first
  *     SYN. (does)
  *   MUST use same local address for all segments of a connection. (does)
- * 
+ *
  * IP Options (4.2.3.8)
  *   MUST ignore unsupported IP options. (does)
  *   MAY support Time Stamp and Record Route. (does)
  *   MUST allow application to specify a source route. (does)
- *   MUST allow receieved Source Route option to set route for all future
+ *   MUST allow received Source Route option to set route for all future
  *     segments on this connection. (does not (security issues))
- * 
+ *
  * ICMP messages (4.2.3.9)
  *   MUST act on ICMP errors. (does)
  *   MUST slow transmission upon receipt of a Source Quench. (does)
@@ -393,20 +405,20 @@
  *     application. (does)
  *   SHOULD abort connection upon receipt of hard Destination Unreachable
  *     messages (2, 3, 4). (does)
- * 
+ *
  * Remote Address Validation (4.2.3.10)
  *   MUST reject as an error OPEN for invalid remote IP address. (does)
  *   MUST ignore SYN with invalid source address. (does)
  *   MUST silently discard incoming SYN for broadcast/multicast
- *     address. (does) 
- * 
+ *     address. (does)
+ *
  * Asynchronous Reports (4.2.4.1)
  * MUST provide mechanism for reporting soft errors to application
  *     layer. (does)
- * 
+ *
  * Type of Service (4.2.4.2)
  *   MUST allow application layer to set Type of Service. (does IP_TOS)
- * 
+ *
  * (Whew. -- MS 950903)
  **/
 
@@ -433,7 +445,7 @@
 /*
  *	Find someone to 'accept'. Must be called with
  *	the socket locked or with interrupts disabled
- */ 
+ */
 
 static struct sk_buff *tcp_find_established(struct sock *s)
 {
@@ -460,7 +472,7 @@
 	struct sk_buff *skb;
 	unsigned long flags;
 	save_flags(flags);
-	cli(); 
+	cli();
 	skb=tcp_find_established(s);
 	if(skb!=NULL)
 		skb_unlink(skb);	/* Take it off the queue */
@@ -468,17 +480,17 @@
 	return skb;
 }
 
-/* 
+/*
  *	This routine closes sockets which have been at least partially
  *	opened, but not yet accepted. Currently it is only called by
- *	tcp_close, and timeout mirrors the value there. 
+ *	tcp_close, and timeout mirrors the value there.
  */
 
-static void tcp_close_pending (struct sock *sk) 
+static void tcp_close_pending (struct sock *sk)
 {
 	struct sk_buff *skb;
 
-	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) 
+	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
 	{
 		tcp_close(skb->sk, 0);
 		kfree_skb(skb, FREE_READ);
@@ -487,7 +499,7 @@
 }
 
 /*
- *	Enter the time wait state. 
+ *	Enter the time wait state.
  */
 
 void tcp_time_wait(struct sock *sk)
@@ -514,20 +526,20 @@
 {
 	struct tcphdr *th = (struct tcphdr *)header;
 	struct sock *sk;
-	
+
 	/*
 	 *	This one is _WRONG_. FIXME urgently.
 	 */
-#ifndef CONFIG_NO_PATH_MTU_DISCOVERY	 
+#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
 	struct iphdr *iph=(struct iphdr *)(header-sizeof(struct iphdr));
-#endif  
+#endif
 	th =(struct tcphdr *)header;
 	sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr);
 
-	if (sk == NULL) 
+	if (sk == NULL)
 		return;
-  
-	if (type == ICMP_SOURCE_QUENCH) 
+
+	if (type == ICMP_SOURCE_QUENCH)
 	{
 		/*
 		 * FIXME:
@@ -538,7 +550,7 @@
 			sk->cong_window--;
 		return;
 	}
-	
+
 	if (type == ICMP_PARAMETERPROB)
 	{
 		sk->err=EPROTO;
@@ -573,11 +585,11 @@
 	 */
 
 	if (code < 13)
-	{	
+	{
 		if(icmp_err_convert[code].fatal || sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
 		{
 			sk->err = icmp_err_convert[code].errno;
-			if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV) 
+			if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
 			{
 				tcp_statistics.TcpAttemptFails++;
 				tcp_set_state(sk,TCP_CLOSE);
@@ -612,29 +624,29 @@
 	if (sk == NULL || (skb = skb_peek(&sk->receive_queue)) == NULL)
 	{
 		restore_flags(flags);
-	  	if(sk && sk->debug) 
+	  	if(sk && sk->debug)
 	  		printk("empty\n");
 	  	return(0);
 	}
-  
+
 	counted = sk->copied_seq;	/* Where we are at the moment */
 	amount = 0;
-  
-	/* 
-	 *	Do until a push or until we are out of data. 
+
+	/*
+	 *	Do until a push or until we are out of data.
 	 */
-	 
-	do 
+
+	do
 	{
 		if (before(counted, skb->seq))	 	/* Found a hole so stops here */
 			break;
 		sum = skb->len - (counted - skb->seq);	/* Length - header but start from where we are up to (avoid overlaps) */
 		if (skb->h.th->syn)
 			sum++;
-		if (sum > 0) 
+		if (sum > 0)
 		{					/* Add it up, move on */
 			amount += sum;
-			if (skb->h.th->syn) 
+			if (skb->h.th->syn)
 				amount--;
 			counted += sum;
 		}
@@ -707,7 +719,7 @@
 
 		if (sk->shutdown & RCV_SHUTDOWN)
 			return 1;
-			
+
 		if (sk->acked_seq == sk->copied_seq)
 			break;
 
@@ -720,7 +732,7 @@
 	case SEL_OUT:
 		if (sk->err)
 			return 1;
-		if (sk->shutdown & SEND_SHUTDOWN) 
+		if (sk->shutdown & SEND_SHUTDOWN)
 			return 0;
 		if (sk->state == TCP_SYN_SENT || sk->state == TCP_SYN_RECV)
 			break;
@@ -745,7 +757,7 @@
 int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
 	int err;
-	switch(cmd) 
+	switch(cmd)
 	{
 
 		case TIOCINQ:
@@ -755,7 +767,7 @@
 		{
 			unsigned long amount;
 
-			if (sk->state == TCP_LISTEN) 
+			if (sk->state == TCP_LISTEN)
 				return(-EINVAL);
 
 			lock_sock(sk);
@@ -796,13 +808,13 @@
 
 
 /*
- *	This routine computes a TCP checksum. 
+ *	This routine computes a TCP checksum.
  *
  *	Modified January 1995 from a go-faster DOS routine by
  *	Jorge Cwik <jorge@laser.satlink.net>
  */
 #undef DEBUG_TCP_CHECK
-void tcp_send_check(struct tcphdr *th, unsigned long saddr, 
+void tcp_send_check(struct tcphdr *th, unsigned long saddr,
 		unsigned long daddr, int len, struct sk_buff *skb)
 {
 #ifdef DEBUG_TCP_CHECK
@@ -829,22 +841,17 @@
 }
 
 
-/* 
- *	This routine builds a generic TCP header. 
+/*
+ *	This routine builds a generic TCP header.
  */
- 
-extern __inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
-{
 
+static inline int tcp_build_header(struct tcphdr *th, struct sock *sk, int push)
+{
 	memcpy(th,(void *) &(sk->dummy_th), sizeof(*th));
+	th->psh = (push == 0) ? 1 : 0;
 	th->seq = htonl(sk->write_seq);
-	th->psh =(push == 0) ? 1 : 0;
-	sk->ack_backlog = 0;
-	sk->bytes_rcv = 0;
-	sk->ack_timed = 0;
 	th->ack_seq = htonl(sk->acked_seq);
-	sk->window = tcp_select_window(sk);
-	th->window = htons(sk->window);
+	th->window = htons(tcp_select_window(sk));
 
 	return(sizeof(*th));
 }
@@ -855,10 +862,10 @@
 static void wait_for_tcp_connect(struct sock * sk)
 {
 	release_sock(sk);
-	cli();			
-	if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT && sk->err == 0) 
+	cli();
+	if (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT && sk->err == 0)
     	{
-		interruptible_sleep_on(sk->sleep);	
+		interruptible_sleep_on(sk->sleep);
 	}
 	sti();
 	lock_sock(sk);
@@ -873,7 +880,7 @@
 	cli();
 	if (sk->wmem_alloc*2 > sk->sndbuf &&
 	    (sk->state == TCP_ESTABLISHED||sk->state == TCP_CLOSE_WAIT)
-		&& sk->err == 0) 
+		&& sk->err == 0)
 	{
 		sk->socket->flags &= ~SO_NOSPACE;
 		interruptible_sleep_on(sk->sleep);
@@ -901,65 +908,65 @@
 	struct proto *prot;
 	struct device *dev = NULL;
 	unsigned char *from;
-	
+
 	/*
 	 *	Ok commence sending
 	 */
-	
+
 	while(iovct<msg->msg_iovlen)
 	{
 		seglen=msg->msg_iov[iovct].iov_len;
 		from=msg->msg_iov[iovct++].iov_base;
 		prot = sk->prot;
-		while(seglen > 0) 
+		while(seglen > 0)
 		{
 			/*
 			 * Stop on errors
 			 */
-			if (sk->err) 
+			if (sk->err)
 			{
-				if (copied) 
+				if (copied)
 					return copied;
 				return sock_error(sk);
 			}
 
 			/*
-			 *	Make sure that we are established. 
+			 *	Make sure that we are established.
 			 */
-			if (sk->shutdown & SEND_SHUTDOWN) 
+			if (sk->shutdown & SEND_SHUTDOWN)
 			{
 				if (copied)
 					return copied;
 				return -EPIPE;
 			}
 
-			/* 
+			/*
 			 *	Wait for a connection to finish.
 			 */
-			while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT) 
+			while (sk->state != TCP_ESTABLISHED && sk->state != TCP_CLOSE_WAIT)
 			{
 				if (copied)
 					return copied;
 
-				if (sk->err) 
+				if (sk->err)
 					return sock_error(sk);
-	
+
 				if (sk->state != TCP_SYN_SENT && sk->state != TCP_SYN_RECV)
 				{
 					if (sk->keepopen)
 						send_sig(SIGPIPE, current, 0);
 					return -EPIPE;
 				}
-	
+
 				if (nonblock)
 					return -EAGAIN;
 
 				if (current->signal & ~current->blocked)
 					return -ERESTARTSYS;
-	
+
 				wait_for_tcp_connect(sk);
 			}
-	
+
 		/*
 		 * The following code can result in copy <= if sk->mss is ever
 		 * decreased.  It shouldn't be.  sk->mss is min(sk->mtu, sk->max_window).
@@ -971,9 +978,9 @@
 		 * before the exchange of SYN's.  If the initial ack from the other
 		 * end has a window of 0, max_window and thus mss will both be 0.
 		 */
-	
-		/* 
-		 *	Now we need to check if we have a half built packet. 
+
+		/*
+		 *	Now we need to check if we have a half built packet.
 		 */
 #ifndef CONFIG_NO_PATH_MTU_DISCOVERY
 		/*
@@ -981,7 +988,7 @@
 		 *		but it works... I do not know why 8) --ANK
 		 *
 		 *	Really, we should rebuild all the queues...
-		 *	It's difficult. Temprorary hack is to send all
+		 *	It's difficult. Temporary hack is to send all
 		 *	queued segments with allowed fragmentation.
 		 */
 		{
@@ -993,18 +1000,18 @@
 			}
 		}
 #endif
-	
-			if ((skb = tcp_dequeue_partial(sk)) != NULL) 
+
+			if ((skb = tcp_dequeue_partial(sk)) != NULL)
 			{
 				int tcp_size;
 
 				tcp_size = skb->tail - (unsigned char *)(skb->h.th + 1);
-	
+
 				/* Add more stuff to the end of skb->len */
-				if (!(flags & MSG_OOB)) 
+				if (!(flags & MSG_OOB))
 				{
 					copy = min(sk->mss - tcp_size, seglen);
-					if (copy <= 0) 
+					if (copy <= 0)
 					{
 						printk("TCP: **bug**: \"copy\" <= 0\n");
 				  		return -EFAULT;
@@ -1031,7 +1038,7 @@
 	 	 *   host, don't use it.  This is sender side
 	 	 *   silly window prevention, as specified in RFC1122.
 	 	 *   (Note that this is different than earlier versions of
-		 *   SWS prevention, e.g. RFC813.).  What we actually do is 
+		 *   SWS prevention, e.g. RFC813.).  What we actually do is
 		 *   use the whole MSS.  Since the results in the right
 		 *   edge of the packet being outside the window, it will
 		 *   be queued for later rather than sent.
@@ -1042,37 +1049,37 @@
 				copy = sk->mss;
 			if (copy > seglen)
 				copy = seglen;
-			if (copy <= 0) 
+			if (copy <= 0)
 			{
 				printk("TCP: **bug**: copy=%d, sk->mss=%d\n", copy, sk->mss);
 		  		return -EFAULT;
 			}
 
 		/*
-		 *	We should really check the window here also. 
+		 *	We should really check the window here also.
 		 */
-		 
+
 			send_tmp = NULL;
-			if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out) 
+			if (copy < sk->mss && !(flags & MSG_OOB) && sk->packets_out)
 			{
 				skb = sock_wmalloc(sk, sk->mtu + 128 + prot->max_header + 15, 0, GFP_KERNEL);
 				send_tmp = skb;
-			} 
-			else 
+			}
+			else
 			{
 				skb = sock_wmalloc(sk, copy + prot->max_header + 15 , 0, GFP_KERNEL);
 			}
-	
+
 			/*
-			 *	If we didn't get any memory, we need to sleep. 
+			 *	If we didn't get any memory, we need to sleep.
 			 */
-	
-			if (skb == NULL) 
+
+			if (skb == NULL)
 			{
 				sk->socket->flags |= SO_NOSPACE;
-				if (nonblock) 
+				if (nonblock)
 				{
-					if (copied) 
+					if (copied)
 						return copied;
 					return -EAGAIN;
 				}
@@ -1091,18 +1098,18 @@
 			skb->sk = sk;
 			skb->free = 0;
 			skb->localroute = sk->localroute|(flags&MSG_DONTROUTE);
-	
+
 			/*
 			 * FIXME: we need to optimize this.
 			 * Perhaps some hints here would be good.
 			 */
-		
+
 			tmp = prot->build_header(skb, sk->saddr, sk->daddr, &dev,
 				 IPPROTO_TCP, sk->opt, skb->truesize,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache);
-			if (tmp < 0 ) 
+			if (tmp < 0 )
 			{
 				sock_wfree(sk, skb);
-				if (copied) 
+				if (copied)
 					return(copied);
 				return(tmp);
 			}
@@ -1112,15 +1119,15 @@
 			skb->dev = dev;
 			skb->h.th =(struct tcphdr *)skb_put(skb,sizeof(struct tcphdr));
 			tmp = tcp_build_header(skb->h.th, sk, seglen-copy);
-			if (tmp < 0) 
+			if (tmp < 0)
 			{
 				sock_wfree(sk, skb);
-				if (copied) 
+				if (copied)
 					return(copied);
 				return(tmp);
 			}
-	
-			if (flags & MSG_OOB) 
+
+			if (flags & MSG_OOB)
 			{
 				skb->h.th->urg = 1;
 				skb->h.th->urg_ptr = ntohs(copy);
@@ -1128,15 +1135,15 @@
 
 			skb->csum = csum_partial_copy_fromuser(from,
 				skb_put(skb,copy), copy, 0);
-		
+
 			from += copy;
 			copied += copy;
 			len -= copy;
 			seglen -= copy;
 			skb->free = 0;
 			sk->write_seq += copy;
-		
-			if (send_tmp != NULL) 
+
+			if (send_tmp != NULL)
 			{
 				tcp_enqueue_partial(send_tmp, sk);
 				continue;
@@ -1158,7 +1165,7 @@
 	/*
 	 *	Do sanity checking for sendmsg/sendto/send
 	 */
-	 
+
 	if (flags & ~(MSG_OOB|MSG_DONTROUTE))
 		goto out;
 	if (msg->msg_name) {
@@ -1166,15 +1173,15 @@
 
 		if (msg->msg_namelen < sizeof(*addr))
 			goto out;
-		if (addr->sin_family && addr->sin_family != AF_INET) 
+		if (addr->sin_family && addr->sin_family != AF_INET)
 			goto out;
 		retval = -ENOTCONN;
 		if(sk->state == TCP_CLOSE)
 			goto out;
 		retval = -EISCONN;
-		if (addr->sin_port != sk->dummy_th.dest) 
+		if (addr->sin_port != sk->dummy_th.dest)
 			goto out;
-		if (addr->sin_addr.s_addr != sk->daddr) 
+		if (addr->sin_addr.s_addr != sk->daddr)
 			goto out;
 	}
 
@@ -1202,17 +1209,17 @@
 out:
 	return retval;
 }
-	
+
 
 /*
- *	Send an ack if one is backlogged at this point. 
+ *	Send an ack if one is backlogged at this point.
  *
- *      This is called for delayed acks also.
+ *	This is called for delayed acks also.
  */
- 
+
 void tcp_read_wakeup(struct sock *sk)
 {
-	if (!sk->ack_backlog) 
+	if (!sk->ack_backlog)
 		return;
 
 	/*
@@ -1220,7 +1227,7 @@
 	 * from the closed destination.
 	 */
 	if ((sk->state == TCP_CLOSE) || (sk->state == TCP_TIME_WAIT))
-		return; 
+		return;
 
 	tcp_send_ack(sk);
 }
@@ -1230,7 +1237,7 @@
  *	Handle reading urgent data. BSD has very simple semantics for
  *	this, no blocking and very strange errors 8)
  */
- 
+
 static int tcp_recv_urg(struct sock * sk, int nonblock,
 	     struct msghdr *msg, int len, int flags, int *addr_len)
 {
@@ -1239,13 +1246,13 @@
 	 */
 	if (sk->urginline || !sk->urg_data || sk->urg_data == URG_READ)
 		return -EINVAL;	/* Yes this is right ! */
-		
-	if (sk->err) 
+
+	if (sk->err)
 		return sock_error(sk);
-		
-	if (sk->state == TCP_CLOSE || sk->done) 
+
+	if (sk->state == TCP_CLOSE || sk->done)
 	{
-		if (!sk->done) 
+		if (!sk->done)
 		{
 			sk->done = 1;
 			return 0;
@@ -1253,13 +1260,13 @@
 		return -ENOTCONN;
 	}
 
-	if (sk->shutdown & RCV_SHUTDOWN) 
+	if (sk->shutdown & RCV_SHUTDOWN)
 	{
 		sk->done = 1;
 		return 0;
 	}
 	lock_sock(sk);
-	if (sk->urg_data & URG_VALID) 
+	if (sk->urg_data & URG_VALID)
 	{
 		char c = sk->urg_data;
 		if (!(flags & MSG_PEEK))
@@ -1278,7 +1285,7 @@
 		return 1;
 	}
 	release_sock(sk);
-	
+
 	/*
 	 * Fixed the recv(..., MSG_OOB) behaviour.  BSD docs and
 	 * the available implementations agree in this case:
@@ -1294,7 +1301,7 @@
  *	must be called with interrupts disabled or with the
  *	socket locked so that the sk_buff queue operation is ok.
  */
- 
+
 static inline void tcp_eat_skb(struct sock *sk, struct sk_buff * skb)
 {
 	skb->sk = sk;
@@ -1303,38 +1310,37 @@
 }
 
 /*
- * 	FIXME:
- * 	This routine frees used buffers.
- * 	It should consider sending an ACK to let the
- * 	other end know we now have a bigger window.
+ *	FIXME:
+ *	This routine frees used buffers.
+ *	It should consider sending an ACK to let the
+ *	other end know we now have a bigger window.
  */
 
 static void cleanup_rbuf(struct sock *sk)
 {
-	struct sk_buff *skb;
-
 	/*
 	 * NOTE! The socket must be locked, so that we don't get
 	 * a messed-up receive queue.
 	 */
-	while ((skb=skb_peek(&sk->receive_queue)) != NULL) {
+	while (!skb_queue_empty(&sk->receive_queue)) {
+		struct sk_buff *skb = sk->receive_queue.next;
 		if (!skb->used || skb->users)
 			break;
 		tcp_eat_skb(sk, skb);
 	}
 
-	/* If we raised the window due to cleaning up, tell the world.. */
-	if (tcp_raise_window(sk)) {
-		sk->ack_backlog++;
-		tcp_read_wakeup(sk);
-	}
-} 
+	/*
+	 * Tell the world if we raised the window.
+	 */
+	if (tcp_raise_window(sk))
+		tcp_send_ack(sk);
+}
 
 
 /*
- *	This routine copies from a sock struct into the user buffer. 
+ *	This routine copies from a sock struct into the user buffer.
  */
- 
+
 static int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
 	int len, int nonblock, int flags, int *addr_len)
 {
@@ -1344,26 +1350,26 @@
 	volatile u32 *seq;	/* So gcc doesn't overoptimise */
 	unsigned long used;
 
-	/* 
-	 *	This error should be checked. 
+	/*
+	 *	This error should be checked.
 	 */
-	 
+
 	if (sk->state == TCP_LISTEN)
 		return -ENOTCONN;
 
 	/*
-	 *	Urgent data needs to be handled specially. 
+	 *	Urgent data needs to be handled specially.
 	 */
-	 
+
 	if (flags & MSG_OOB)
 		return tcp_recv_urg(sk, nonblock, msg, len, flags, addr_len);
 
 	/*
 	 *	Copying sequence to update. This is volatile to handle
-	 *	the multi-reader case neatly (memcpy_to/fromfs might be 
+	 *	the multi-reader case neatly (memcpy_to/fromfs might be
 	 *	inline and thus not flush cached variables otherwise).
 	 */
-	 
+
 	peek_seq = sk->copied_seq;
 	seq = &sk->copied_seq;
 	if (flags & MSG_PEEK)
@@ -1371,15 +1377,15 @@
 
 	add_wait_queue(sk->sleep, &wait);
 	lock_sock(sk);
-	while (len > 0) 
+	while (len > 0)
 	{
 		struct sk_buff * skb;
 		u32 offset;
-	
+
 		/*
 		 * Are we at urgent data? Stop if we have read anything.
 		 */
-		 
+
 		if (copied && sk->urg_data && sk->urg_seq == *seq)
 			break;
 
@@ -1397,11 +1403,11 @@
 		/*
 		 *	Next get a buffer.
 		 */
-		 
+
 		current->state = TASK_INTERRUPTIBLE;
 
 		skb = skb_peek(&sk->receive_queue);
-		do 
+		do
 		{
 			if (!skb)
 				break;
@@ -1423,15 +1429,15 @@
 		if (copied)
 			break;
 
-		if (sk->err) 
+		if (sk->err)
 		{
 			copied = sock_error(sk);
 			break;
 		}
 
-		if (sk->state == TCP_CLOSE) 
+		if (sk->state == TCP_CLOSE)
 		{
-			if (!sk->done) 
+			if (!sk->done)
 			{
 				sk->done = 1;
 				break;
@@ -1440,13 +1446,13 @@
 			break;
 		}
 
-		if (sk->shutdown & RCV_SHUTDOWN) 
+		if (sk->shutdown & RCV_SHUTDOWN)
 		{
 			sk->done = 1;
 			break;
 		}
-			
-		if (nonblock) 
+
+		if (nonblock)
 		{
 			copied = -EAGAIN;
 			break;
@@ -1463,32 +1469,32 @@
 	found_ok_skb:
 		/*
 		 *	Lock the buffer. We can be fairly relaxed as
-		 *	an interrupt will never steal a buffer we are 
+		 *	an interrupt will never steal a buffer we are
 		 *	using unless I've missed something serious in
 		 *	tcp_data.
 		 */
-		
+
 		skb->users++;
-		
+
 		/*
-		 *	Ok so how much can we use ? 
+		 *	Ok so how much can we use ?
 		 */
-		 
+
 		used = skb->len - offset;
 		if (len < used)
 			used = len;
 		/*
-		 *	Do we have urgent data here? 
+		 *	Do we have urgent data here?
 		 */
-		
-		if (sk->urg_data) 
+
+		if (sk->urg_data)
 		{
 			u32 urg_offset = sk->urg_seq - *seq;
-			if (urg_offset < used) 
+			if (urg_offset < used)
 			{
-				if (!urg_offset) 
+				if (!urg_offset)
 				{
-					if (!sk->urginline) 
+					if (!sk->urginline)
 					{
 						++*seq;
 						offset++;
@@ -1499,12 +1505,12 @@
 					used = urg_offset;
 			}
 		}
-		
+
 		/*
 		 *	Copy it - We _MUST_ update *seq first so that we
 		 *	don't ever double read when we have dual readers
 		 */
-		 
+
 		*seq += used;
 
 		/*
@@ -1512,25 +1518,25 @@
 		 *	do a second read it relies on the skb->users to avoid
 		 *	a crash when cleanup_rbuf() gets called.
 		 */
-		 
+
 		memcpy_toiovec(msg->msg_iov,((unsigned char *)skb->h.th) +
 			skb->h.th->doff*4 + offset, used);
 		copied += used;
 		len -= used;
-		
+
 		/*
 		 *	We now will not sleep again until we are finished
 		 *	with skb. Sorry if you are doing the SMP port
 		 *	but you'll just have to fix it neatly ;)
 		 */
-		 
+
 		skb->users --;
-		
+
 		if (after(sk->copied_seq,sk->urg_seq))
 			sk->urg_data = 0;
 		if (used + offset < skb->len)
 			continue;
-		
+
 		/*
 		 *	Process the FIN.
 		 */
@@ -1541,24 +1547,24 @@
 			continue;
 		skb->used = 1;
 		if (!skb->users)
-			tcp_eat_skb(sk, skb);		
+			tcp_eat_skb(sk, skb);
 		continue;
 
 	found_fin_ok:
 		++*seq;
 		if (flags & MSG_PEEK)
 			break;
-			
+
 		/*
 		 *	All is done
 		 */
-		 
+
 		skb->used = 1;
 		sk->shutdown |= RCV_SHUTDOWN;
 		break;
 
 	}
-	
+
 	if(copied>0 && msg->msg_name)
 	{
 		struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
@@ -1568,7 +1574,7 @@
 	}
 	if(addr_len)
 		*addr_len=sizeof(struct sockaddr_in);
-		
+
 	remove_wait_queue(sk->sleep, &wait);
 	current->state = TASK_RUNNING;
 
@@ -1582,11 +1588,11 @@
 
 /*
  *	State processing on a close. This implements the state shift for
- *	sending our FIN frame. Note that we only send a FIN for some 
+ *	sending our FIN frame. Note that we only send a FIN for some
  *	states. A shutdown() may have already sent the FIN, or we may be
  *	closed.
  */
- 
+
 static int tcp_close_state(struct sock *sk, int dead)
 {
 	int ns=TCP_CLOSE;
@@ -1613,9 +1619,9 @@
 			ns=TCP_LAST_ACK;
 			send_fin=1;
 	}
-	
+
 	tcp_set_state(sk,ns);
-		
+
 	/*
 	 *	This is a (useful) BSD violating of the RFC. There is a
 	 *	problem with TCP as specified in that the other end could
@@ -1633,7 +1639,7 @@
 		else
 			tcp_reset_msl_timer(sk, TIME_CLOSE, TCP_FIN_TIMEOUT);
 	}
-	
+
 	return send_fin;
 }
 
@@ -1650,18 +1656,18 @@
 	 *		Tim MacKenzie(tym@dibbler.cs.monash.edu.au) 4 Dec '92.
 	 */
 
-	if (!(how & SEND_SHUTDOWN)) 
+	if (!(how & SEND_SHUTDOWN))
 		return;
-	 
+
 	/*
 	 *	If we've already sent a FIN, or it's a closed state
 	 */
-	 
+
 	if (sk->state == TCP_FIN_WAIT1 ||
 	    sk->state == TCP_FIN_WAIT2 ||
 	    sk->state == TCP_CLOSING ||
 	    sk->state == TCP_LAST_ACK ||
-	    sk->state == TCP_TIME_WAIT || 
+	    sk->state == TCP_TIME_WAIT ||
 	    sk->state == TCP_CLOSE ||
 	    sk->state == TCP_LISTEN
 	  )
@@ -1677,19 +1683,19 @@
 	sk->shutdown |= SEND_SHUTDOWN;
 
 	/*
-	 *  Clear out any half completed packets. 
+	 *  Clear out any half completed packets.
 	 */
 
 	if (sk->partial)
 		tcp_send_partial(sk);
-		
+
 	/*
 	 *	FIN if needed
 	 */
-	 
+
 	if (tcp_close_state(sk,0))
 		tcp_send_fin(sk);
-		
+
 	release_sock(sk);
 }
 
@@ -1697,7 +1703,7 @@
 /*
  *	Return 1 if we still have things to send in our buffers.
  */
- 
+
 static inline int closing(struct sock * sk)
 {
 	switch (sk->state) {
@@ -1715,12 +1721,12 @@
 	struct sk_buff *skb;
 
 	/*
-	 * We need to grab some memory, and put together a FIN,	
+	 * We need to grab some memory, and put together a FIN,
 	 * and then put it into the queue to be sent.
 	 */
-	
+
 	lock_sock(sk);
-	
+
 	tcp_cache_zap();
 	if(sk->state == TCP_LISTEN)
 	{
@@ -1731,11 +1737,11 @@
 		sk->dead = 1;
 		return;
 	}
-	
+
 	sk->keepopen = 1;
 	sk->shutdown = SHUTDOWN_MASK;
 
-	if (!sk->dead) 
+	if (!sk->dead)
 	  	sk->state_change(sk);
 
 	/*
@@ -1743,22 +1749,22 @@
 	 *  descriptor close, not protocol-sourced closes, because the
 	 *  reader process may not have drained the data yet!
 	 */
-		 
+
 	while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
 		kfree_skb(skb, FREE_READ);
 
 	/*
-	 *	Get rid off any half-completed packets. 
+	 *	Get rid off any half-completed packets.
 	 */
 
-	if (sk->partial) 
+	if (sk->partial)
 		tcp_send_partial(sk);
-		
+
 	/*
 	 *	Timeout is not the same thing - however the code likes
 	 *	to send both the same way (sigh).
 	 */
-	 
+
 	if (tcp_close_state(sk,1)==1)
 	{
 		tcp_send_fin(sk);
@@ -1771,7 +1777,7 @@
 		while(closing(sk) && current->timeout)
 		{
 			interruptible_sleep_on(sk->sleep);
-			if (current->signal & ~current->blocked) 
+			if (current->signal & ~current->blocked)
 			{
 				break;
 			}
@@ -1792,32 +1798,32 @@
 
 
 /*
- *	This will accept the next outstanding connection. 
+ *	This will accept the next outstanding connection.
  */
- 
+
 static struct sock *tcp_accept(struct sock *sk, int flags)
 {
 	struct sock *newsk;
 	struct sk_buff *skb;
-  
+
   /*
    * We need to make sure that this socket is listening,
    * and that it has something pending.
    */
 
-	if (sk->state != TCP_LISTEN) 
+	if (sk->state != TCP_LISTEN)
 	{
 		sk->err = EINVAL;
-		return(NULL); 
+		return(NULL);
 	}
 
 	/* Avoid the race. */
 	cli();
 	lock_sock(sk);
 
-	while((skb = tcp_dequeue_established(sk)) == NULL) 
+	while((skb = tcp_dequeue_established(sk)) == NULL)
 	{
-		if (flags & O_NONBLOCK) 
+		if (flags & O_NONBLOCK)
 		{
 			sti();
 			release_sock(sk);
@@ -1827,7 +1833,7 @@
 
 		release_sock(sk);
 		interruptible_sleep_on(sk->sleep);
-		if (current->signal & ~current->blocked) 
+		if (current->signal & ~current->blocked)
 		{
 			sti();
 			sk->err = ERESTARTSYS;
@@ -1838,7 +1844,7 @@
 	sti();
 
 	/*
-	 *	Now all we need to do is return skb->sk. 
+	 *	Now all we need to do is return skb->sk.
 	 */
 
 	newsk = skb->sk;
@@ -1850,9 +1856,9 @@
 }
 
 /*
- *	This will initiate an outgoing connection. 
+ *	This will initiate an outgoing connection.
  */
- 
+
 static int tcp_connect(struct sock *sk, struct sockaddr_in *usin, int addr_len)
 {
 	struct sk_buff *buff;
@@ -1863,47 +1869,48 @@
 	struct tcphdr *t1;
 	struct rtable *rt;
 
-	if (sk->state != TCP_CLOSE) 
+	if (sk->state != TCP_CLOSE)
 		return(-EISCONN);
 
 	/*
 	 *	Don't allow a double connect.
 	 */
-	 	
+
 	if(sk->daddr)
 		return -EINVAL;
-	
-	if (addr_len < 8) 
+
+	if (addr_len < 8)
 		return(-EINVAL);
 
-	if (usin->sin_family && usin->sin_family != AF_INET) 
+	if (usin->sin_family && usin->sin_family != AF_INET)
 		return(-EAFNOSUPPORT);
 
   	/*
   	 *	connect() to INADDR_ANY means loopback (BSD'ism).
   	 */
-  	
+
   	if(usin->sin_addr.s_addr==INADDR_ANY)
 		usin->sin_addr.s_addr=ip_my_addr();
-		  
+
 	/*
-	 *	Don't want a TCP connection going to a broadcast address 
+	 *	Don't want a TCP connection going to a broadcast address
 	 */
 
-	if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST) 
+	if ((atype=ip_chk_addr(usin->sin_addr.s_addr)) == IS_BROADCAST || atype==IS_MULTICAST)
 		return -ENETUNREACH;
-  
+
 	lock_sock(sk);
 	sk->daddr = usin->sin_addr.s_addr;
 	sk->write_seq = tcp_init_seq();
 	sk->window_seq = sk->write_seq;
 	sk->rcv_ack_seq = sk->write_seq -1;
+	sk->rcv_ack_cnt = 1;
 	sk->err = 0;
 	sk->dummy_th.dest = usin->sin_port;
 	release_sock(sk);
 
 	buff = sock_wmalloc(sk,MAX_SYN_SIZE,0, GFP_KERNEL);
-	if (buff == NULL) 
+	if (buff == NULL)
 	{
 		return(-ENOMEM);
 	}
@@ -1911,15 +1918,15 @@
 	buff->sk = sk;
 	buff->free = 0;
 	buff->localroute = sk->localroute;
-	
+
 
 	/*
 	 *	Put in the IP header and routing stuff.
 	 */
-	 
+
 	tmp = sk->prot->build_header(buff, sk->saddr, sk->daddr, &dev,
 		IPPROTO_TCP, NULL, MAX_SYN_SIZE,sk->ip_tos,sk->ip_ttl,&sk->ip_route_cache);
-	if (tmp < 0) 
+	if (tmp < 0)
 	{
 		sock_wfree(sk, buff);
 		release_sock(sk);
@@ -1941,7 +1948,7 @@
 	t1->syn = 1;
 	t1->doff = 6;
 	/* use 512 or whatever user asked for */
-	
+
 	if(rt!=NULL && (rt->rt_flags&RTF_WINDOW))
 		sk->window_clamp=rt->rt_window;
 	else
@@ -1951,20 +1958,20 @@
 		sk->mtu = sk->user_mss;
 	else if (rt)
 		sk->mtu = rt->rt_mtu - sizeof(struct iphdr) - sizeof(struct tcphdr);
-	else 
+	else
 		sk->mtu = 576 - sizeof(struct iphdr) - sizeof(struct tcphdr);
 
 	/*
-	 *	but not bigger than device MTU 
+	 *	but not bigger than device MTU
 	 */
 
 	if(sk->mtu <32)
 		sk->mtu = 32;	/* Sanity limit */
-		
+
 	sk->mtu = min(sk->mtu, dev->mtu - sizeof(struct iphdr) - sizeof(struct tcphdr));
 
 #ifdef CONFIG_SKIP
-	
+
 	/*
 	 *	SKIP devices set their MTU to 65535. This is so they can take packets
 	 *	unfragmented to security process then fragment. They could lie to the
@@ -1973,13 +1980,13 @@
 	 *
 	 *	[IPHDR][IPSP][Security data][Modified TCP data][Security data]
 	 */
-	 
+
 	if(skip_pick_mtu!=NULL)		/* If SKIP is loaded.. */
 		sk->mtu=skip_pick_mtu(sk->mtu,dev);
 #endif
-	
+
 	/*
-	 *	Put in the TCP options to say MTU. 
+	 *	Put in the TCP options to say MTU.
 	 */
 
 	ptr = skb_put(buff,4);
@@ -1992,7 +1999,7 @@
 		  sizeof(struct tcphdr) + 4, buff);
 
 	/*
-	 *	This must go first otherwise a really quick response will get reset. 
+	 *	This must go first otherwise a really quick response will get reset.
 	 */
 
 	tcp_cache_zap();
@@ -2001,25 +2008,27 @@
 		sk->rto = rt->rt_irtt;
 	else
 		sk->rto = TCP_TIMEOUT_INIT;
-	sk->retransmit_timer.function=&tcp_retransmit_timer;
+	sk->delack_timer.function = tcp_delack_timer;
+	sk->delack_timer.data = (unsigned long) sk;
+	sk->retransmit_timer.function = tcp_retransmit_timer;
 	sk->retransmit_timer.data = (unsigned long)sk;
 	tcp_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 
+	sk->retransmits = 0;				/* Now works the right way instead of a hacked
 											initial setting */
 
-	sk->prot->queue_xmit(sk, dev, buff, 0);  
+	sk->prot->queue_xmit(sk, dev, buff, 0);
 	tcp_reset_xmit_timer(sk, TIME_WRITE, sk->rto);
 	tcp_statistics.TcpActiveOpens++;
 	tcp_statistics.TcpOutSegs++;
-  
+
 	release_sock(sk);
 	return(0);
 }
 
 /*
- *	Socket option code for TCP. 
+ *	Socket option code for TCP.
  */
-  
+
 int tcp_setsockopt(struct sock *sk, int level, int optname, char *optval, int optlen)
 {
 	int val,err;
@@ -2027,13 +2036,13 @@
 	if(level!=SOL_TCP)
 		return ip_setsockopt(sk,level,optname,optval,optlen);
 
-  	if (optval == NULL) 
+  	if (optval == NULL)
   		return(-EINVAL);
 
   	err=verify_area(VERIFY_READ, optval, sizeof(int));
   	if(err)
   		return err;
-  	
+
   	val = get_user((int *)optval);
 
 	switch(optname)
@@ -2062,7 +2071,7 @@
 
 	if(level!=SOL_TCP)
 		return ip_getsockopt(sk,level,optname,optval,optlen);
-			
+
 	switch(optname)
 	{
 		case TCP_MAXSEG:
@@ -2085,7 +2094,7 @@
   	put_user(val,(int *)optval);
 
   	return(0);
-}	
+}
 
 
 struct proto tcp_prot = {

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