Commit | Line | Data |
---|---|---|
d62f9ed4 PM |
1 | /* nf_sysctl.c netfilter sysctl registration/unregistation |
2 | * | |
3 | * Copyright (c) 2006 Patrick McHardy <kaber@trash.net> | |
4 | */ | |
5 | #include <linux/module.h> | |
6 | #include <linux/sysctl.h> | |
7 | #include <linux/string.h> | |
8 | #include <linux/slab.h> | |
9 | ||
10 | static void | |
11 | path_free(struct ctl_table *path, struct ctl_table *table) | |
12 | { | |
13 | struct ctl_table *t, *next; | |
14 | ||
15 | for (t = path; t != NULL && t != table; t = next) { | |
16 | next = t->child; | |
17 | kfree(t); | |
18 | } | |
19 | } | |
20 | ||
21 | static struct ctl_table * | |
22 | path_dup(struct ctl_table *path, struct ctl_table *table) | |
23 | { | |
24 | struct ctl_table *t, *last = NULL, *tmp; | |
25 | ||
26 | for (t = path; t != NULL; t = t->child) { | |
27 | /* twice the size since path elements are terminated by an | |
28 | * empty element */ | |
29 | tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL); | |
30 | if (tmp == NULL) { | |
31 | if (last != NULL) | |
32 | path_free(path, table); | |
33 | return NULL; | |
34 | } | |
35 | ||
36 | if (last != NULL) | |
37 | last->child = tmp; | |
38 | else | |
39 | path = tmp; | |
40 | last = tmp; | |
41 | } | |
42 | ||
43 | if (last != NULL) | |
44 | last->child = table; | |
45 | else | |
46 | path = table; | |
47 | ||
48 | return path; | |
49 | } | |
50 | ||
51 | struct ctl_table_header * | |
52 | nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table) | |
53 | { | |
54 | struct ctl_table_header *header; | |
55 | ||
56 | path = path_dup(path, table); | |
57 | if (path == NULL) | |
58 | return NULL; | |
0b4d4147 | 59 | header = register_sysctl_table(path); |
d62f9ed4 PM |
60 | if (header == NULL) |
61 | path_free(path, table); | |
62 | return header; | |
63 | } | |
64 | EXPORT_SYMBOL_GPL(nf_register_sysctl_table); | |
65 | ||
66 | void | |
67 | nf_unregister_sysctl_table(struct ctl_table_header *header, | |
68 | struct ctl_table *table) | |
69 | { | |
70 | struct ctl_table *path = header->ctl_table; | |
71 | ||
72 | unregister_sysctl_table(header); | |
73 | path_free(path, table); | |
74 | } | |
75 | EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table); | |
76 | ||
77 | /* net/netfilter */ | |
78 | static struct ctl_table nf_net_netfilter_table[] = { | |
79 | { | |
80 | .ctl_name = NET_NETFILTER, | |
81 | .procname = "netfilter", | |
82 | .mode = 0555, | |
83 | }, | |
84 | { | |
85 | .ctl_name = 0 | |
86 | } | |
87 | }; | |
88 | struct ctl_table nf_net_netfilter_sysctl_path[] = { | |
89 | { | |
90 | .ctl_name = CTL_NET, | |
91 | .procname = "net", | |
92 | .mode = 0555, | |
93 | .child = nf_net_netfilter_table, | |
94 | }, | |
95 | { | |
96 | .ctl_name = 0 | |
97 | } | |
98 | }; | |
99 | EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path); | |
100 | ||
101 | /* net/ipv4/netfilter */ | |
102 | static struct ctl_table nf_net_ipv4_netfilter_table[] = { | |
103 | { | |
104 | .ctl_name = NET_IPV4_NETFILTER, | |
105 | .procname = "netfilter", | |
106 | .mode = 0555, | |
107 | }, | |
108 | { | |
109 | .ctl_name = 0 | |
110 | } | |
111 | }; | |
112 | static struct ctl_table nf_net_ipv4_table[] = { | |
113 | { | |
114 | .ctl_name = NET_IPV4, | |
115 | .procname = "ipv4", | |
116 | .mode = 0555, | |
117 | .child = nf_net_ipv4_netfilter_table, | |
118 | }, | |
119 | { | |
120 | .ctl_name = 0 | |
121 | } | |
122 | }; | |
123 | struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = { | |
124 | { | |
125 | .ctl_name = CTL_NET, | |
126 | .procname = "net", | |
127 | .mode = 0555, | |
128 | .child = nf_net_ipv4_table, | |
129 | }, | |
130 | { | |
131 | .ctl_name = 0 | |
132 | } | |
133 | }; | |
134 | EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path); |