patch-2.3.99-pre7 linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
Next file: linux/net/ipv4/netfilter/ip_conntrack_standalone.c
Previous file: linux/net/ipv4/netfilter/ip_conntrack_core.c
Back to the patch index
Back to the overall index
- Lines: 66
- Date:
Thu Apr 27 15:43:15 2000
- Orig file:
v2.3.99-pre6/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
- Orig date:
Wed Apr 26 16:34:09 2000
diff -u --recursive --new-file v2.3.99-pre6/linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c linux/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
@@ -23,6 +23,10 @@
/* FIXME: Examine ipfilter's timeouts and conntrack transitions more
closely. They're more complex. --RR */
+/* We steal a bit to indicate no reply yet (can't use status, because
+ it's set before we get into packet handling). */
+#define TCP_REPLY_BIT 0x1000
+
/* Actually, I believe that neither ipmasq (where this code is stolen
from) nor ipfilter do it exactly right. A new conntrack machine taking
into account packet loss (which creates uncertainty as to exactly
@@ -141,7 +145,7 @@
enum tcp_conntrack state;
READ_LOCK(&tcp_lock);
- state = conntrack->proto.tcp_state;
+ state = (conntrack->proto.tcp_state & ~TCP_REPLY_BIT);
READ_UNLOCK(&tcp_lock);
return sprintf(buffer, "%s ", tcp_conntrack_names[state]);
@@ -161,7 +165,7 @@
struct iphdr *iph, size_t len,
enum ip_conntrack_info ctinfo)
{
- enum tcp_conntrack newconntrack;
+ enum tcp_conntrack newconntrack, oldtcpstate;
struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
/* We're guaranteed to have the base header, but maybe not the
@@ -172,10 +176,11 @@
}
WRITE_LOCK(&tcp_lock);
+ oldtcpstate = conntrack->proto.tcp_state;
newconntrack
= tcp_conntracks
[CTINFO2DIR(ctinfo)]
- [get_conntrack_index(tcph)][conntrack->proto.tcp_state];
+ [get_conntrack_index(tcph)][oldtcpstate & ~TCP_REPLY_BIT];
/* Invalid */
if (newconntrack == TCP_CONNTRACK_MAX) {
@@ -187,9 +192,22 @@
}
conntrack->proto.tcp_state = newconntrack;
+ if ((oldtcpstate & TCP_REPLY_BIT)
+ || ctinfo >= IP_CT_IS_REPLY)
+ conntrack->proto.tcp_state |= TCP_REPLY_BIT;
+
WRITE_UNLOCK(&tcp_lock);
- ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
+ /* If only reply is a RST, we can consider ourselves not to
+ have an established connection: this is a fairly common
+ problem case, so we can delete the conntrack
+ immediately. --RR */
+ if (!(oldtcpstate & TCP_REPLY_BIT) && tcph->rst) {
+ if (del_timer(&conntrack->timeout))
+ conntrack->timeout.function((unsigned long)conntrack);
+ } else
+ ip_ct_refresh(conntrack, tcp_timeouts[newconntrack]);
+
return NF_ACCEPT;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)