06ddddb2911f8f9691757bf9a130907f1bebfc47
[sfrench/cifs-2.6.git] / net / netfilter / nf_sysctl.c
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;
59         header = register_sysctl_table(path, 0);
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);