Branch data Line data Source code
1 : : /*
2 : : * sysctl_net_ipv6.c: sysctl interface to net IPV6 subsystem.
3 : : *
4 : : * Changes:
5 : : * YOSHIFUJI Hideaki @USAGI: added icmp sysctl table.
6 : : */
7 : :
8 : : #include <linux/mm.h>
9 : : #include <linux/sysctl.h>
10 : : #include <linux/in6.h>
11 : : #include <linux/ipv6.h>
12 : : #include <linux/slab.h>
13 : : #include <linux/export.h>
14 : : #include <net/ndisc.h>
15 : : #include <net/ipv6.h>
16 : : #include <net/addrconf.h>
17 : : #include <net/inet_frag.h>
18 : :
19 : : static struct ctl_table ipv6_table_template[] = {
20 : : {
21 : : .procname = "bindv6only",
22 : : .data = &init_net.ipv6.sysctl.bindv6only,
23 : : .maxlen = sizeof(int),
24 : : .mode = 0644,
25 : : .proc_handler = proc_dointvec
26 : : },
27 : : {
28 : : .procname = "anycast_src_echo_reply",
29 : : .data = &init_net.ipv6.sysctl.anycast_src_echo_reply,
30 : : .maxlen = sizeof(int),
31 : : .mode = 0644,
32 : : .proc_handler = proc_dointvec
33 : : },
34 : : {
35 : : .procname = "flowlabel_consistency",
36 : : .data = &init_net.ipv6.sysctl.flowlabel_consistency,
37 : : .maxlen = sizeof(int),
38 : : .mode = 0644,
39 : : .proc_handler = proc_dointvec
40 : : },
41 : : { }
42 : : };
43 : :
44 : : static struct ctl_table ipv6_rotable[] = {
45 : : {
46 : : .procname = "mld_max_msf",
47 : : .data = &sysctl_mld_max_msf,
48 : : .maxlen = sizeof(int),
49 : : .mode = 0644,
50 : : .proc_handler = proc_dointvec
51 : : },
52 : : { }
53 : : };
54 : :
55 : 0 : static int __net_init ipv6_sysctl_net_init(struct net *net)
56 : : {
57 : : struct ctl_table *ipv6_table;
58 : : struct ctl_table *ipv6_route_table;
59 : : struct ctl_table *ipv6_icmp_table;
60 : : int err;
61 : :
62 : : err = -ENOMEM;
63 : 0 : ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
64 : : GFP_KERNEL);
65 [ # # ]: 0 : if (!ipv6_table)
66 : : goto out;
67 : 0 : ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
68 : 0 : ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply;
69 : 0 : ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency;
70 : :
71 : 0 : ipv6_route_table = ipv6_route_sysctl_init(net);
72 [ # # ]: 0 : if (!ipv6_route_table)
73 : : goto out_ipv6_table;
74 : :
75 : 0 : ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
76 [ # # ]: 0 : if (!ipv6_icmp_table)
77 : : goto out_ipv6_route_table;
78 : :
79 : 0 : net->ipv6.sysctl.hdr = register_net_sysctl(net, "net/ipv6", ipv6_table);
80 [ # # ]: 0 : if (!net->ipv6.sysctl.hdr)
81 : : goto out_ipv6_icmp_table;
82 : :
83 : 0 : net->ipv6.sysctl.route_hdr =
84 : 0 : register_net_sysctl(net, "net/ipv6/route", ipv6_route_table);
85 [ # # ]: 0 : if (!net->ipv6.sysctl.route_hdr)
86 : : goto out_unregister_ipv6_table;
87 : :
88 : 0 : net->ipv6.sysctl.icmp_hdr =
89 : 0 : register_net_sysctl(net, "net/ipv6/icmp", ipv6_icmp_table);
90 [ # # ]: 0 : if (!net->ipv6.sysctl.icmp_hdr)
91 : : goto out_unregister_route_table;
92 : :
93 : : err = 0;
94 : : out:
95 : 0 : return err;
96 : : out_unregister_route_table:
97 : 0 : unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
98 : : out_unregister_ipv6_table:
99 : 0 : unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
100 : : out_ipv6_icmp_table:
101 : 0 : kfree(ipv6_icmp_table);
102 : : out_ipv6_route_table:
103 : 0 : kfree(ipv6_route_table);
104 : : out_ipv6_table:
105 : 0 : kfree(ipv6_table);
106 : 0 : goto out;
107 : : }
108 : :
109 : 0 : static void __net_exit ipv6_sysctl_net_exit(struct net *net)
110 : : {
111 : : struct ctl_table *ipv6_table;
112 : : struct ctl_table *ipv6_route_table;
113 : : struct ctl_table *ipv6_icmp_table;
114 : :
115 : 0 : ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
116 : 0 : ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
117 : 0 : ipv6_icmp_table = net->ipv6.sysctl.icmp_hdr->ctl_table_arg;
118 : :
119 : 0 : unregister_net_sysctl_table(net->ipv6.sysctl.icmp_hdr);
120 : 0 : unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
121 : 0 : unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
122 : :
123 : 0 : kfree(ipv6_table);
124 : 0 : kfree(ipv6_route_table);
125 : 0 : kfree(ipv6_icmp_table);
126 : 0 : }
127 : :
128 : : static struct pernet_operations ipv6_sysctl_net_ops = {
129 : : .init = ipv6_sysctl_net_init,
130 : : .exit = ipv6_sysctl_net_exit,
131 : : };
132 : :
133 : : static struct ctl_table_header *ip6_header;
134 : :
135 : 0 : int ipv6_sysctl_register(void)
136 : : {
137 : : int err = -ENOMEM;
138 : :
139 : 0 : ip6_header = register_net_sysctl(&init_net, "net/ipv6", ipv6_rotable);
140 [ # # ]: 0 : if (ip6_header == NULL)
141 : : goto out;
142 : :
143 : 0 : err = register_pernet_subsys(&ipv6_sysctl_net_ops);
144 [ # # ]: 0 : if (err)
145 : : goto err_pernet;
146 : : out:
147 : 0 : return err;
148 : :
149 : : err_pernet:
150 : 0 : unregister_net_sysctl_table(ip6_header);
151 : 0 : goto out;
152 : : }
153 : :
154 : 0 : void ipv6_sysctl_unregister(void)
155 : : {
156 : 0 : unregister_net_sysctl_table(ip6_header);
157 : 0 : unregister_pernet_subsys(&ipv6_sysctl_net_ops);
158 : 0 : }
|