[NET]: Make the device list and device lookups per namespace.
[safe/jmp/linux-2.6] / net / ipv4 / netfilter / ipt_recent.c
index 682c094..db2a798 100644 (file)
@@ -12,6 +12,7 @@
  * Copyright 2002-2003, Stephen Frost, 2.5.x port by laforge@netfilter.org
  */
 #include <linux/init.h>
+#include <linux/ip.h>
 #include <linux/moduleparam.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -23,8 +24,9 @@
 #include <linux/bitops.h>
 #include <linux/skbuff.h>
 #include <linux/inet.h>
+#include <net/net_namespace.h>
 
-#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ipt_recent.h>
 
 MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
@@ -50,11 +52,10 @@ MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/ipt_recent/* files");
 MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/ipt_recent/* files");
 MODULE_PARM_DESC(ip_list_gid,"owning group of /proc/net/ipt_recent/* files");
 
-
 struct recent_entry {
        struct list_head        list;
        struct list_head        lru_list;
-       u_int32_t               addr;
+       __be32                  addr;
        u_int8_t                ttl;
        u_int8_t                index;
        u_int16_t               nstamps;
@@ -79,23 +80,23 @@ static DEFINE_MUTEX(recent_mutex);
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry   *proc_dir;
-static struct file_operations  recent_fops;
+static const struct file_operations    recent_fops;
 #endif
 
 static u_int32_t hash_rnd;
 static int hash_rnd_initted;
 
-static unsigned int recent_entry_hash(u_int32_t addr)
+static unsigned int recent_entry_hash(__be32 addr)
 {
        if (!hash_rnd_initted) {
                get_random_bytes(&hash_rnd, 4);
                hash_rnd_initted = 1;
        }
-       return jhash_1word(addr, hash_rnd) & (ip_list_hash_size - 1);
+       return jhash_1word((__force u32)addr, hash_rnd) & (ip_list_hash_size - 1);
 }
 
 static struct recent_entry *
-recent_entry_lookup(const struct recent_table *table, u_int32_t addr, u_int8_t ttl)
+recent_entry_lookup(const struct recent_table *table, __be32 addr, u_int8_t ttl)
 {
        struct recent_entry *e;
        unsigned int h;
@@ -116,7 +117,7 @@ static void recent_entry_remove(struct recent_table *t, struct recent_entry *e)
 }
 
 static struct recent_entry *
-recent_entry_init(struct recent_table *t, u_int32_t addr, u_int8_t ttl)
+recent_entry_init(struct recent_table *t, __be32 addr, u_int8_t ttl)
 {
        struct recent_entry *e;
 
@@ -163,31 +164,30 @@ static void recent_table_flush(struct recent_table *t)
        struct recent_entry *e, *next;
        unsigned int i;
 
-       for (i = 0; i < ip_list_hash_size; i++) {
+       for (i = 0; i < ip_list_hash_size; i++)
                list_for_each_entry_safe(e, next, &t->iphash[i], list)
                        recent_entry_remove(t, e);
-       }
 }
 
-static int
+static bool
 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)
+                int offset, unsigned int protoff, bool *hotdrop)
 {
        const struct ipt_recent_info *info = matchinfo;
        struct recent_table *t;
        struct recent_entry *e;
-       u_int32_t addr;
+       __be32 addr;
        u_int8_t ttl;
-       int ret = info->invert;
+       bool ret = info->invert;
 
        if (info->side == IPT_RECENT_DEST)
-               addr = skb->nh.iph->daddr;
+               addr = ip_hdr(skb)->daddr;
        else
-               addr = skb->nh.iph->saddr;
+               addr = ip_hdr(skb)->saddr;
 
-       ttl = skb->nh.iph->ttl;
+       ttl = ip_hdr(skb)->ttl;
        /* use TTL as seen before forwarding */
        if (out && !skb->sk)
                ttl++;
@@ -201,16 +201,16 @@ ipt_recent_match(const struct sk_buff *skb,
                        goto out;
                e = recent_entry_init(t, addr, ttl);
                if (e == NULL)
-                       *hotdrop = 1;
-               ret ^= 1;
+                       *hotdrop = true;
+               ret = !ret;
                goto out;
        }
 
        if (info->check_set & IPT_RECENT_SET)
