X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fipv6%2Fsysctl_net_ipv6.c;h=3804dcbbfab0f46cc0cfcfd852482e4eb529e312;hb=c135b6592bd63925397e60425e0301f33f06c7a6;hp=f713fbf34c230d93d25061ff7db3c04a5577d771;hpb=291480c09a9452a3d8852a9bfeb5ba2cbcfe662c;p=linux-2.6 diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index f713fbf34c..3804dcbbfa 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c @@ -14,63 +14,29 @@ #include #include -static ctl_table ipv6_table[] = { +static ctl_table ipv6_table_template[] = { { .ctl_name = NET_IPV6_ROUTE, .procname = "route", .maxlen = 0, .mode = 0555, - .child = ipv6_route_table + .child = ipv6_route_table_template }, { .ctl_name = NET_IPV6_ICMP, .procname = "icmp", .maxlen = 0, .mode = 0555, - .child = ipv6_icmp_table + .child = ipv6_icmp_table_template }, { .ctl_name = NET_IPV6_BINDV6ONLY, .procname = "bindv6only", - .data = &sysctl_ipv6_bindv6only, + .data = &init_net.ipv6.sysctl.bindv6only, .maxlen = sizeof(int), .mode = 0644, .proc_handler = &proc_dointvec }, - { - .ctl_name = NET_IPV6_IP6FRAG_HIGH_THRESH, - .procname = "ip6frag_high_thresh", - .data = &ip6_frags_ctl.high_thresh, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = NET_IPV6_IP6FRAG_LOW_THRESH, - .procname = "ip6frag_low_thresh", - .data = &ip6_frags_ctl.low_thresh, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = NET_IPV6_IP6FRAG_TIME, - .procname = "ip6frag_time", - .data = &ip6_frags_ctl.timeout, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies, - }, - { - .ctl_name = NET_IPV6_IP6FRAG_SECRET_INTERVAL, - .procname = "ip6frag_secret_interval", - .data = &ip6_frags_ctl.secret_interval, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec_jiffies, - .strategy = &sysctl_jiffies - }, { .ctl_name = NET_IPV6_MLD_MAX_MSF, .procname = "mld_max_msf", @@ -89,20 +55,83 @@ struct ctl_path net_ipv6_ctl_path[] = { }; EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); -static struct ctl_table_header *ipv6_sysctl_header; +static int ipv6_sysctl_net_init(struct net *net) +{ + struct ctl_table *ipv6_table; + struct ctl_table *ipv6_route_table; + struct ctl_table *ipv6_icmp_table; + int err; -int ipv6_sysctl_register(void) + err = -ENOMEM; + ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template), + GFP_KERNEL); + if (!ipv6_table) + goto out; + + ipv6_route_table = ipv6_route_sysctl_init(net); + if (!ipv6_route_table) + goto out_ipv6_table; + ipv6_table[0].child = ipv6_route_table; + + ipv6_icmp_table = ipv6_icmp_sysctl_init(net); + if (!ipv6_icmp_table) + goto out_ipv6_route_table; + ipv6_table[1].child = ipv6_icmp_table; + + ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; + + /* We don't want this value to be per namespace, it should be global + to all namespaces, so make it read-only when we are not in the + init network namespace */ + if (net != &init_net) + ipv6_table[3].mode = 0444; + + net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, + ipv6_table); + if (!net->ipv6.sysctl.table) + goto out_ipv6_icmp_table; + + err = 0; +out: + return err; + +out_ipv6_icmp_table: + kfree(ipv6_icmp_table); +out_ipv6_route_table: + kfree(ipv6_route_table); +out_ipv6_table: + kfree(ipv6_table); + goto out; +} + +static void ipv6_sysctl_net_exit(struct net *net) { - ipv6_sysctl_header = register_sysctl_paths(net_ipv6_ctl_path, - ipv6_table); - if (!ipv6_sysctl_header) - return -ENOMEM; + struct ctl_table *ipv6_table; + struct ctl_table *ipv6_route_table; + struct ctl_table *ipv6_icmp_table; + + ipv6_table = net->ipv6.sysctl.table->ctl_table_arg; + ipv6_route_table = ipv6_table[0].child; + ipv6_icmp_table = ipv6_table[1].child; - return 0; + unregister_net_sysctl_table(net->ipv6.sysctl.table); + + kfree(ipv6_table); + kfree(ipv6_route_table); + kfree(ipv6_icmp_table); +} +static struct pernet_operations ipv6_sysctl_net_ops = { + .init = ipv6_sysctl_net_init, + .exit = ipv6_sysctl_net_exit, +}; + +int ipv6_sysctl_register(void) +{ + return register_pernet_subsys(&ipv6_sysctl_net_ops); } void ipv6_sysctl_unregister(void) { - unregister_sysctl_table(ipv6_sysctl_header); + unregister_pernet_subsys(&ipv6_sysctl_net_ops); }