Signed-off-by: Vasily Averin <vvs@xxxxxxxxxx> --- net/bridge/br_netfilter.c | 56 +++++++++++++++++++++++++++++++++----------- 1 files changed, 42 insertions(+), 14 deletions(-) diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index a079c06..ed3b6ce 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -48,9 +48,6 @@ #define store_orig_dstaddr(skb) (skb_origaddr(skb) = ip_hdr(skb)->daddr) #define dnat_took_place(skb) (skb_origaddr(skb) != ip_hdr(skb)->daddr) -#ifdef CONFIG_SYSCTL -static struct ctl_table_header *brnf_sysctl_header; -#endif #define brnf_call_arptables 1 #define brnf_call_iptables 1 #define brnf_call_ip6tables 1 @@ -1076,17 +1073,58 @@ static struct ctl_table brnf_table[] = { { } }; +static int brnf_sysctl_net_register(struct brnf_net *bn) +{ + struct ctl_table *table; + struct ctl_table_header *hdr; + int i; + + table = brnf_table; + if (!net_eq(bn->net, &init_net)) { + + table = kmemdup(table, sizeof(brnf_table), GFP_KERNEL); + if (!table) + goto err_alloc; + } + hdr = register_net_sysctl(bn->net, "net/bridge", table); + if (!hdr) + goto err_reg; + + bn->hdr = hdr; + return 0; + +err_reg: + if (!net_eq(bn->net, &init_net)) + kfree(table); +err_alloc: + return -ENOMEM; +} + +static void brnf_sysctl_net_unregister(struct brnf_net *bn) +{ + struct ctl_table *table; + + if (bn->hdr == NULL) + return; + + table = bn->hdr->ctl_table_arg; + unregister_net_sysctl_table(bn->hdr); + if (!net_eq(bn->net, &init_net)) + kfree(table); +} + static int __net_init brnf_net_init(struct net *net) { struct brnf_net *bn = brnf_net(net); memcpy(bn, &init_brnf_net, sizeof(struct brnf_net)); bn->net = net; - return 0; + return brnf_sysctl_net_register(bn); } static void __net_exit brnf_net_exit(struct net *net) { + brnf_sysctl_net_unregister(brnf_net(net)); } static struct pernet_operations __net_initdata brnf_net_ops = { @@ -1110,17 +1148,8 @@ int __init br_netfilter_init(void) goto err_nf; #ifdef CONFIG_SYSCTL - brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); - if (brnf_sysctl_header == NULL) { - printk(KERN_WARNING - "br_netfilter: can't register to sysctl.\n"); - nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); - dst_entries_destroy(&fake_dst_ops); - return -ENOMEM; - } ret = register_pernet_subsys(&brnf_net_ops); if (ret < 0) { - unregister_net_sysctl_table(brnf_sysctl_header); nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); goto err_nf; } @@ -1138,7 +1167,6 @@ void br_netfilter_fini(void) { #ifdef CONFIG_SYSCTL unregister_pernet_subsys(&brnf_net_ops); - unregister_net_sysctl_table(brnf_sysctl_header); #endif nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); dst_entries_destroy(&fake_dst_ops); -- 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html