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);