Commit | Line | Data |
---|---|---|
1da177e4 LT |
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> | |
1da177e4 LT |
10 | #include <linux/in6.h> |
11 | #include <linux/ipv6.h> | |
12 | #include <net/ndisc.h> | |
13 | #include <net/ipv6.h> | |
14 | #include <net/addrconf.h> | |
04128f23 | 15 | #include <net/inet_frag.h> |
1da177e4 | 16 | |
760f2d01 | 17 | static ctl_table ipv6_table_template[] = { |
1da177e4 LT |
18 | { |
19 | .ctl_name = NET_IPV6_ROUTE, | |
20 | .procname = "route", | |
21 | .maxlen = 0, | |
22 | .mode = 0555, | |
760f2d01 | 23 | .child = ipv6_route_table_template |
1da177e4 LT |
24 | }, |
25 | { | |
26 | .ctl_name = NET_IPV6_ICMP, | |
27 | .procname = "icmp", | |
28 | .maxlen = 0, | |
29 | .mode = 0555, | |
760f2d01 | 30 | .child = ipv6_icmp_table_template |
1da177e4 LT |
31 | }, |
32 | { | |
33 | .ctl_name = NET_IPV6_BINDV6ONLY, | |
34 | .procname = "bindv6only", | |
99bc9c4e | 35 | .data = &init_net.ipv6.sysctl.bindv6only, |
1da177e4 LT |
36 | .maxlen = sizeof(int), |
37 | .mode = 0644, | |
6d9f239a | 38 | .proc_handler = proc_dointvec |
1da177e4 | 39 | }, |
34ac2573 PE |
40 | { .ctl_name = 0 } |
41 | }; | |
42 | ||
43 | static ctl_table ipv6_table[] = { | |
1da177e4 LT |
44 | { |
45 | .ctl_name = NET_IPV6_MLD_MAX_MSF, | |
46 | .procname = "mld_max_msf", | |
47 | .data = &sysctl_mld_max_msf, | |
48 | .maxlen = sizeof(int), | |
49 | .mode = 0644, | |
6d9f239a | 50 | .proc_handler = proc_dointvec |
1da177e4 LT |
51 | }, |
52 | { .ctl_name = 0 } | |
53 | }; | |
54 | ||
3d7cc2ba | 55 | struct ctl_path net_ipv6_ctl_path[] = { |
4d43b78a PE |
56 | { .procname = "net", .ctl_name = CTL_NET, }, |
57 | { .procname = "ipv6", .ctl_name = NET_IPV6, }, | |
58 | { }, | |
1da177e4 | 59 | }; |
3d7cc2ba | 60 | EXPORT_SYMBOL_GPL(net_ipv6_ctl_path); |
1da177e4 | 61 | |
89918fc2 | 62 | static int ipv6_sysctl_net_init(struct net *net) |
1da177e4 | 63 | { |
760f2d01 DL |
64 | struct ctl_table *ipv6_table; |
65 | struct ctl_table *ipv6_route_table; | |
66 | struct ctl_table *ipv6_icmp_table; | |
67 | int err; | |
68 | ||
69 | err = -ENOMEM; | |
70 | ipv6_table = kmemdup(ipv6_table_template, sizeof(ipv6_table_template), | |
71 | GFP_KERNEL); | |
72 | if (!ipv6_table) | |
73 | goto out; | |
74 | ||
75 | ipv6_route_table = ipv6_route_sysctl_init(net); | |
76 | if (!ipv6_route_table) | |
77 | goto out_ipv6_table; | |
5ee09105 | 78 | ipv6_table[0].child = ipv6_route_table; |
760f2d01 DL |
79 | |
80 | ipv6_icmp_table = ipv6_icmp_sysctl_init(net); | |
81 | if (!ipv6_icmp_table) | |
82 | goto out_ipv6_route_table; | |
760f2d01 DL |
83 | ipv6_table[1].child = ipv6_icmp_table; |
84 | ||
99bc9c4e DL |
85 | ipv6_table[2].data = &net->ipv6.sysctl.bindv6only; |
86 | ||
760f2d01 DL |
87 | net->ipv6.sysctl.table = register_net_sysctl_table(net, net_ipv6_ctl_path, |
88 | ipv6_table); | |
760f2d01 DL |
89 | if (!net->ipv6.sysctl.table) |
90 | goto out_ipv6_icmp_table; | |
91 | ||
92 | err = 0; | |
93 | out: | |
94 | return err; | |
291480c0 | 95 | |
760f2d01 DL |
96 | out_ipv6_icmp_table: |
97 | kfree(ipv6_icmp_table); | |
98 | out_ipv6_route_table: | |
99 | kfree(ipv6_route_table); | |
100 | out_ipv6_table: | |
101 | kfree(ipv6_table); | |
102 | goto out; | |
1da177e4 LT |
103 | } |
104 | ||
89918fc2 DL |
105 | static void ipv6_sysctl_net_exit(struct net *net) |
106 | { | |
760f2d01 DL |
107 | struct ctl_table *ipv6_table; |
108 | struct ctl_table *ipv6_route_table; | |
109 | struct ctl_table *ipv6_icmp_table; | |
110 | ||
111 | ipv6_table = net->ipv6.sysctl.table->ctl_table_arg; | |
112 | ipv6_route_table = ipv6_table[0].child; | |
113 | ipv6_icmp_table = ipv6_table[1].child; | |
114 | ||
115 | unregister_net_sysctl_table(net->ipv6.sysctl.table); | |
116 | ||
117 | kfree(ipv6_table); | |
118 | kfree(ipv6_route_table); | |
119 | kfree(ipv6_icmp_table); | |
89918fc2 DL |
120 | } |
121 | ||
122 | static struct pernet_operations ipv6_sysctl_net_ops = { | |
123 | .init = ipv6_sysctl_net_init, | |
124 | .exit = ipv6_sysctl_net_exit, | |
125 | }; | |
126 | ||
34ac2573 PE |
127 | static struct ctl_table_header *ip6_header; |
128 | ||
89918fc2 DL |
129 | int ipv6_sysctl_register(void) |
130 | { | |
c19a28e1 | 131 | int err = -ENOMEM; |
34ac2573 PE |
132 | |
133 | ip6_header = register_net_sysctl_rotable(net_ipv6_ctl_path, ipv6_table); | |
134 | if (ip6_header == NULL) | |
135 | goto out; | |
136 | ||
137 | err = register_pernet_subsys(&ipv6_sysctl_net_ops); | |
138 | if (err) | |
139 | goto err_pernet; | |
140 | out: | |
141 | return err; | |
142 | ||
143 | err_pernet: | |
144 | unregister_net_sysctl_table(ip6_header); | |
145 | goto out; | |
89918fc2 DL |
146 | } |
147 | ||
1da177e4 LT |
148 | void ipv6_sysctl_unregister(void) |
149 | { | |
34ac2573 | 150 | unregister_net_sysctl_table(ip6_header); |
89918fc2 | 151 | unregister_pernet_subsys(&ipv6_sysctl_net_ops); |
1da177e4 | 152 | } |
eeb61f71 AV |
153 | |
154 | static struct ctl_table_header *ip6_base; | |
155 | ||
156 | int ipv6_static_sysctl_register(void) | |
157 | { | |
158 | static struct ctl_table empty[1]; | |
ce3113ec | 159 | ip6_base = register_sysctl_paths(net_ipv6_ctl_path, empty); |
eeb61f71 AV |
160 | if (ip6_base == NULL) |
161 | return -ENOMEM; | |
162 | return 0; | |
163 | } | |
164 | ||
165 | void ipv6_static_sysctl_unregister(void) | |
166 | { | |
167 | unregister_net_sysctl_table(ip6_base); | |
168 | } |