Commit 7a85bd22 authored by Harald Welte's avatar Harald Welte Committed by David S. Miller

[NETFILTER]: Fix conntrack bug introduced by list_del change.

parent 1bf453b3
......@@ -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;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment