]> err.no Git - linux-2.6/blobdiff - net/ipv6/netfilter/ip6_tables.c
Merge branch 'for-jeff' of git://git.kernel.org/pub/scm/linux/kernel/git/chris/linux...
[linux-2.6] / net / ipv6 / netfilter / ip6_tables.c
index b89f133f41d054fdf88e5ac677b6b169bbc1cf37..0b4557e03431fa05fae2037d4d0248950bcd3a2d 100644 (file)
@@ -55,7 +55,7 @@ MODULE_DESCRIPTION("IPv6 packet filter");
 do {                                                           \
        if (!(x))                                               \
                printk("IP_NF_ASSERT: %s:%s:%u\n",              \
-                      __FUNCTION__, __FILE__, __LINE__);       \
+                      __func__, __FILE__, __LINE__);   \
 } while(0)
 #else
 #define IP_NF_ASSERT(x)
@@ -325,7 +325,7 @@ static void trace_packet(struct sk_buff *skb,
                         struct ip6t_entry *e)
 {
        void *table_base;
-       struct ip6t_entry *root;
+       const struct ip6t_entry *root;
        char *hookname, *chainname, *comment;
        unsigned int rulenum = 0;
 
@@ -952,7 +952,7 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
 {
        unsigned int countersize;
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
 
        /* We need atomic snapshot of counters: rest doesn't change
           (other than comefrom, which userspace doesn't care
@@ -979,9 +979,9 @@ copy_entries_to_user(unsigned int total_size,
        unsigned int off, num;
        struct ip6t_entry *e;
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
        int ret = 0;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
 
        counters = alloc_counters(table);
        if (IS_ERR(counters))
@@ -1001,8 +1001,8 @@ copy_entries_to_user(unsigned int total_size,
        /* ... then go back and fix counters and names */
        for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
                unsigned int i;
-               struct ip6t_entry_match *m;
-               struct ip6t_entry_target *t;
+               const struct ip6t_entry_match *m;
+               const struct ip6t_entry_target *t;
 
                e = (struct ip6t_entry *)(loc_cpu_entry + off);
                if (copy_to_user(userptr + off
@@ -1118,7 +1118,7 @@ static int compat_table_info(const struct xt_table_info *info,
 }
 #endif
 
-static int get_info(void __user *user, int *len, int compat)
+static int get_info(struct net *net, void __user *user, int *len, int compat)
 {
        char name[IP6T_TABLE_MAXNAMELEN];
        struct xt_table *t;
@@ -1138,11 +1138,11 @@ static int get_info(void __user *user, int *len, int compat)
        if (compat)
                xt_compat_lock(AF_INET6);
 #endif
-       t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, name),
+       t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
                                    "ip6table_%s", name);
        if (t && !IS_ERR(t)) {
                struct ip6t_getinfo info;
-               struct xt_table_info *private = t->private;
+               const struct xt_table_info *private = t->private;
 
 #ifdef CONFIG_COMPAT
                if (compat) {
@@ -1178,7 +1178,7 @@ static int get_info(void __user *user, int *len, int compat)
 }
 
 static int
-get_entries(struct ip6t_get_entries __user *uptr, int *len)
+get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len)
 {
        int ret;
        struct ip6t_get_entries get;
@@ -1196,7 +1196,7 @@ get_entries(struct ip6t_get_entries __user *uptr, int *len)
                return -EINVAL;
        }
 
-       t = xt_find_table_lock(&init_net, AF_INET6, get.name);
+       t = xt_find_table_lock(net, AF_INET6, get.name);
        if (t && !IS_ERR(t)) {
                struct xt_table_info *private = t->private;
                duprintf("t->private->number = %u\n", private->number);
@@ -1206,7 +1206,7 @@ get_entries(struct ip6t_get_entries __user *uptr, int *len)
                else {
                        duprintf("get_entries: I've got %u not %u!\n",
                                 private->size, get.size);
-                       ret = -EINVAL;
+                       ret = -EAGAIN;
                }
                module_put(t->me);
                xt_table_unlock(t);
@@ -1217,7 +1217,7 @@ get_entries(struct ip6t_get_entries __user *uptr, int *len)
 }
 
 static int
-__do_replace(const char *name, unsigned int valid_hooks,
+__do_replace(struct net *net, const char *name, unsigned int valid_hooks,
             struct xt_table_info *newinfo, unsigned int num_counters,
             void __user *counters_ptr)
 {
@@ -1225,7 +1225,7 @@ __do_replace(const char *name, unsigned int valid_hooks,
        struct xt_table *t;
        struct xt_table_info *oldinfo;
        struct xt_counters *counters;
-       void *loc_cpu_old_entry;
+       const void *loc_cpu_old_entry;
 
        ret = 0;
        counters = vmalloc_node(num_counters * sizeof(struct xt_counters),
@@ -1235,7 +1235,7 @@ __do_replace(const char *name, unsigned int valid_hooks,
                goto out;
        }
 
-       t = try_then_request_module(xt_find_table_lock(&init_net, AF_INET6, name),
+       t = try_then_request_module(xt_find_table_lock(net, AF_INET6, name),
                                    "ip6table_%s", name);
        if (!t || IS_ERR(t)) {
                ret = t ? PTR_ERR(t) : -ENOENT;
@@ -1288,7 +1288,7 @@ __do_replace(const char *name, unsigned int valid_hooks,
 }
 
 static int
-do_replace(void __user *user, unsigned int len)
+do_replace(struct net *net, void __user *user, unsigned int len)
 {
        int ret;
        struct ip6t_replace tmp;
@@ -1322,7 +1322,7 @@ do_replace(void __user *user, unsigned int len)
 
        duprintf("ip_tables: Translated table\n");
 
-       ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo,
+       ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
                           tmp.num_counters, tmp.counters);
        if (ret)
                goto free_newinfo_untrans;
@@ -1358,7 +1358,8 @@ add_counter_to_entry(struct ip6t_entry *e,
 }
 
 static int
-do_add_counters(void __user *user, unsigned int len, int compat)
+do_add_counters(struct net *net, void __user *user, unsigned int len,
+               int compat)
 {
        unsigned int i;
        struct xt_counters_info tmp;
@@ -1368,9 +1369,9 @@ do_add_counters(void __user *user, unsigned int len, int compat)
        int size;
        void *ptmp;
        struct xt_table *t;
-       struct xt_table_info *private;
+       const struct xt_table_info *private;
        int ret = 0;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
 #ifdef CONFIG_COMPAT
        struct compat_xt_counters_info compat_tmp;
 
@@ -1410,7 +1411,7 @@ do_add_counters(void __user *user, unsigned int len, int compat)
                goto free;
        }
 
-       t = xt_find_table_lock(&init_net, AF_INET6, name);
+       t = xt_find_table_lock(net, AF_INET6, name);
        if (!t || IS_ERR(t)) {
                ret = t ? PTR_ERR(t) : -ENOENT;
                goto free;
@@ -1456,7 +1457,7 @@ struct compat_ip6t_replace {
 
 static int
 compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
-                         compat_uint_t *size, struct xt_counters *counters,
+                         unsigned int *size, struct xt_counters *counters,
                          unsigned int *i)
 {
        struct ip6t_entry_target *t;
@@ -1503,7 +1504,7 @@ compat_find_calc_match(struct ip6t_entry_match *m,
                       const char *name,
                       const struct ip6t_ip6 *ipv6,
                       unsigned int hookmask,
-                      int *size, int *i)
+                      int *size, unsigned int *i)
 {
        struct xt_match *match;
 
@@ -1561,7 +1562,8 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
        struct ip6t_entry_target *t;
        struct xt_target *target;
        unsigned int entry_offset;
-       int ret, off, h, j;
+       unsigned int j;
+       int ret, off, h;
 
        duprintf("check_compat_entry_size_and_hooks %p\n", e);
        if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0
@@ -1673,7 +1675,8 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
 static int compat_check_entry(struct ip6t_entry *e, const char *name,
                                     unsigned int *i)
 {
-       int j, ret;
+       unsigned int j;
+       int ret;
 
        j = 0;
        ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6,
@@ -1815,7 +1818,7 @@ out_unlock:
 }
 
 static int
-compat_do_replace(void __user *user, unsigned int len)
+compat_do_replace(struct net *net, void __user *user, unsigned int len)
 {
        int ret;
        struct compat_ip6t_replace tmp;
@@ -1852,7 +1855,7 @@ compat_do_replace(void __user *user, unsigned int len)
 
        duprintf("compat_do_replace: Translated table\n");
 
-       ret = __do_replace(tmp.name, tmp.valid_hooks, newinfo,
+       ret = __do_replace(net, tmp.name, tmp.valid_hooks, newinfo,
                           tmp.num_counters, compat_ptr(tmp.counters));
        if (ret)
                goto free_newinfo_untrans;
@@ -1876,11 +1879,11 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
 
        switch (cmd) {
        case IP6T_SO_SET_REPLACE:
-               ret = compat_do_replace(user, len);
+               ret = compat_do_replace(sock_net(sk), user, len);
                break;
 
        case IP6T_SO_SET_ADD_COUNTERS:
-               ret = do_add_counters(user, len, 1);
+               ret = do_add_counters(sock_net(sk), user, len, 1);
                break;
 
        default:
@@ -1902,11 +1905,11 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
                            void __user *userptr)
 {
        struct xt_counters *counters;
-       struct xt_table_info *private = table->private;
+       const struct xt_table_info *private = table->private;
        void __user *pos;
        unsigned int size;
        int ret = 0;
-       void *loc_cpu_entry;
+       const void *loc_cpu_entry;
        unsigned int i = 0;
 
        counters = alloc_counters(table);
@@ -1929,7 +1932,8 @@ compat_copy_entries_to_user(unsigned int total_size, struct xt_table *table,
 }
 
 static int
-compat_get_entries(struct compat_ip6t_get_entries __user *uptr, int *len)
+compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
+                  int *len)
 {
        int ret;
        struct compat_ip6t_get_entries get;
@@ -1950,9 +1954,9 @@ compat_get_entries(struct compat_ip6t_get_entries __user *uptr, int *len)
        }
 
        xt_compat_lock(AF_INET6);
-       t = xt_find_table_lock(&init_net, AF_INET6, get.name);
+       t = xt_find_table_lock(net, AF_INET6, get.name);
        if (t && !IS_ERR(t)) {
-               struct xt_table_info *private = t->private;
+               const struct xt_table_info *private = t->private;
                struct xt_table_info info;
                duprintf("t->private->number = %u\n", private->number);
                ret = compat_table_info(private, &info);
@@ -1962,7 +1966,7 @@ compat_get_entries(struct compat_ip6t_get_entries __user *uptr, int *len)
                } else if (!ret) {
                        duprintf("compat_get_entries: I've got %u not %u!\n",
                                 private->size, get.size);
-                       ret = -EINVAL;
+                       ret = -EAGAIN;
                }
                xt_compat_flush_offsets(AF_INET6);
                module_put(t->me);
@@ -1986,10 +1990,10 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
        switch (cmd) {
        case IP6T_SO_GET_INFO:
-               ret = get_info(user, len, 1);
+               ret = get_info(sock_net(sk), user, len, 1);
                break;
        case IP6T_SO_GET_ENTRIES:
-               ret = compat_get_entries(user, len);
+               ret = compat_get_entries(sock_net(sk), user, len);
                break;
        default:
                ret = do_ip6t_get_ctl(sk, cmd, user, len);
@@ -2008,11 +2012,11 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 
        switch (cmd) {
        case IP6T_SO_SET_REPLACE:
-               ret = do_replace(user, len);
+               ret = do_replace(sock_net(sk), user, len);
                break;
 
        case IP6T_SO_SET_ADD_COUNTERS:
-               ret = do_add_counters(user, len, 0);
+               ret = do_add_counters(sock_net(sk), user, len, 0);
                break;
 
        default:
@@ -2033,11 +2037,11 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 
        switch (cmd) {
        case IP6T_SO_GET_INFO:
-               ret = get_info(user, len, 0);
+               ret = get_info(sock_net(sk), user, len, 0);
                break;
 
        case IP6T_SO_GET_ENTRIES:
-               ret = get_entries(user, len);
+               ret = get_entries(sock_net(sk), user, len);
                break;
 
        case IP6T_SO_GET_REVISION_MATCH:
@@ -2074,7 +2078,8 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        return ret;
 }
 
-struct xt_table *ip6t_register_table(struct xt_table *table, const struct ip6t_replace *repl)
+struct xt_table *ip6t_register_table(struct net *net, struct xt_table *table,
+                                    const struct ip6t_replace *repl)
 {
        int ret;
        struct xt_table_info *newinfo;
@@ -2101,7 +2106,7 @@ struct xt_table *ip6t_register_table(struct xt_table *table, const struct ip6t_r
        if (ret != 0)
                goto out_free;
 
-       new_table = xt_register_table(&init_net, table, &bootstrap, newinfo);
+       new_table = xt_register_table(net, table, &bootstrap, newinfo);
        if (IS_ERR(new_table)) {
                ret = PTR_ERR(new_table);
                goto out_free;
@@ -2118,12 +2123,15 @@ void ip6t_unregister_table(struct xt_table *table)
 {
        struct xt_table_info *private;
        void *loc_cpu_entry;
+       struct module *table_owner = table->me;
 
        private = xt_unregister_table(table);
 
        /* Decrease module usage counts and free resources */
        loc_cpu_entry = private->entries[raw_smp_processor_id()];
        IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL);
+       if (private->number > private->initial_entries)
+               module_put(table_owner);
        xt_free_table_info(private);
 }
 
@@ -2147,7 +2155,8 @@ icmp6_match(const struct sk_buff *skb,
           unsigned int protoff,
           bool *hotdrop)
 {
-       struct icmp6hdr _icmph, *ic;
+       const struct icmp6hdr *ic;
+       struct icmp6hdr _icmph;
        const struct ip6t_icmp *icmpinfo = matchinfo;
 
        /* Must not be a fragment. */
@@ -2230,11 +2239,26 @@ static struct xt_match icmp6_matchstruct __read_mostly = {
        .family         = AF_INET6,
 };
 
+static int __net_init ip6_tables_net_init(struct net *net)
+{
+       return xt_proto_init(net, AF_INET6);
+}
+
+static void __net_exit ip6_tables_net_exit(struct net *net)
+{
+       xt_proto_fini(net, AF_INET6);
+}
+
+static struct pernet_operations ip6_tables_net_ops = {
+       .init = ip6_tables_net_init,
+       .exit = ip6_tables_net_exit,
+};
+
 static int __init ip6_tables_init(void)
 {
        int ret;
 
-       ret = xt_proto_init(AF_INET6);
+       ret = register_pernet_subsys(&ip6_tables_net_ops);
        if (ret < 0)
                goto err1;
 
@@ -2264,7 +2288,7 @@ err4:
 err3:
        xt_unregister_target(&ip6t_standard_target);
 err2:
-       xt_proto_fini(AF_INET6);
+       unregister_pernet_subsys(&ip6_tables_net_ops);
 err1:
        return ret;
 }
@@ -2276,7 +2300,8 @@ static void __exit ip6_tables_fini(void)
        xt_unregister_match(&icmp6_matchstruct);
        xt_unregister_target(&ip6t_error_target);
        xt_unregister_target(&ip6t_standard_target);
-       xt_proto_fini(AF_INET6);
+
+       unregister_pernet_subsys(&ip6_tables_net_ops);
 }
 
 /*