Actually, try the attached patch.  it's a first try at solving the problem
from the first approach (see the SYN, delete old, make new...)
I don't know what problems/bugs it will introduce elsewhere yet O:-)

Darren

Index: ip_state.c
===================================================================
RCS file: /devel/CVS/IP-Filter/ip_state.c,v
retrieving revision 2.186.2.52
diff -c -r2.186.2.52 ip_state.c
*** ip_state.c  2 Feb 2007 22:50:32 -0000       2.186.2.52
--- ip_state.c  3 Mar 2007 01:29:25 -0000
***************
*** 171,176 ****
--- 171,177 ----
        ips_iptq,
        ips_icmptq,
        ips_icmpacktq,
+       ips_deletetq,
        *ips_utqe = NULL;
  #ifdef        IPFILTER_LOG
  int   ipstate_logging = 1;
***************
*** 276,282 ****
        ips_iptq.ifq_head = NULL;
        ips_iptq.ifq_tail = &ips_iptq.ifq_head;
        MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab");
!       ips_iptq.ifq_next = NULL;
  
        RWLOCK_INIT(&ipf_state, "ipf IP state rwlock");
        MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex");
--- 277,289 ----
        ips_iptq.ifq_head = NULL;
        ips_iptq.ifq_tail = &ips_iptq.ifq_head;
        MUTEX_INIT(&ips_iptq.ifq_lock, "ipftq ip tab");
!       ips_iptq.ifq_next = &ips_deletetq;
!       ips_deletetq.ifq_ttl = (u_long)1;
!       ips_deletetq.ifq_ref = 1;
!       ips_deletetq.ifq_head = NULL;
!       ips_deletetq.ifq_tail = &ips_deletetq.ifq_head;
!       MUTEX_INIT(&ips_deletetq.ifq_lock, "state delete queue");
!       ips_deletetq.ifq_next = NULL;
  
        RWLOCK_INIT(&ipf_state, "ipf IP state rwlock");
        MUTEX_INIT(&ipf_stinsert, "ipf state insert mutex");
***************
*** 327,332 ****
--- 334,340 ----
                MUTEX_DESTROY(&ips_udpacktq.ifq_lock);
                MUTEX_DESTROY(&ips_icmpacktq.ifq_lock);
                MUTEX_DESTROY(&ips_iptq.ifq_lock);
+               MUTEX_DESTROY(&ips_deletetq.ifq_lock);
        }
  
        if (ips_table != NULL) {
***************
*** 1394,1399 ****
--- 1402,1423 ----
        tdata = &is->is_tcp.ts_data[source];
  
        MUTEX_ENTER(&is->is_lock);
+ 
+       /*
+        * If a SYN packet is received for a connection that is on the way out
+        * but hasn't yet departed then advance this session along the way.
+        */
+       if ((tcp->th_flags & TH_OPENING) == TH_SYN) {
+               if ((is->is_state[0] > IPF_TCPS_ESTABLISHED) &&
+                   (is->is_state[1] > IPF_TCPS_ESTABLISHED)) {
+                       is->is_state[!source] = IPF_TCPS_CLOSED;
+                       fr_movequeue(&is->is_sti, is->is_sti.tqe_ifq,
+                                    &ips_deletetq);
+                       MUTEX_ENTER(&is->is_lock);
+                       return 0;
+               }
+       }
+ 
        if (fr_tcpinwindow(fin, fdata, tdata, tcp, is->is_flags)) {
  #ifdef        IPFILTER_SCAN
                if (is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER)) {
***************
*** 1444,1451 ****
  
                }
                ret = 1;
!       } else
                fin->fin_flx |= FI_OOW;
        MUTEX_EXIT(&is->is_lock);
        return ret;
  }
--- 1468,1476 ----
  
                }
                ret = 1;
!       } else {
                fin->fin_flx |= FI_OOW;
+       }
        MUTEX_EXIT(&is->is_lock);
        return ret;
  }
***************
*** 2352,2357 ****
--- 2377,2389 ----
                hvm = DOUBLE_HASH(hv);
                for (isp = &ips_table[hvm]; ((is = *isp) != NULL); ) {
                        isp = &is->is_hnext;
+                       /*
+                        * If a connection is about to be deleted, no packets
+                        * are allowed to match it.
+                        */
+                       if (is->is_sti.tqe_ifq == &ips_deletetq)
+                               continue;
+ 
                        if ((is->is_p != pr) || (is->is_v != v))
                                continue;
                        is = fr_matchsrcdst(fin, is, &src, &dst, NULL, FI_CMP);

Reply via email to