--- tcp_in.c	2009-04-23 15:17:15.890625000 +0200
+++ tcp_in_new.c	2009-04-24 13:32:58.484375000 +0200
@@ -506,7 +506,6 @@
   struct tcp_seg *rseg;
   u8_t acceptable = 0;
   err_t err;
-  u8_t accepted_inseq;
 
   err = ERR_OK;
 
@@ -626,11 +625,11 @@
         old_cwnd = pcb->cwnd;
         /* If there was any data contained within this ACK,
          * we'd better pass it on to the application as well. */
-        accepted_inseq = tcp_receive(pcb);
+        tcp_receive(pcb);
 
         pcb->cwnd = ((old_cwnd == 1) ? (pcb->mss * 2) : pcb->mss);
 
-        if ((flags & TCP_FIN) && accepted_inseq) {
+        if (recv_flags & TF_GOT_FIN) {
           tcp_ack_now(pcb);
           pcb->state = CLOSE_WAIT;
         }
@@ -649,16 +648,16 @@
   case CLOSE_WAIT:
     /* FALLTHROUGH */
   case ESTABLISHED:
-    accepted_inseq = tcp_receive(pcb);
-    if ((flags & TCP_FIN) && accepted_inseq) { /* passive close */
+    tcp_receive(pcb);
+    if (recv_flags & TF_GOT_FIN) { /* passive close */
       tcp_ack_now(pcb);
       pcb->state = CLOSE_WAIT;
     }
     break;
   case FIN_WAIT_1:
     tcp_receive(pcb);
-    if (flags & TCP_FIN) {
-      if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+    if (recv_flags & TF_GOT_FIN) {
+      if (flags & TCP_ACK && ackno == pcb->snd_max) {
         LWIP_DEBUGF(TCP_DEBUG,
           ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
         tcp_ack_now(pcb);
@@ -670,13 +669,13 @@
         tcp_ack_now(pcb);
         pcb->state = CLOSING;
       }
-    } else if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+    } else if (flags & TCP_ACK && ackno == pcb->snd_max) {
       pcb->state = FIN_WAIT_2;
     }
     break;
   case FIN_WAIT_2:
     tcp_receive(pcb);
-    if (flags & TCP_FIN) {
+    if (recv_flags & TF_GOT_FIN) {
       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
       tcp_ack_now(pcb);
       tcp_pcb_purge(pcb);
@@ -687,7 +686,7 @@
     break;
   case CLOSING:
     tcp_receive(pcb);
-    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+    if (flags & TCP_ACK && ackno == pcb->snd_max) {
       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
       tcp_ack_now(pcb);
       tcp_pcb_purge(pcb);
@@ -698,7 +697,7 @@
     break;
   case LAST_ACK:
     tcp_receive(pcb);
-    if (flags & TCP_ACK && ackno == pcb->snd_nxt) {
+    if (flags & TCP_ACK && ackno == pcb->snd_max) {
       LWIP_DEBUGF(TCP_DEBUG, ("TCP connection closed %"U16_F" -> %"U16_F".\n", inseg.tcphdr->src, inseg.tcphdr->dest));
       /* bugfix #21699: don't set pcb->state to CLOSED here or we risk leaking segments */
       recv_flags = TF_CLOSED;
@@ -1068,6 +1067,7 @@
                segment. */
             inseg.len = (u16_t)(pcb->ooseq->tcphdr->seqno - seqno);
             pbuf_realloc(inseg.p, inseg.len);
+            tcplen = TCP_TCPLEN(&inseg);
           } else {
             /* does the ooseq segment contain only flags that are in inseg also? */
             if ((TCPH_FLAGS(inseg.tcphdr) & (TCP_FIN|TCP_SYN)) ==
@@ -1080,14 +1080,7 @@
         }
 #endif /* TCP_QUEUE_OOSEQ */
 
-        tcplen = TCP_TCPLEN(&inseg);
-
-        /* First received FIN will be ACKed +1, on any successive (duplicate)
-         * FINs we are already in CLOSE_WAIT and have already done +1.
-         */
-        if (pcb->state != CLOSE_WAIT) {
-          pcb->rcv_nxt += tcplen;
-        }
+        pcb->rcv_nxt += tcplen;
 
         /* Update the receiver's (our) window. */
         if (pcb->rcv_wnd < tcplen) {
@@ -1150,9 +1143,6 @@
           if (TCPH_FLAGS(cseg->tcphdr) & TCP_FIN) {
             LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_receive: dequeued FIN.\n"));
             recv_flags = TF_GOT_FIN;
-            if (pcb->state == ESTABLISHED) { /* force passive close or we can move to active close */
-              pcb->state = CLOSE_WAIT;
-            } 
           }
 
 
