]> git.hungrycats.org Git - linux/commitdiff
[NETFILTER]: Fix conntrack bug introduced by list_del change.
authorHarald Welte <laforge@netfilter.org>
Sun, 2 Mar 2003 17:25:50 +0000 (09:25 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Sun, 2 Mar 2003 17:25:50 +0000 (09:25 -0800)
include/linux/netfilter_ipv4/ip_conntrack.h
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_proto_tcp.c
net/ipv4/netfilter/ip_conntrack_proto_udp.c
net/ipv4/netfilter/ip_conntrack_standalone.c

index b32550bfb69ce8ae34a6b1deb81a87f5cbbe5116..6908061d0debcfcfce3b4e688431ba50ac687979 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/config.h>
 #include <linux/netfilter_ipv4/ip_conntrack_tuple.h>
+#include <linux/bitops.h>
 #include <asm/atomic.h>
 
 enum ip_conntrack_info
@@ -41,6 +42,10 @@ enum ip_conntrack_status {
        /* Conntrack should never be early-expired. */
        IPS_ASSURED_BIT = 2,
        IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+       /* Connection is confirmed: originating packet has left box */
+       IPS_CONFIRMED_BIT = 3,
+       IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
 };
 
 #include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
@@ -159,7 +164,7 @@ struct ip_conntrack
        struct ip_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
 
        /* Have we seen traffic both ways yet? (bitset) */
-       volatile unsigned long status;
+       unsigned long status;
 
        /* Timer function; drops refcnt when it goes off. */
        struct timer_list timeout;
@@ -255,7 +260,7 @@ ip_ct_selective_cleanup(int (*kill)(const struct ip_conntrack *i, void *data),
 /* It's confirmed if it is, or has been in the hash table. */
 static inline int is_confirmed(struct ip_conntrack *ct)
 {
-       return ct->tuplehash[IP_CT_DIR_ORIGINAL].list.next != NULL;
+       return test_bit(IPS_CONFIRMED_BIT, &ct->status);
 }
 
 extern unsigned int ip_conntrack_htable_size;
index ebb576ec62cec61533554212f4b98b50010a4b6b..6cd6013e2ecbcfccd99769590b483179737a0c10 100644 (file)
@@ -290,9 +290,6 @@ clean_from_lists(struct ip_conntrack *ct)
 {
        DEBUGP("clean_from_lists(%p)\n", ct);
        MUST_BE_WRITE_LOCKED(&ip_conntrack_lock);
-       /* Remove from both hash lists: must not NULL out next ptrs,
-           otherwise we'll look unconfirmed.  Fortunately, LIST_DELETE
-           doesn't do this. --RR */
        LIST_DELETE(&ip_conntrack_hash
                    [hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)],
                    &ct->tuplehash[IP_CT_DIR_ORIGINAL]);
@@ -465,6 +462,7 @@ __ip_conntrack_confirm(struct nf_ct_info *nfct)
                ct->timeout.expires += jiffies;
                add_timer(&ct->timeout);
                atomic_inc(&ct->ct_general.use);
+               set_bit(IPS_CONFIRMED_BIT, &ct->status);
                WRITE_UNLOCK(&ip_conntrack_lock);
                return NF_ACCEPT;
        }
@@ -583,7 +581,7 @@ icmp_error_track(struct sk_buff *skb,
    connection.  Too bad: we're in trouble anyway. */
 static inline int unreplied(const struct ip_conntrack_tuple_hash *i)
 {
-       return !(i->ctrack->status & IPS_ASSURED);
+       return !(test_bit(IPS_ASSURED_BIT, &i->ctrack->status));
 }
 
 static int early_drop(struct list_head *chain)
@@ -718,7 +716,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple,
                        conntrack, expected);
                /* Welcome, Mr. Bond.  We've been expecting you... */
                IP_NF_ASSERT(master_ct(conntrack));
-               conntrack->status = IPS_EXPECTED;
+               __set_bit(IPS_EXPECTED_BIT, &conntrack->status);
                conntrack->master = expected;
                expected->sibling = conntrack;
                LIST_DELETE(&ip_conntrack_expect_list, expected);
@@ -766,11 +764,11 @@ resolve_normal_ct(struct sk_buff *skb,
                *set_reply = 1;
        } else {
                /* Once we've had two way comms, always ESTABLISHED. */
-               if (h->ctrack->status & IPS_SEEN_REPLY) {
+               if (test_bit(IPS_SEEN_REPLY_BIT, &h->ctrack->status)) {
                        DEBUGP("ip_conntrack_in: normal packet for %p\n",
                               h->ctrack);
                        *ctinfo = IP_CT_ESTABLISHED;
-               } else if (h->ctrack->status & IPS_EXPECTED) {
+               } else if (test_bit(IPS_EXPECTED_BIT, &h->ctrack->status)) {
                        DEBUGP("ip_conntrack_in: related packet for %p\n",
                               h->ctrack);
                        *ctinfo = IP_CT_RELATED;
index c6d70ff4a5a4e291656d9b64154d399f3235b3b3..585806b4b11b407fe55f834b379da6bce59e8cd3 100644 (file)
@@ -190,7 +190,7 @@ static int tcp_packet(struct ip_conntrack *conntrack,
           have an established connection: this is a fairly common
           problem case, so we can delete the conntrack
           immediately.  --RR */
-       if (!(conntrack->status & IPS_SEEN_REPLY) && tcph->rst) {
+       if (!test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status) && tcph->rst) {
                WRITE_UNLOCK(&tcp_lock);
                if (del_timer(&conntrack->timeout))
                        conntrack->timeout.function((unsigned long)conntrack);
index 57e807026c18582e5bcb0ce7efc974098d1fde3e..bb4b8787d546e4e393807e50065d7fdd9562bc63 100644 (file)
@@ -51,7 +51,7 @@ static int udp_packet(struct ip_conntrack *conntrack,
 {
        /* If we've seen traffic both ways, this is some kind of UDP
           stream.  Extend timeout. */
-       if (conntrack->status & IPS_SEEN_REPLY) {
+       if (test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)) {
                ip_ct_refresh(conntrack, UDP_STREAM_TIMEOUT);
                /* Also, more likely to be important, and not a probe */
                set_bit(IPS_ASSURED_BIT, &conntrack->status);
index f64800e8bc6d3e8024e1a5e926cd1bd804abb470..3b6cd1628dfd4eda5cd3d95ae229d51d93a16d75 100644 (file)
@@ -76,7 +76,7 @@ print_expect(char *buffer, const struct ip_conntrack_expect *expect)
 }
 
 static unsigned int
-print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
+print_conntrack(char *buffer, struct ip_conntrack *conntrack)
 {
        unsigned int len;
        struct ip_conntrack_protocol *proto
@@ -94,12 +94,12 @@ print_conntrack(char *buffer, const struct ip_conntrack *conntrack)
        len += print_tuple(buffer + len,
                           &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
                           proto);
-       if (!(conntrack->status & IPS_SEEN_REPLY))
+       if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
                len += sprintf(buffer + len, "[UNREPLIED] ");
        len += print_tuple(buffer + len,
                           &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
                           proto);
-       if (conntrack->status & IPS_ASSURED)
+       if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
                len += sprintf(buffer + len, "[ASSURED] ");
        len += sprintf(buffer + len, "use=%u ",
                       atomic_read(&conntrack->ct_general.use));