blob: fac2135aa47b6ff8c291a807581c63209b1f7629 [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * sysctl_net_ipv6.c: sysctl interface to net IPV6 subsystem.
4 *
5 * Changes:
6 * YOSHIFUJI Hideaki @USAGI: added icmp sysctl table.
7 */
8
9#include <linux/mm.h>
10#include <linux/sysctl.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/in6.h>
12#include <linux/ipv6.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
Paul Gortmakerbc3b2d72011-07-15 11:47:34 -040014#include <linux/export.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#include <net/ndisc.h>
16#include <net/ipv6.h>
17#include <net/addrconf.h>
Pavel Emelyanov04128f22007-10-15 02:33:45 -070018#include <net/inet_frag.h>
David Ahernb4bac172018-03-02 08:32:18 -080019#include <net/netevent.h>
Huw Davies4fee5242016-06-27 15:06:17 -040020#ifdef CONFIG_NETLABEL
21#include <net/calipso.h>
22#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070023
Eric Dumazeta346abe2019-07-01 06:39:36 -070024static int flowlabel_reflect_max = 0x7;
Tom Herbert42240902015-07-31 16:52:12 -070025static int auto_flowlabels_min;
26static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX;
27
David Ahernb4bac172018-03-02 08:32:18 -080028static int proc_rt6_multipath_hash_policy(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020029 void *buffer, size_t *lenp, loff_t *ppos)
David Ahernb4bac172018-03-02 08:32:18 -080030{
31 struct net *net;
32 int ret;
33
34 net = container_of(table->data, struct net,
35 ipv6.sysctl.multipath_hash_policy);
36 ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
37 if (write && ret == 0)
38 call_netevent_notifiers(NETEVENT_IPV6_MPATH_HASH_UPDATE, net);
39
40 return ret;
41}
Hannes Frederic Sowa2f711932014-09-02 15:49:25 +020042
Joe Perchesfe2c6332013-06-11 23:04:25 -070043static struct ctl_table ipv6_table_template[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070044 {
Linus Torvalds1da177e2005-04-16 15:20:36 -070045 .procname = "bindv6only",
Daniel Lezcano99bc9c42008-01-10 02:54:53 -080046 .data = &init_net.ipv6.sysctl.bindv6only,
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 .maxlen = sizeof(int),
48 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -080049 .proc_handler = proc_dointvec
Linus Torvalds1da177e2005-04-16 15:20:36 -070050 },
FX Le Bail509aba32014-01-07 14:57:27 +010051 {
52 .procname = "anycast_src_echo_reply",
FX Le Bailec35b612014-01-13 15:59:01 +010053 .data = &init_net.ipv6.sysctl.anycast_src_echo_reply,
FX Le Bail509aba32014-01-07 14:57:27 +010054 .maxlen = sizeof(int),
55 .mode = 0644,
56 .proc_handler = proc_dointvec
57 },
Florent Fourcot6444f722014-01-17 17:15:05 +010058 {
59 .procname = "flowlabel_consistency",
60 .data = &init_net.ipv6.sysctl.flowlabel_consistency,
61 .maxlen = sizeof(int),
62 .mode = 0644,
63 .proc_handler = proc_dointvec
64 },
Lorenzo Colittie1108612014-05-13 10:17:33 -070065 {
Tom Herbertcb1ce2e2014-07-01 21:33:10 -070066 .procname = "auto_flowlabels",
67 .data = &init_net.ipv6.sysctl.auto_flowlabels,
68 .maxlen = sizeof(int),
69 .mode = 0644,
Tom Herbert42240902015-07-31 16:52:12 -070070 .proc_handler = proc_dointvec_minmax,
71 .extra1 = &auto_flowlabels_min,
72 .extra2 = &auto_flowlabels_max
Tom Herbertcb1ce2e2014-07-01 21:33:10 -070073 },
74 {
Lorenzo Colittie1108612014-05-13 10:17:33 -070075 .procname = "fwmark_reflect",
76 .data = &init_net.ipv6.sysctl.fwmark_reflect,
77 .maxlen = sizeof(int),
78 .mode = 0644,
79 .proc_handler = proc_dointvec
80 },
Hannes Frederic Sowa1855b7c2015-03-23 23:36:05 +010081 {
82 .procname = "idgen_retries",
83 .data = &init_net.ipv6.sysctl.idgen_retries,
84 .maxlen = sizeof(int),
85 .mode = 0644,
86 .proc_handler = proc_dointvec,
87 },
88 {
89 .procname = "idgen_delay",
90 .data = &init_net.ipv6.sysctl.idgen_delay,
91 .maxlen = sizeof(int),
92 .mode = 0644,
93 .proc_handler = proc_dointvec_jiffies,
94 },
Tom Herbert82a584b2015-04-29 15:33:21 -070095 {
96 .procname = "flowlabel_state_ranges",
97 .data = &init_net.ipv6.sysctl.flowlabel_state_ranges,
98 .maxlen = sizeof(int),
99 .mode = 0644,
100 .proc_handler = proc_dointvec
101 },
Tom Herbert35a256f2015-07-08 16:58:22 -0700102 {
103 .procname = "ip_nonlocal_bind",
104 .data = &init_net.ipv6.sysctl.ip_nonlocal_bind,
105 .maxlen = sizeof(int),
106 .mode = 0644,
107 .proc_handler = proc_dointvec
108 },
Jakub Sitnicki22b67222017-08-23 09:55:41 +0200109 {
110 .procname = "flowlabel_reflect",
111 .data = &init_net.ipv6.sysctl.flowlabel_reflect,
112 .maxlen = sizeof(int),
113 .mode = 0644,
Eiichi Tsukata00dc3302019-06-28 11:37:14 +0900114 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700115 .extra1 = SYSCTL_ZERO,
Eric Dumazeta346abe2019-07-01 06:39:36 -0700116 .extra2 = &flowlabel_reflect_max,
Jakub Sitnicki22b67222017-08-23 09:55:41 +0200117 },
Tom Herbert47d3d7a2017-10-30 14:16:00 -0700118 {
119 .procname = "max_dst_opts_number",
120 .data = &init_net.ipv6.sysctl.max_dst_opts_cnt,
121 .maxlen = sizeof(int),
122 .mode = 0644,
123 .proc_handler = proc_dointvec
124 },
125 {
126 .procname = "max_hbh_opts_number",
127 .data = &init_net.ipv6.sysctl.max_hbh_opts_cnt,
128 .maxlen = sizeof(int),
129 .mode = 0644,
130 .proc_handler = proc_dointvec
131 },
132 {
133 .procname = "max_dst_opts_length",
134 .data = &init_net.ipv6.sysctl.max_dst_opts_len,
135 .maxlen = sizeof(int),
136 .mode = 0644,
137 .proc_handler = proc_dointvec
138 },
139 {
140 .procname = "max_hbh_length",
141 .data = &init_net.ipv6.sysctl.max_hbh_opts_len,
142 .maxlen = sizeof(int),
143 .mode = 0644,
144 .proc_handler = proc_dointvec
145 },
David Ahernb4bac172018-03-02 08:32:18 -0800146 {
147 .procname = "fib_multipath_hash_policy",
148 .data = &init_net.ipv6.sysctl.multipath_hash_policy,
149 .maxlen = sizeof(int),
150 .mode = 0644,
151 .proc_handler = proc_rt6_multipath_hash_policy,
Matteo Croceeec48442019-07-18 15:58:50 -0700152 .extra1 = SYSCTL_ZERO,
153 .extra2 = SYSCTL_ONE,
David Ahernb4bac172018-03-02 08:32:18 -0800154 },
Ahmed Abdelsalamb5facfd2018-04-24 20:23:16 +0200155 {
156 .procname = "seg6_flowlabel",
157 .data = &init_net.ipv6.sysctl.seg6_flowlabel,
158 .maxlen = sizeof(int),
159 .mode = 0644,
160 .proc_handler = proc_dointvec
161 },
Eric W. Biedermanf8572d82009-11-05 13:32:03 -0800162 { }
Pavel Emelyanov34ac2572008-05-19 13:53:30 -0700163};
164
Joe Perchesfe2c6332013-06-11 23:04:25 -0700165static struct ctl_table ipv6_rotable[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167 .procname = "mld_max_msf",
168 .data = &sysctl_mld_max_msf,
169 .maxlen = sizeof(int),
170 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -0800171 .proc_handler = proc_dointvec
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172 },
Hannes Frederic Sowa2f711932014-09-02 15:49:25 +0200173 {
174 .procname = "mld_qrv",
175 .data = &sysctl_mld_qrv,
176 .maxlen = sizeof(int),
177 .mode = 0644,
178 .proc_handler = proc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700179 .extra1 = SYSCTL_ONE
Hannes Frederic Sowa2f711932014-09-02 15:49:25 +0200180 },
Huw Davies4fee5242016-06-27 15:06:17 -0400181#ifdef CONFIG_NETLABEL
182 {
183 .procname = "calipso_cache_enable",
184 .data = &calipso_cache_enabled,
185 .maxlen = sizeof(int),
186 .mode = 0644,
187 .proc_handler = proc_dointvec,
188 },
189 {
190 .procname = "calipso_cache_bucket_size",
191 .data = &calipso_cache_bucketsize,
192 .maxlen = sizeof(int),
193 .mode = 0644,
194 .proc_handler = proc_dointvec,
195 },
196#endif /* CONFIG_NETLABEL */
Eric W. Biedermanf8572d82009-11-05 13:32:03 -0800197 { }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198};
199
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000200static int __net_init ipv6_sysctl_net_init(struct net *net)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800202 struct ctl_table *ipv6_table;
203 struct ctl_table *ipv6_route_table;
204 struct ctl_table *ipv6_icmp_table;
Cambda Zhud2f7e562020-03-03 14:54:34 +0800205 int err, i;
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800206
207 err = -ENOMEM;
208 ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template),
209 GFP_KERNEL);
210 if (!ipv6_table)
211 goto out;
Cambda Zhud2f7e562020-03-03 14:54:34 +0800212 /* Update the variables to point into the current struct net */
213 for (i = 0; i < ARRAY_SIZE(ipv6_table_template) - 1; i++)
214 ipv6_table[i].data += (void *)net - (void *)&init_net;
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800215
216 ipv6_route_table = ipv6_route_sysctl_init(net);
217 if (!ipv6_route_table)
218 goto out_ipv6_table;
219
220 ipv6_icmp_table = ipv6_icmp_sysctl_init(net);
221 if (!ipv6_icmp_table)
222 goto out_ipv6_route_table;
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800223
Eric W. Biederman6dceb032012-04-19 13:37:09 +0000224 net->ipv6.sysctl.hdr = register_net_sysctl(net, "net/ipv6", ipv6_table);
225 if (!net->ipv6.sysctl.hdr)
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800226 goto out_ipv6_icmp_table;
Daniel Lezcano291480c2008-01-10 02:47:55 -0800227
Eric W. Biederman6dceb032012-04-19 13:37:09 +0000228 net->ipv6.sysctl.route_hdr =
229 register_net_sysctl(net, "net/ipv6/route", ipv6_route_table);
230 if (!net->ipv6.sysctl.route_hdr)
231 goto out_unregister_ipv6_table;
232
233 net->ipv6.sysctl.icmp_hdr =
234 register_net_sysctl(net, "net/ipv6/icmp", ipv6_icmp_table);
235 if (!net->ipv6.sysctl.icmp_hdr)
236 goto out_unregister_route_table;
237
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800238 err = 0;
239out:
240 return err;
Eric W. Biederman6dceb032012-04-19 13:37:09 +0000241out_unregister_route_table:
242 unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
243out_unregister_ipv6_table:
244 unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800245out_ipv6_icmp_table:
246 kfree(ipv6_icmp_table);
247out_ipv6_route_table:
248 kfree(ipv6_route_table);
249out_ipv6_table:
250 kfree(ipv6_table);
251 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252}
253
Alexey Dobriyan2c8c1e72010-01-17 03:35:32 +0000254static void __net_exit ipv6_sysctl_net_exit(struct net *net)
Daniel Lezcano89918fc2008-01-10 02:49:34 -0800255{
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800256 struct ctl_table *ipv6_table;
257 struct ctl_table *ipv6_route_table;
258 struct ctl_table *ipv6_icmp_table;
259
Eric W. Biederman6dceb032012-04-19 13:37:09 +0000260 ipv6_table = net->ipv6.sysctl.hdr->ctl_table_arg;
261 ipv6_route_table = net->ipv6.sysctl.route_hdr->ctl_table_arg;
262 ipv6_icmp_table = net->ipv6.sysctl.icmp_hdr->ctl_table_arg;
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800263
Eric W. Biederman6dceb032012-04-19 13:37:09 +0000264 unregister_net_sysctl_table(net->ipv6.sysctl.icmp_hdr);
265 unregister_net_sysctl_table(net->ipv6.sysctl.route_hdr);
266 unregister_net_sysctl_table(net->ipv6.sysctl.hdr);
Daniel Lezcano760f2d02008-01-10 02:53:43 -0800267
268 kfree(ipv6_table);
269 kfree(ipv6_route_table);
270 kfree(ipv6_icmp_table);
Daniel Lezcano89918fc2008-01-10 02:49:34 -0800271}
272
273static struct pernet_operations ipv6_sysctl_net_ops = {
274 .init = ipv6_sysctl_net_init,
275 .exit = ipv6_sysctl_net_exit,
276};
277
Pavel Emelyanov34ac2572008-05-19 13:53:30 -0700278static struct ctl_table_header *ip6_header;
279
Daniel Lezcano89918fc2008-01-10 02:49:34 -0800280int ipv6_sysctl_register(void)
281{
Fernando Carrijoc19a28e2009-01-07 18:09:08 -0800282 int err = -ENOMEM;
Pavel Emelyanov34ac2572008-05-19 13:53:30 -0700283
Eric W. Biederman43444752012-04-19 13:22:55 +0000284 ip6_header = register_net_sysctl(&init_net, "net/ipv6", ipv6_rotable);
Ian Morris63159f22015-03-29 14:00:04 +0100285 if (!ip6_header)
Pavel Emelyanov34ac2572008-05-19 13:53:30 -0700286 goto out;
287
288 err = register_pernet_subsys(&ipv6_sysctl_net_ops);
289 if (err)
290 goto err_pernet;
291out:
292 return err;
293
294err_pernet:
295 unregister_net_sysctl_table(ip6_header);
296 goto out;
Daniel Lezcano89918fc2008-01-10 02:49:34 -0800297}
298
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299void ipv6_sysctl_unregister(void)
300{
Pavel Emelyanov34ac2572008-05-19 13:53:30 -0700301 unregister_net_sysctl_table(ip6_header);
Daniel Lezcano89918fc2008-01-10 02:49:34 -0800302 unregister_pernet_subsys(&ipv6_sysctl_net_ops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303}