@@ -192,6 +192,8 @@ struct xt_table {
/* Man behind the curtain... */
struct xt_table_info *private;
+ struct nf_hook_ops *ops;
+
/* Set this to THIS_MODULE if you are a module, otherwise NULL */
struct module *me;
@@ -50,7 +50,8 @@ struct arpt_error {
extern void *arpt_alloc_initial_table(const struct xt_table *);
extern struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
- const struct arpt_replace *repl);
+ const struct arpt_replace *repl,
+ nf_hookfn *hookfn);
extern void arpt_unregister_table(struct xt_table *table);
extern unsigned int arpt_do_table(struct sk_buff *skb,
unsigned int hook,
@@ -26,9 +26,15 @@ extern void ipt_init(void) __init;
extern struct xt_table *ipt_register_table(struct net *net,
const struct xt_table *table,
- const struct ipt_replace *repl);
+ const struct ipt_replace *repl,
+ nf_hookfn *hookfn);
extern void ipt_unregister_table(struct net *net, struct xt_table *table);
+extern struct xt_table *__ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl);
+extern void __ipt_unregister_table(struct net *net, struct xt_table *table);
+
/* Standard entry. */
struct ipt_standard {
struct ipt_entry entry;
@@ -27,8 +27,14 @@ extern void ip6t_init(void) __init;
extern void *ip6t_alloc_initial_table(const struct xt_table *);
extern struct xt_table *ip6t_register_table(struct net *net,
const struct xt_table *table,
- const struct ip6t_replace *repl);
+ const struct ip6t_replace *repl,
+ nf_hookfn *hookfn);
extern void ip6t_unregister_table(struct net *net, struct xt_table *table);
+extern struct xt_table *__ip6t_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ip6t_replace *repl);
+extern void __ip6t_unregister_table(struct net *net, struct xt_table *table);
+
extern unsigned int ip6t_do_table(struct sk_buff *skb,
unsigned int hook,
const struct nf_hook_state *state,
@@ -1779,13 +1779,15 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
struct xt_table *arpt_register_table(struct net *net,
const struct xt_table *table,
- const struct arpt_replace *repl)
+ const struct arpt_replace *repl,
+ nf_hookfn *hookfn)
{
int ret;
struct xt_table_info *newinfo;
struct xt_table_info bootstrap = {0};
void *loc_cpu_entry;
struct xt_table *new_table;
+ struct nf_hook_ops *ops;
newinfo = xt_alloc_table_info(repl->size);
if (!newinfo) {
@@ -1806,8 +1808,17 @@ struct xt_table *arpt_register_table(struct net *net,
ret = PTR_ERR(new_table);
goto out_free;
}
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ ret = PTR_ERR(ops);
+ goto out_unregister_table;
+ }
+
return new_table;
+out_unregister_table:
+ xt_unregister_table(new_table);
out_free:
xt_free_table_info(newinfo);
out:
@@ -1821,6 +1832,8 @@ void arpt_unregister_table(struct xt_table *table)
struct module *table_owner = table->me;
struct arpt_entry *iter;
+ xt_hook_unlink(table, table->ops);
+
private = xt_unregister_table(table);
/* Decrease module usage counts and free resources */
@@ -36,17 +36,16 @@ arptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv4.arptable_filter);
}
-static struct nf_hook_ops *arpfilter_ops __read_mostly;
-
static int __net_init arptable_filter_net_init(struct net *net)
{
struct arpt_replace *repl;
-
+
repl = arpt_alloc_initial_table(&packet_filter);
if (repl == NULL)
return -ENOMEM;
net->ipv4.arptable_filter =
- arpt_register_table(net, &packet_filter, repl);
+ arpt_register_table(net, &packet_filter, repl,
+ arptable_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter);
}
@@ -63,28 +62,11 @@ static struct pernet_operations arptable_filter_net_ops = {
static int __init arptable_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&arptable_filter_net_ops);
- if (ret < 0)
- return ret;
-
- arpfilter_ops = xt_hook_link(&init_net, &packet_filter,
- arptable_filter_hook);
- if (IS_ERR(arpfilter_ops)) {
- ret = PTR_ERR(arpfilter_ops);
- goto cleanup_table;
- }
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&arptable_filter_net_ops);
- return ret;
+ return register_pernet_subsys(&arptable_filter_net_ops);
}
static void __exit arptable_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, arpfilter_ops);
unregister_pernet_subsys(&arptable_filter_net_ops);
}
@@ -2057,9 +2057,10 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-struct xt_table *ipt_register_table(struct net *net,
- const struct xt_table *table,
- const struct ipt_replace *repl)
+/* Just like ipt_register_table() but no hook in registered. */
+struct xt_table *__ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl)
{
int ret;
struct xt_table_info *newinfo;
@@ -2093,8 +2094,38 @@ out_free:
out:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(__ipt_register_table);
-void ipt_unregister_table(struct net *net, struct xt_table *table)
+struct xt_table *ipt_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ipt_replace *repl,
+ nf_hookfn *hookfn)
+{
+ struct xt_table *new_table;
+ struct nf_hook_ops *ops;
+ int ret;
+
+ new_table = __ipt_register_table(net, table, repl);
+ if (IS_ERR(new_table)) {
+ ret = PTR_ERR(new_table);
+ goto out;
+ }
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ ret = PTR_ERR(ops);
+ goto out_free;
+ }
+
+ return new_table;
+out_free:
+ __ipt_unregister_table(net, new_table);
+out:
+ return ERR_PTR(ret);
+}
+
+/* Just like ipt_unregister_table() but no hook in unregistered. */
+void __ipt_unregister_table(struct net *net, struct xt_table *table)
{
struct xt_table_info *private;
void *loc_cpu_entry;
@@ -2111,6 +2142,13 @@ void ipt_unregister_table(struct net *net, struct xt_table *table)
module_put(table_owner);
xt_free_table_info(private);
}
+EXPORT_SYMBOL_GPL(__ipt_unregister_table);
+
+void ipt_unregister_table(struct net *net, struct xt_table *table)
+{
+ xt_hook_unlink(table, table->ops);
+ __ipt_unregister_table(net, table);
+}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
static inline bool
@@ -48,8 +48,6 @@ iptable_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ipt_do_table(skb, ops->hooknum, state, net->ipv4.iptable_filter);
}
-static struct nf_hook_ops *filter_ops __read_mostly;
-
/* Default to forward because I got too much mail already. */
static bool forward = true;
module_param(forward, bool, 0000);
@@ -66,7 +64,8 @@ static int __net_init iptable_filter_net_init(struct net *net)
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
net->ipv4.iptable_filter =
- ipt_register_table(net, &packet_filter, repl);
+ ipt_register_table(net, &packet_filter, repl,
+ iptable_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter);
}
@@ -83,26 +82,11 @@ static struct pernet_operations iptable_filter_net_ops = {
static int __init iptable_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_filter_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- filter_ops = xt_hook_link(&init_net, &packet_filter,
- iptable_filter_hook);
- if (IS_ERR(filter_ops)) {
- ret = PTR_ERR(filter_ops);
- unregister_pernet_subsys(&iptable_filter_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_filter_net_ops);
}
static void __exit iptable_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, filter_ops);
unregister_pernet_subsys(&iptable_filter_net_ops);
}
@@ -94,8 +94,6 @@ iptable_mangle_hook(const struct nf_hook_ops *ops,
dev_net(state->in)->ipv4.iptable_mangle);
}
-static struct nf_hook_ops *mangle_ops __read_mostly;
-
static int __net_init iptable_mangle_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -104,7 +102,8 @@ static int __net_init iptable_mangle_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_mangle =
- ipt_register_table(net, &packet_mangler, repl);
+ ipt_register_table(net, &packet_mangler, repl,
+ iptable_mangle_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle);
}
@@ -121,26 +120,11 @@ static struct pernet_operations iptable_mangle_net_ops = {
static int __init iptable_mangle_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_mangle_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- mangle_ops = xt_hook_link(&init_net, &packet_mangler,
- iptable_mangle_hook);
- if (IS_ERR(mangle_ops)) {
- ret = PTR_ERR(mangle_ops);
- unregister_pernet_subsys(&iptable_mangle_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_mangle_net_ops);
}
static void __exit iptable_mangle_fini(void)
{
- xt_hook_unlink(&packet_mangler, mangle_ops);
unregister_pernet_subsys(&iptable_mangle_net_ops);
}
@@ -104,18 +104,49 @@ static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
static int __net_init iptable_nat_net_init(struct net *net)
{
struct ipt_replace *repl;
+ int err;
repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
if (repl == NULL)
return -ENOMEM;
- net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
+
+ net->ipv4.nat_table = __ipt_register_table(net, &nf_nat_ipv4_table,
+ repl);
+ if (IS_ERR(net->ipv4.nat_table)) {
+ err = PTR_ERR(net->ipv4.nat_table);
+ goto err1;
+ }
kfree(repl);
- return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
+
+ net->ipv4.nat_table->ops = kmemdup(nf_nat_ipv4_ops,
+ sizeof(nf_nat_ipv4_ops), GFP_KERNEL);
+ if (net->ipv4.nat_table->ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->ipv4.nat_table->ops,
+ ARRAY_SIZE(nf_nat_ipv4_ops));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->ipv4.nat_table->ops);
+err2:
+ __ipt_unregister_table(net, net->ipv4.nat_table);
+err1:
+ kfree(repl);
+
+ return err;
}
static void __net_exit iptable_nat_net_exit(struct net *net)
{
- ipt_unregister_table(net, net->ipv4.nat_table);
+ nf_unregister_hooks(net->ipv4.nat_table->ops,
+ ARRAY_SIZE(nf_nat_ipv4_ops));
+ kfree(net->ipv4.nat_table->ops);
+ __ipt_unregister_table(net, net->ipv4.nat_table);
}
static struct pernet_operations iptable_nat_net_ops = {
@@ -125,27 +156,11 @@ static struct pernet_operations iptable_nat_net_ops = {
static int __init iptable_nat_init(void)
{
- int err;
-
- err = register_pernet_subsys(&iptable_nat_net_ops);
- if (err < 0)
- goto err1;
-
- err = nf_register_hooks(&init_net, nf_nat_ipv4_ops,
- ARRAY_SIZE(nf_nat_ipv4_ops));
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- unregister_pernet_subsys(&iptable_nat_net_ops);
-err1:
- return err;
+ return register_pernet_subsys(&iptable_nat_net_ops);
}
static void __exit iptable_nat_exit(void)
{
- nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
unregister_pernet_subsys(&iptable_nat_net_ops);
}
@@ -35,8 +35,6 @@ iptable_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ipt_do_table(skb, ops->hooknum, state, net->ipv4.iptable_raw);
}
-static struct nf_hook_ops *rawtable_ops __read_mostly;
-
static int __net_init iptable_raw_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -45,7 +43,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_raw =
- ipt_register_table(net, &packet_raw, repl);
+ ipt_register_table(net, &packet_raw, repl, iptable_raw_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
}
@@ -62,25 +60,11 @@ static struct pernet_operations iptable_raw_net_ops = {
static int __init iptable_raw_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_raw_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- rawtable_ops = xt_hook_link(&init_net, &packet_raw, iptable_raw_hook);
- if (IS_ERR(rawtable_ops)) {
- ret = PTR_ERR(rawtable_ops);
- unregister_pernet_subsys(&iptable_raw_net_ops);
- }
-
- return ret;
+ return register_pernet_subsys(&iptable_raw_net_ops);
}
static void __exit iptable_raw_fini(void)
{
- xt_hook_unlink(&packet_raw, rawtable_ops);
unregister_pernet_subsys(&iptable_raw_net_ops);
}
@@ -53,8 +53,6 @@ iptable_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv4.iptable_security);
}
-static struct nf_hook_ops *sectbl_ops __read_mostly;
-
static int __net_init iptable_security_net_init(struct net *net)
{
struct ipt_replace *repl;
@@ -63,7 +61,8 @@ static int __net_init iptable_security_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv4.iptable_security =
- ipt_register_table(net, &security_table, repl);
+ ipt_register_table(net, &security_table, repl,
+ iptable_security_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv4.iptable_security);
}
@@ -80,29 +79,11 @@ static struct pernet_operations iptable_security_net_ops = {
static int __init iptable_security_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&iptable_security_net_ops);
- if (ret < 0)
- return ret;
-
- sectbl_ops = xt_hook_link(&init_net, &security_table,
- iptable_security_hook);
- if (IS_ERR(sectbl_ops)) {
- ret = PTR_ERR(sectbl_ops);
- goto cleanup_table;
- }
-
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&iptable_security_net_ops);
- return ret;
+ return register_pernet_subsys(&iptable_security_net_ops);
}
static void __exit iptable_security_fini(void)
{
- xt_hook_unlink(&security_table, sectbl_ops);
unregister_pernet_subsys(&iptable_security_net_ops);
}
@@ -2067,7 +2067,8 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
return ret;
}
-struct xt_table *ip6t_register_table(struct net *net,
+/* Just like ip6t_register_table() but no hook is registered. */
+struct xt_table *__ip6t_register_table(struct net *net,
const struct xt_table *table,
const struct ip6t_replace *repl)
{
@@ -2102,8 +2103,38 @@ out_free:
out:
return ERR_PTR(ret);
}
+EXPORT_SYMBOL_GPL(__ip6t_register_table);
-void ip6t_unregister_table(struct net *net, struct xt_table *table)
+struct xt_table *ip6t_register_table(struct net *net,
+ const struct xt_table *table,
+ const struct ip6t_replace *repl,
+ nf_hookfn *hookfn)
+{
+ struct xt_table *new_table;
+ struct nf_hook_ops *ops;
+ int err;
+
+ new_table = __ip6t_register_table(net, table, repl);
+ if (IS_ERR(new_table)) {
+ err = PTR_ERR(new_table);
+ goto err1;
+ }
+
+ ops = xt_hook_link(net, table, hookfn);
+ if (IS_ERR(ops)) {
+ err = PTR_ERR(ops);
+ goto err2;
+ }
+
+ return 0;
+err2:
+ __ip6t_unregister_table(net, new_table);
+err1:
+ return ERR_PTR(err);
+}
+
+/* Just like ip6t_unregister_table() but no hook is unregistered. */
+void __ip6t_unregister_table(struct net *net, struct xt_table *table)
{
struct xt_table_info *private;
void *loc_cpu_entry;
@@ -2120,6 +2151,13 @@ void ip6t_unregister_table(struct net *net, struct xt_table *table)
module_put(table_owner);
xt_free_table_info(private);
}
+EXPORT_SYMBOL_GPL(__ip6t_unregister_table);
+
+void ip6t_unregister_table(struct net *net, struct xt_table *table)
+{
+ __ip6t_unregister_table(net, table);
+ xt_hook_unlink(table, table->ops);
+}
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
static inline bool
@@ -40,8 +40,6 @@ ip6table_filter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ip6t_do_table(skb, ops->hooknum, state, net->ipv6.ip6table_filter);
}
-static struct nf_hook_ops *filter_ops __read_mostly;
-
/* Default to forward because I got too much mail already. */
static bool forward = true;
module_param(forward, bool, 0000);
@@ -58,7 +56,8 @@ static int __net_init ip6table_filter_net_init(struct net *net)
forward ? -NF_ACCEPT - 1 : -NF_DROP - 1;
net->ipv6.ip6table_filter =
- ip6t_register_table(net, &packet_filter, repl);
+ ip6t_register_table(net, &packet_filter, repl,
+ ip6table_filter_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter);
}
@@ -75,30 +74,11 @@ static struct pernet_operations ip6table_filter_net_ops = {
static int __init ip6table_filter_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_filter_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- filter_ops = xt_hook_link(&init_net, &packet_filter,
- ip6table_filter_hook);
- if (IS_ERR(filter_ops)) {
- ret = PTR_ERR(filter_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_filter_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_filter_net_ops);
}
static void __exit ip6table_filter_fini(void)
{
- xt_hook_unlink(&packet_filter, filter_ops);
unregister_pernet_subsys(&ip6table_filter_net_ops);
}
@@ -89,7 +89,6 @@ ip6table_mangle_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
dev_net(state->in)->ipv6.ip6table_mangle);
}
-static struct nf_hook_ops *mangle_ops __read_mostly;
static int __net_init ip6table_mangle_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -98,7 +97,8 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_mangle =
- ip6t_register_table(net, &packet_mangler, repl);
+ ip6t_register_table(net, &packet_mangler, repl,
+ ip6table_mangle_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
}
@@ -115,30 +115,11 @@ static struct pernet_operations ip6table_mangle_net_ops = {
static int __init ip6table_mangle_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_mangle_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- mangle_ops = xt_hook_link(&init_net, &packet_mangler,
- ip6table_mangle_hook);
- if (IS_ERR(mangle_ops)) {
- ret = PTR_ERR(mangle_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_mangle_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_mangle_net_ops);
}
static void __exit ip6table_mangle_fini(void)
{
- xt_hook_unlink(&packet_mangler, mangle_ops);
unregister_pernet_subsys(&ip6table_mangle_net_ops);
}
@@ -106,18 +106,49 @@ static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
static int __net_init ip6table_nat_net_init(struct net *net)
{
struct ip6t_replace *repl;
+ int err;
repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table);
if (repl == NULL)
return -ENOMEM;
- net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
+
+ net->ipv6.ip6table_nat =
+ __ip6t_register_table(net, &nf_nat_ipv6_table, repl);
+ if (IS_ERR(net->ipv6.ip6table_nat)) {
+ err = PTR_ERR(net->ipv6.ip6table_nat);
+ goto err1;
+ }
kfree(repl);
- return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat);
+
+ net->ipv6.ip6table_nat->ops =
+ kmemdup(nf_nat_ipv6_ops, sizeof(nf_nat_ipv6_ops), GFP_KERNEL);
+ if (net->ipv6.ip6table_nat->ops == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ err = nf_register_hooks(net, net->ipv6.ip6table_nat->ops,
+ ARRAY_SIZE(nf_nat_ipv6_ops));
+ if (err < 0)
+ goto err3;
+
+ return 0;
+err3:
+ kfree(net->ipv6.ip6table_nat->ops);
+err2:
+ __ip6t_unregister_table(net, net->ipv6.ip6table_nat);
+err1:
+ kfree(repl);
+
+ return err;
}
static void __net_exit ip6table_nat_net_exit(struct net *net)
{
- ip6t_unregister_table(net, net->ipv6.ip6table_nat);
+ nf_unregister_hooks(net->ipv6.ip6table_nat->ops,
+ ARRAY_SIZE(nf_nat_ipv6_ops));
+ kfree(net->ipv6.ip6table_nat->ops);
+ __ip6t_unregister_table(net, net->ipv6.ip6table_nat);
}
static struct pernet_operations ip6table_nat_net_ops = {
@@ -127,27 +158,11 @@ static struct pernet_operations ip6table_nat_net_ops = {
static int __init ip6table_nat_init(void)
{
- int err;
-
- err = register_pernet_subsys(&ip6table_nat_net_ops);
- if (err < 0)
- goto err1;
-
- err = nf_register_hooks(&init_net, nf_nat_ipv6_ops,
- ARRAY_SIZE(nf_nat_ipv6_ops));
- if (err < 0)
- goto err2;
- return 0;
-
-err2:
- unregister_pernet_subsys(&ip6table_nat_net_ops);
-err1:
- return err;
+ return register_pernet_subsys(&ip6table_nat_net_ops);
}
static void __exit ip6table_nat_exit(void)
{
- nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
unregister_pernet_subsys(&ip6table_nat_net_ops);
}
@@ -27,8 +27,6 @@ ip6table_raw_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
return ip6t_do_table(skb, ops->hooknum, state, net->ipv6.ip6table_raw);
}
-static struct nf_hook_ops *rawtable_ops __read_mostly;
-
static int __net_init ip6table_raw_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -37,7 +35,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_raw =
- ip6t_register_table(net, &packet_raw, repl);
+ ip6t_register_table(net, &packet_raw, repl, ip6table_raw_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw);
}
@@ -54,29 +52,11 @@ static struct pernet_operations ip6table_raw_net_ops = {
static int __init ip6table_raw_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_raw_net_ops);
- if (ret < 0)
- return ret;
-
- /* Register hooks */
- rawtable_ops = xt_hook_link(&init_net, &packet_raw, ip6table_raw_hook);
- if (IS_ERR(rawtable_ops)) {
- ret = PTR_ERR(rawtable_ops);
- goto cleanup_table;
- }
-
- return ret;
-
- cleanup_table:
- unregister_pernet_subsys(&ip6table_raw_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_raw_net_ops);
}
static void __exit ip6table_raw_fini(void)
{
- xt_hook_unlink(&packet_raw, rawtable_ops);
unregister_pernet_subsys(&ip6table_raw_net_ops);
}
@@ -45,8 +45,6 @@ ip6table_security_hook(const struct nf_hook_ops *ops, struct sk_buff *skb,
net->ipv6.ip6table_security);
}
-static struct nf_hook_ops *sectbl_ops __read_mostly;
-
static int __net_init ip6table_security_net_init(struct net *net)
{
struct ip6t_replace *repl;
@@ -55,7 +53,8 @@ static int __net_init ip6table_security_net_init(struct net *net)
if (repl == NULL)
return -ENOMEM;
net->ipv6.ip6table_security =
- ip6t_register_table(net, &security_table, repl);
+ ip6t_register_table(net, &security_table, repl,
+ ip6table_security_hook);
kfree(repl);
return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security);
}
@@ -72,29 +71,11 @@ static struct pernet_operations ip6table_security_net_ops = {
static int __init ip6table_security_init(void)
{
- int ret;
-
- ret = register_pernet_subsys(&ip6table_security_net_ops);
- if (ret < 0)
- return ret;
-
- sectbl_ops = xt_hook_link(&init_net, &security_table,
- ip6table_security_hook);
- if (IS_ERR(sectbl_ops)) {
- ret = PTR_ERR(sectbl_ops);
- goto cleanup_table;
- }
-
- return ret;
-
-cleanup_table:
- unregister_pernet_subsys(&ip6table_security_net_ops);
- return ret;
+ return register_pernet_subsys(&ip6table_security_net_ops);
}
static void __exit ip6table_security_fini(void)
{
- xt_hook_unlink(&security_table, sectbl_ops);
unregister_pernet_subsys(&ip6table_security_net_ops);
}
To achieve this, this patch moves struct nf_hook_ops to the xt_table struct. This has a nice side effect since this simplifies the boiler plate code that registers a table. There is one exception though, since NAT tables are special given that their hooks have different priorities. To address this, they use the new __ip{6}t_register_table() and __ip{6}_unregister_table() that don't call xt_hook_link(). Then, these table manually register the hooks and attach the nf_hooks_ops to the new xt_table field. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- include/linux/netfilter/x_tables.h | 2 ++ include/linux/netfilter_arp/arp_tables.h | 3 +- include/linux/netfilter_ipv4/ip_tables.h | 8 ++++- include/linux/netfilter_ipv6/ip6_tables.h | 8 ++++- net/ipv4/netfilter/arp_tables.c | 15 +++++++- net/ipv4/netfilter/arptable_filter.c | 26 +++----------- net/ipv4/netfilter/ip_tables.c | 46 +++++++++++++++++++++--- net/ipv4/netfilter/iptable_filter.c | 22 ++---------- net/ipv4/netfilter/iptable_mangle.c | 22 ++---------- net/ipv4/netfilter/iptable_nat.c | 55 ++++++++++++++++++----------- net/ipv4/netfilter/iptable_raw.c | 20 ++--------- net/ipv4/netfilter/iptable_security.c | 25 ++----------- net/ipv6/netfilter/ip6_tables.c | 42 ++++++++++++++++++++-- net/ipv6/netfilter/ip6table_filter.c | 26 ++------------ net/ipv6/netfilter/ip6table_mangle.c | 25 ++----------- net/ipv6/netfilter/ip6table_nat.c | 55 ++++++++++++++++++----------- net/ipv6/netfilter/ip6table_raw.c | 24 ++----------- net/ipv6/netfilter/ip6table_security.c | 25 ++----------- 18 files changed, 210 insertions(+), 239 deletions(-)