-               ret ^= 1;
+               ret = !ret;
        else if (info->check_set & IPT_RECENT_REMOVE) {
                recent_entry_remove(t, e);
-               ret ^= 1;
+               ret = !ret;
        } else if (info->check_set & (IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) {
                unsigned long t = jiffies - info->seconds * HZ;
                unsigned int i, hits = 0;
@@ -219,7 +219,7 @@ ipt_recent_match(const struct sk_buff *skb,
                        if (info->seconds && time_after(t, e->stamps[i]))
                                continue;
                        if (++hits >= info->hit_count) {
-                               ret ^= 1;
+                               ret = !ret;
                                break;
                        }
                }
@@ -235,32 +235,32 @@ out:
        return ret;
 }
 
-static int
+static bool
 ipt_recent_checkentry(const char *tablename, const void *ip,
                      const struct xt_match *match, void *matchinfo,
-                     unsigned int matchsize, unsigned int hook_mask)
+                     unsigned int hook_mask)
 {
        const struct ipt_recent_info *info = matchinfo;
        struct recent_table *t;
        unsigned i;
-       int ret = 0;
+       bool ret = false;
 
        if (hweight8(info->check_set &
                     (IPT_RECENT_SET | IPT_RECENT_REMOVE |
                      IPT_RECENT_CHECK | IPT_RECENT_UPDATE)) != 1)
-               return 0;
+               return false;
        if ((info->check_set & (IPT_RECENT_SET | IPT_RECENT_REMOVE)) &&
            (info->seconds || info->hit_count))
-               return 0;
+               return false;
        if (info->name[0] == '\0' ||
            strnlen(info->name, IPT_RECENT_NAME_LEN) == IPT_RECENT_NAME_LEN)
-               return 0;
+               return false;
 
        mutex_lock(&recent_mutex);
        t = recent_table_lookup(info->name);
        if (t != NULL) {
                t->refcnt++;
-               ret = 1;
+               ret = true;
                goto out;
        }
 
@@ -287,15 +287,14 @@ ipt_recent_checkentry(const char *tablename, const void *ip,
        spin_lock_bh(&recent_lock);
        list_add_tail(&t->list, &tables);
        spin_unlock_bh(&recent_lock);
-       ret = 1;
+       ret = true;
 out:
        mutex_unlock(&recent_mutex);
        return ret;
 }
 
 static void
-ipt_recent_destroy(const struct xt_match *match, void *matchinfo,
-                  unsigned int matchsize)
+ipt_recent_destroy(const struct xt_match *match, void *matchinfo)
 {
        const struct ipt_recent_info *info = matchinfo;
        struct recent_table *t;
@@ -324,18 +323,16 @@ struct recent_iter_state {
 static void *recent_seq_start(struct seq_file *seq, loff_t *pos)
 {
        struct recent_iter_state *st = seq->private;
-       struct recent_table *t = st->table;
+       const struct recent_table *t = st->table;
        struct recent_entry *e;
        loff_t p = *pos;
 
        spin_lock_bh(&recent_lock);
 
-       for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++) {
-               list_for_each_entry(e, &t->iphash[st->bucket], list) {
+       for (st->bucket = 0; st->bucket < ip_list_hash_size; st->bucket++)
+               list_for_each_entry(e, &t->iphash[st->bucket], list)
                        if (p-- == 0)
                                return e;
-               }
-       }
        return NULL;
 }
 
@@ -374,7 +371,7 @@ static int recent_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations recent_seq_ops = {
+static const struct seq_operations recent_seq_ops = {
        .start          = recent_seq_start,
        .next           = recent_seq_next,
        .stop           = recent_seq_stop,
@@ -391,23 +388,28 @@ static int recent_seq_open(struct inode *inode, struct file *file)
        st = kzalloc(sizeof(*st), GFP_KERNEL);
        if (st == NULL)
                return -ENOMEM;
+
        ret = seq_open(file, &recent_seq_ops);
-       if (ret)
+       if (ret) {
                kfree(st);
+               goto out;
+       }
+
        st->table    = pde->data;
        seq          = file->private_data;
        seq->private = st;
+out:
        return ret;
 }
 
 static ssize_t recent_proc_write(struct file *file, const char __user *input,
                                 size_t size, loff_t *loff)
 {
-       struct proc_dir_entry *pde = PDE(file->f_dentry->d_inode);
+       struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
        struct recent_table *t = pde->data;
        struct recent_entry *e;
        char buf[sizeof("+255.255.255.255")], *c = buf;
-       u_int32_t addr;
+       __be32 addr;
        int add;
 
        if (size > sizeof(buf))
@@ -455,7 +457,7 @@ static ssize_t recent_proc_write(struct file *file, const char __user *input,
        return size;
 }
 
-static struct file_operations recent_fops = {
+static const struct file_operations recent_fops = {
        .open           = recent_seq_open,
        .read           = seq_read,
        .write          = recent_proc_write,
@@ -464,8 +466,9 @@ static struct file_operations recent_fops = {
 };
 #endif /* CONFIG_PROC_FS */
 
-static struct ipt_match recent_match = {
+static struct xt_match recent_match __read_mostly = {
        .name           = "recent",
+       .family         = AF_INET,
        .match          = ipt_recent_match,
        .matchsize      = sizeof(struct ipt_recent_info),
        .checkentry     = ipt_recent_checkentry,
@@ -481,13 +484,13 @@ static int __init ipt_recent_init(void)
                return -EINVAL;
        ip_list_hash_size = 1 << fls(ip_list_tot);
 
-       err = ipt_register_match(&recent_match);
+       err = xt_register_match(&recent_match);
 #ifdef CONFIG_PROC_FS
        if (err)
                return err;
-       proc_dir = proc_mkdir("ipt_recent", proc_net);
+       proc_dir = proc_mkdir("ipt_recent", init_net.proc_net);
        if (proc_dir == NULL) {
-               ipt_unregister_match(&recent_match);
+               xt_unregister_match(&recent_match);
                err = -ENOMEM;
        }
 #endif
@@ -497,9 +500,9 @@ static int __init ipt_recent_init(void)
 static void __exit ipt_recent_exit(void)
 {
        BUG_ON(!list_empty(&tables));
-       ipt_unregister_match(&recent_match);
+       xt_unregister_match(&recent_match);
 #ifdef CONFIG_PROC_FS
-       remove_proc_entry("ipt_recent", proc_net);
+       remove_proc_entry("ipt_recent", init_net.proc_net);
 #endif
 }