1 // SPDX-License-Identifier: GPL-2.0
3 * sysctl_net_ipv6.c: sysctl interface to net IPV6 subsystem.
6 * YOSHIFUJI Hideaki @USAGI: added icmp sysctl table.
10 #include <linux/sysctl.h>
11 #include <linux/in6.h>
12 #include <linux/ipv6.h>
13 #include <linux/slab.h>
14 #include <linux/export.h>
15 #include <net/ndisc.h>
17 #include <net/addrconf.h>
18 #include <net/inet_frag.h>
19 #include <net/netevent.h>
20 #include <net/ip_fib.h>
21 #ifdef CONFIG_NETLABEL
22 #include <net/calipso.h>
24 #include <linux/ioam6.h>
26 static int flowlabel_reflect_max
= 0x7;
27 static int auto_flowlabels_max
= IP6_AUTO_FLOW_LABEL_MAX
;
28 static u32 rt6_multipath_hash_fields_all_mask
=
29 FIB_MULTIPATH_HASH_FIELD_ALL_MASK
;
30 static u32 ioam6_id_max
= IOAM6_DEFAULT_ID
;
31 static u64 ioam6_id_wide_max
= IOAM6_DEFAULT_ID_WIDE
;
33 static int proc_rt6_multipath_hash_policy(const struct ctl_table
*table
, int write
,
34 void *buffer
, size_t *lenp
, loff_t
*ppos
)
39 net
= container_of(table
->data
, struct net
,
40 ipv6
.sysctl
.multipath_hash_policy
);
41 ret
= proc_dou8vec_minmax(table
, write
, buffer
, lenp
, ppos
);
42 if (write
&& ret
== 0)
43 call_netevent_notifiers(NETEVENT_IPV6_MPATH_HASH_UPDATE
, net
);
49 proc_rt6_multipath_hash_fields(const struct ctl_table
*table
, int write
, void *buffer
,
50 size_t *lenp
, loff_t
*ppos
)
55 net
= container_of(table
->data
, struct net
,
56 ipv6
.sysctl
.multipath_hash_fields
);
57 ret
= proc_douintvec_minmax(table
, write
, buffer
, lenp
, ppos
);
58 if (write
&& ret
== 0)
59 call_netevent_notifiers(NETEVENT_IPV6_MPATH_HASH_UPDATE
, net
);
64 static struct ctl_table ipv6_table_template
[] = {
66 .procname
= "bindv6only",
67 .data
= &init_net
.ipv6
.sysctl
.bindv6only
,
70 .proc_handler
= proc_dou8vec_minmax
,
73 .procname
= "anycast_src_echo_reply",
74 .data
= &init_net
.ipv6
.sysctl
.anycast_src_echo_reply
,
77 .proc_handler
= proc_dou8vec_minmax
,
80 .procname
= "flowlabel_consistency",
81 .data
= &init_net
.ipv6
.sysctl
.flowlabel_consistency
,
84 .proc_handler
= proc_dou8vec_minmax
,
87 .procname
= "auto_flowlabels",
88 .data
= &init_net
.ipv6
.sysctl
.auto_flowlabels
,
91 .proc_handler
= proc_dou8vec_minmax
,
92 .extra2
= &auto_flowlabels_max
95 .procname
= "fwmark_reflect",
96 .data
= &init_net
.ipv6
.sysctl
.fwmark_reflect
,
99 .proc_handler
= proc_dou8vec_minmax
,
102 .procname
= "idgen_retries",
103 .data
= &init_net
.ipv6
.sysctl
.idgen_retries
,
104 .maxlen
= sizeof(int),
106 .proc_handler
= proc_dointvec
,
109 .procname
= "idgen_delay",
110 .data
= &init_net
.ipv6
.sysctl
.idgen_delay
,
111 .maxlen
= sizeof(int),
113 .proc_handler
= proc_dointvec_jiffies
,
116 .procname
= "flowlabel_state_ranges",
117 .data
= &init_net
.ipv6
.sysctl
.flowlabel_state_ranges
,
118 .maxlen
= sizeof(u8
),
120 .proc_handler
= proc_dou8vec_minmax
,
123 .procname
= "ip_nonlocal_bind",
124 .data
= &init_net
.ipv6
.sysctl
.ip_nonlocal_bind
,
125 .maxlen
= sizeof(u8
),
127 .proc_handler
= proc_dou8vec_minmax
,
130 .procname
= "flowlabel_reflect",
131 .data
= &init_net
.ipv6
.sysctl
.flowlabel_reflect
,
132 .maxlen
= sizeof(int),
134 .proc_handler
= proc_dointvec_minmax
,
135 .extra1
= SYSCTL_ZERO
,
136 .extra2
= &flowlabel_reflect_max
,
139 .procname
= "max_dst_opts_number",
140 .data
= &init_net
.ipv6
.sysctl
.max_dst_opts_cnt
,
141 .maxlen
= sizeof(int),
143 .proc_handler
= proc_dointvec
146 .procname
= "max_hbh_opts_number",
147 .data
= &init_net
.ipv6
.sysctl
.max_hbh_opts_cnt
,
148 .maxlen
= sizeof(int),
150 .proc_handler
= proc_dointvec
153 .procname
= "max_dst_opts_length",
154 .data
= &init_net
.ipv6
.sysctl
.max_dst_opts_len
,
155 .maxlen
= sizeof(int),
157 .proc_handler
= proc_dointvec
160 .procname
= "max_hbh_length",
161 .data
= &init_net
.ipv6
.sysctl
.max_hbh_opts_len
,
162 .maxlen
= sizeof(int),
164 .proc_handler
= proc_dointvec
167 .procname
= "fib_multipath_hash_policy",
168 .data
= &init_net
.ipv6
.sysctl
.multipath_hash_policy
,
169 .maxlen
= sizeof(u8
),
171 .proc_handler
= proc_rt6_multipath_hash_policy
,
172 .extra1
= SYSCTL_ZERO
,
173 .extra2
= SYSCTL_THREE
,
176 .procname
= "fib_multipath_hash_fields",
177 .data
= &init_net
.ipv6
.sysctl
.multipath_hash_fields
,
178 .maxlen
= sizeof(u32
),
180 .proc_handler
= proc_rt6_multipath_hash_fields
,
181 .extra1
= SYSCTL_ONE
,
182 .extra2
= &rt6_multipath_hash_fields_all_mask
,
185 .procname
= "seg6_flowlabel",
186 .data
= &init_net
.ipv6
.sysctl
.seg6_flowlabel
,
187 .maxlen
= sizeof(int),
189 .proc_handler
= proc_dointvec
192 .procname
= "fib_notify_on_flag_change",
193 .data
= &init_net
.ipv6
.sysctl
.fib_notify_on_flag_change
,
194 .maxlen
= sizeof(u8
),
196 .proc_handler
= proc_dou8vec_minmax
,
197 .extra1
= SYSCTL_ZERO
,
198 .extra2
= SYSCTL_TWO
,
201 .procname
= "ioam6_id",
202 .data
= &init_net
.ipv6
.sysctl
.ioam6_id
,
203 .maxlen
= sizeof(u32
),
205 .proc_handler
= proc_douintvec_minmax
,
206 .extra2
= &ioam6_id_max
,
209 .procname
= "ioam6_id_wide",
210 .data
= &init_net
.ipv6
.sysctl
.ioam6_id_wide
,
211 .maxlen
= sizeof(u64
),
213 .proc_handler
= proc_doulongvec_minmax
,
214 .extra2
= &ioam6_id_wide_max
,
218 static struct ctl_table ipv6_rotable
[] = {
220 .procname
= "mld_max_msf",
221 .data
= &sysctl_mld_max_msf
,
222 .maxlen
= sizeof(int),
224 .proc_handler
= proc_dointvec
227 .procname
= "mld_qrv",
228 .data
= &sysctl_mld_qrv
,
229 .maxlen
= sizeof(int),
231 .proc_handler
= proc_dointvec_minmax
,
234 #ifdef CONFIG_NETLABEL
236 .procname
= "calipso_cache_enable",
237 .data
= &calipso_cache_enabled
,
238 .maxlen
= sizeof(int),
240 .proc_handler
= proc_dointvec
,
243 .procname
= "calipso_cache_bucket_size",
244 .data
= &calipso_cache_bucketsize
,
245 .maxlen
= sizeof(int),
247 .proc_handler
= proc_dointvec
,
249 #endif /* CONFIG_NETLABEL */
252 static int __net_init
ipv6_sysctl_net_init(struct net
*net
)
254 size_t table_size
= ARRAY_SIZE(ipv6_table_template
);
255 struct ctl_table
*ipv6_table
;
256 struct ctl_table
*ipv6_route_table
;
257 struct ctl_table
*ipv6_icmp_table
;
261 ipv6_table
= kmemdup(ipv6_table_template
, sizeof(ipv6_table_template
),
265 /* Update the variables to point into the current struct net */
266 for (i
= 0; i
< table_size
; i
++)
267 ipv6_table
[i
].data
+= (void *)net
- (void *)&init_net
;
269 ipv6_route_table
= ipv6_route_sysctl_init(net
);
270 if (!ipv6_route_table
)
273 ipv6_icmp_table
= ipv6_icmp_sysctl_init(net
);
274 if (!ipv6_icmp_table
)
275 goto out_ipv6_route_table
;
277 net
->ipv6
.sysctl
.hdr
= register_net_sysctl_sz(net
, "net/ipv6",
278 ipv6_table
, table_size
);
279 if (!net
->ipv6
.sysctl
.hdr
)
280 goto out_ipv6_icmp_table
;
282 net
->ipv6
.sysctl
.route_hdr
= register_net_sysctl_sz(net
,
285 ipv6_route_sysctl_table_size(net
));
286 if (!net
->ipv6
.sysctl
.route_hdr
)
287 goto out_unregister_ipv6_table
;
289 net
->ipv6
.sysctl
.icmp_hdr
= register_net_sysctl_sz(net
,
292 ipv6_icmp_sysctl_table_size());
293 if (!net
->ipv6
.sysctl
.icmp_hdr
)
294 goto out_unregister_route_table
;
299 out_unregister_route_table
:
300 unregister_net_sysctl_table(net
->ipv6
.sysctl
.route_hdr
);
301 out_unregister_ipv6_table
:
302 unregister_net_sysctl_table(net
->ipv6
.sysctl
.hdr
);
304 kfree(ipv6_icmp_table
);
305 out_ipv6_route_table
:
306 kfree(ipv6_route_table
);
312 static void __net_exit
ipv6_sysctl_net_exit(struct net
*net
)
314 const struct ctl_table
*ipv6_table
;
315 const struct ctl_table
*ipv6_route_table
;
316 const struct ctl_table
*ipv6_icmp_table
;
318 ipv6_table
= net
->ipv6
.sysctl
.hdr
->ctl_table_arg
;
319 ipv6_route_table
= net
->ipv6
.sysctl
.route_hdr
->ctl_table_arg
;
320 ipv6_icmp_table
= net
->ipv6
.sysctl
.icmp_hdr
->ctl_table_arg
;
322 unregister_net_sysctl_table(net
->ipv6
.sysctl
.icmp_hdr
);
323 unregister_net_sysctl_table(net
->ipv6
.sysctl
.route_hdr
);
324 unregister_net_sysctl_table(net
->ipv6
.sysctl
.hdr
);
327 kfree(ipv6_route_table
);
328 kfree(ipv6_icmp_table
);
331 static struct pernet_operations ipv6_sysctl_net_ops
= {
332 .init
= ipv6_sysctl_net_init
,
333 .exit
= ipv6_sysctl_net_exit
,
336 static struct ctl_table_header
*ip6_header
;
338 int ipv6_sysctl_register(void)
342 ip6_header
= register_net_sysctl(&init_net
, "net/ipv6", ipv6_rotable
);
346 err
= register_pernet_subsys(&ipv6_sysctl_net_ops
);
353 unregister_net_sysctl_table(ip6_header
);
357 void ipv6_sysctl_unregister(void)
359 unregister_net_sysctl_table(ip6_header
);
360 unregister_pernet_subsys(&ipv6_sysctl_net_ops
);