Bug#332231: Backport of ipt_recent.c
Hi,
I ran into the same problem and made a backport of ipt_recent.c for
Sarge's 2.6.8. It was actually pretty simple to backport. Attached is
the diff against the ipt_recent.c source file from Philipp's comment of
6 Jul 2006.
The backported module is already running in one of my systems. Works as
expected so far.
I'll be grateful for any feedback.
Martin
--- ipt_recent.c 2007-02-20 21:57:51.000000000 +0100
+++ kernel-source-2.6.8/net/ipv4/netfilter/ipt_recent.c 2007-02-22 22:02:11.118926120 +0100
@@ -68,8 +68,8 @@ struct recent_table {
};
static LIST_HEAD(tables);
-static DEFINE_SPINLOCK(recent_lock);
-static DEFINE_MUTEX(recent_mutex);
+static spinlock_t recent_lock = SPIN_LOCK_UNLOCKED;
+static DECLARE_MUTEX(recent_mutex);
#ifdef CONFIG_PROC_FS
static struct proc_dir_entry *proc_dir;
@@ -166,8 +166,8 @@ static void recent_table_flush(struct re
static int
ipt_recent_match(const struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
- const struct xt_match *match, const void *matchinfo,
- int offset, unsigned int protoff, int *hotdrop)
+ const void *matchinfo,
+ int offset, int *hotdrop)
{
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
@@ -233,13 +233,14 @@ out:
}
static int
-ipt_recent_checkentry(const char *tablename, const void *ip,
- const struct xt_match *match, void *matchinfo,
+ipt_recent_checkentry(const char *tablename, const struct ipt_ip *ip,
+ void *matchinfo,
unsigned int matchsize, unsigned int hook_mask)
{
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
unsigned i;
+ unsigned tlen = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size;
int ret = 0;
if (hweight8(info->check_set &
@@ -253,7 +254,7 @@ ipt_recent_checkentry(const char *tablen
strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
return 0;
- mutex_lock(&recent_mutex);
+ down(&recent_mutex);
t = recent_table_lookup(info->name);
if (t != NULL) {
t->refcnt++;
@@ -261,10 +262,10 @@ ipt_recent_checkentry(const char *tablen
goto out;
}
- t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
- GFP_KERNEL);
+ t = kmalloc(tlen, GFP_KERNEL);
if (t == NULL)
goto out;
+ memset(t, 0, tlen);
t->refcnt = 1;
strcpy(t->name, info->name);
INIT_LIST_HEAD(&t->lru_list);
@@ -284,18 +285,18 @@ ipt_recent_checkentry(const char *tablen
spin_unlock_bh(&recent_lock);
ret = 1;
out:
- mutex_unlock(&recent_mutex);
+ up(&recent_mutex);
return ret;
}
static void
-ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
+ipt_recent_destroy(void *matchinfo,
unsigned int matchsize)
{
const struct ipt_recent_info *info = matchinfo;
struct recent_table *t;
- mutex_lock(&recent_mutex);
+ down(&recent_mutex);
t = recent_table_lookup(info->name);
if (--t->refcnt == 0) {
spin_lock_bh(&recent_lock);
@@ -307,7 +308,7 @@ ipt_recent_destroy(const struct xt_match
#endif
kfree(t);
}
- mutex_unlock(&recent_mutex);
+ up(&recent_mutex);
}
#ifdef CONFIG_PROC_FS
@@ -383,9 +384,10 @@ static int recent_seq_open(struct inode
struct recent_iter_state *st;
int ret;
- st = kzalloc(sizeof(*st), GFP_KERNEL);
+ st = kmalloc(sizeof(*st), GFP_KERNEL);
if (st == NULL)
return -ENOMEM;
+ memset(st, 0, sizeof(*st));
ret = seq_open(file, &recent_seq_ops);
if (ret)
kfree(st);
@@ -462,7 +464,6 @@ static struct file_operations recent_fop
static struct ipt_match recent_match = {
.name = "recent",
.match = ipt_recent_match,
- .matchsize = sizeof(struct ipt_recent_info),
.checkentry = ipt_recent_checkentry,
.destroy = ipt_recent_destroy,
.me = THIS_MODULE,
Reply to: