Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / net / ipv6 / sysctl_net_ipv6.c
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 int one = 1;
20
21 static struct ctl_table ipv6_table_template[] = {
22         {
23                 .procname       = "bindv6only",
24                 .data           = &init_net.ipv6.sysctl.bindv6only,
25                 .maxlen         = sizeof(int),
26                 .mode           = 0644,
27                 .proc_handler   = proc_dointvec
28         },
29         {
30                 .procname       = "anycast_src_echo_reply",
31                 .data           = &init_net.ipv6.sysctl.anycast_src_echo_reply,
32                 .maxlen         = sizeof(int),
33                 .mode           = 0644,
34                 .proc_handler   = proc_dointvec
35         },
36         {
37                 .procname       = "flowlabel_consistency",
38                 .data           = &init_net.ipv6.sysctl.flowlabel_consistency,
39                 .maxlen         = sizeof(int),
40                 .mode           = 0644,
41                 .proc_handler   = proc_dointvec
42         },
43         {
44                 .procname       = "auto_flowlabels",
45                 .data           = &init_net.ipv6.sysctl.auto_flowlabels,
46                 .maxlen         = sizeof(int),
47                 .mode           = 0644,
48                 .proc_handler   = proc_dointvec
49         },
50         {
51                 .procname       = "fwmark_reflect",
52                 .data           = &init_net.ipv6.sysctl.fwmark_reflect,
53                 .maxlen         = sizeof(int),
54                 .mode           = 0644,
55                 .proc_handler   = proc_dointvec
56         },
57         {
58                 .procname       = "idgen_retries",
59                 .data           = &init_net.ipv6.sysctl.idgen_retries,
60                 .maxlen         = sizeof(int),
61                 .mode           = 0644,
62                 .proc_handler   = proc_dointvec,
63         },
64         {
65                 .procname       = "idgen_delay",
66                 .data           = &init_net.ipv6.sysctl.idgen_delay,
67                 .maxlen         = sizeof(int),
68                 .mode           = 0644,
69                 .proc_handler   = proc_dointvec_jiffies,
70         },
71         { }
72 };
73
74 static struct ctl_table ipv6_rotable[] = {
75         {
76                 .procname       = "mld_max_msf",
77                 .data           = &sysctl_mld_max_msf,
78                 .maxlen         = sizeof(int),
79                 .mode           = 0644,
80                 .proc_handler   = proc_dointvec
81         },
82         {
83                 .procname       = "mld_qrv",
84                 .data           = &sysctl_mld_qrv,
85                 .maxlen         = sizeof(int),
86                 .mode           = 0644,
87                 .proc_handler   = proc_dointvec_minmax,
88                 .extra1         = &one
89         },
90         { }
91 };
92
93 static int __net_init ipv6_sysctl_net_init(struct net *net)
94 {
95         struct ctl_table *ipv6_table;
96         struct ctl_table *ipv6_route_table;
97         struct ctl_table *ipv6_icmp_table;
98         int err;
99
100         err = -ENOMEM;
101         ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
102                              GFP_KERNEL);
103         if (!ipv6_table)
104                 goto out;
105         ipv6_table[0].data = &net->ipv6.sysctl.bindv6only;
106         ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply;
107         ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency;
108         ipv6_table[3].data = &net->ipv6.sysctl.auto_flowlabels;
109         ipv6_table[4].data = &net->ipv6.sysctl.fwmark_reflect;
110         ipv6_table[5].data = &net->ipv6.sysctl.idgen_retries;
111         ipv6_table[6].data = &net->ipv6.sysctl.idgen_delay;
112
113         ipv6_route_table = ipv6_route_sysctl_init(net);
114         if (!ipv6_route_table)
115                 goto out_ipv6_table;
116
117         ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
118         if (!ipv6_icmp_table)
119                 goto out_ipv6_route_table;
120
121         net->ipv6.sysctl.hdr = register_net_sysctl(net, "net/ipv6", ipv6_table);
122         if (!net->ipv6.sysctl.hdr)
123                 goto out_ipv6_icmp_table;
124
125         net->ipv6.sysctl.route_hdr =
126                 register_net_sysctl(net, "net/ipv6/route", ipv6_route_table);
127         if (!net->ipv6.sysctl.route_hdr)
128                 goto out_unregister_ipv6_table;
129
130         net->ipv6.sysctl.icmp_hdr =
131                 register_net_sysctl(net, "net/ipv6/icmp", ipv6_icmp_table);
132         if (!net->ipv6.sysctl.icmp_hdr)
133                 goto out_unregister_route_table;
134
135         err = 0;
136 out:
137         return err;
138 out_unregister_route_table:
139         unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
140 out_unregister_ipv6_table:
141         unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
142 out_ipv6_icmp_table:
143         kfree(ipv6_icmp_table);
144 out_ipv6_route_table:
145         kfree(ipv6_route_table);
146 out_ipv6_table:
147         kfree(ipv6_table);
148         goto out;
149 }
150
151 static void __net_exit ipv6_sysctl_net_exit(struct net *net)
152 {
153         struct ctl_table *ipv6_table;
154         struct ctl_table *ipv6_route_table;
155         struct ctl_table *ipv6_icmp_table;
156
157         ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
158         ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
159         ipv6_icmp_table = net->ipv6.sysctl.icmp_hdr->ctl_table_arg;
160
161         unregister_net_sysctl_table(net->ipv6.sysctl.icmp_hdr);
162         unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
163         unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
164
165         kfree(ipv6_table);
166         kfree(ipv6_route_table);
167         kfree(ipv6_icmp_table);
168 }
169
170 static struct pernet_operations ipv6_sysctl_net_ops = {
171         .init = ipv6_sysctl_net_init,
172         .exit = ipv6_sysctl_net_exit,
173 };
174
175 static struct ctl_table_header *ip6_header;
176
177 int ipv6_sysctl_register(void)
178 {
179         int err = -ENOMEM;
180
181         ip6_header = register_net_sysctl(&init_net, "net/ipv6", ipv6_rotable);
182         if (!ip6_header)
183                 goto out;
184
185         err = register_pernet_subsys(&ipv6_sysctl_net_ops);
186         if (err)
187                 goto err_pernet;
188 out:
189         return err;
190
191 err_pernet:
192         unregister_net_sysctl_table(ip6_header);
193         goto out;
194 }
195
196 void ipv6_sysctl_unregister(void)
197 {
198         unregister_net_sysctl_table(ip6_header);
199         unregister_pernet_subsys(&ipv6_sysctl_net_ops);
200 }