From d62f9ed4a490309bd9e5df0b42ba5d096e7b5902 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 29 Nov 2006 02:35:17 +0100 Subject: [NETFILTER]: nf_conntrack: automatic sysctl registation for conntrack protocols Add helper functions for sysctl registration with optional instantiating of common path elements (like net/netfilter) and use it for support for automatic registation of conntrack protocol sysctls. Signed-off-by: Patrick McHardy --- net/netfilter/nf_sysctl.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 net/netfilter/nf_sysctl.c (limited to 'net/netfilter/nf_sysctl.c') diff --git a/net/netfilter/nf_sysctl.c b/net/netfilter/nf_sysctl.c new file mode 100644 index 000000000000..06ddddb2911f --- /dev/null +++ b/net/netfilter/nf_sysctl.c @@ -0,0 +1,134 @@ +/* nf_sysctl.c netfilter sysctl registration/unregistation + * + * Copyright (c) 2006 Patrick McHardy + */ +#include +#include +#include +#include + +static void +path_free(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table *t, *next; + + for (t = path; t != NULL && t != table; t = next) { + next = t->child; + kfree(t); + } +} + +static struct ctl_table * +path_dup(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table *t, *last = NULL, *tmp; + + for (t = path; t != NULL; t = t->child) { + /* twice the size since path elements are terminated by an + * empty element */ + tmp = kmemdup(t, 2 * sizeof(*t), GFP_KERNEL); + if (tmp == NULL) { + if (last != NULL) + path_free(path, table); + return NULL; + } + + if (last != NULL) + last->child = tmp; + else + path = tmp; + last = tmp; + } + + if (last != NULL) + last->child = table; + else + path = table; + + return path; +} + +struct ctl_table_header * +nf_register_sysctl_table(struct ctl_table *path, struct ctl_table *table) +{ + struct ctl_table_header *header; + + path = path_dup(path, table); + if (path == NULL) + return NULL; + header = register_sysctl_table(path, 0); + if (header == NULL) + path_free(path, table); + return header; +} +EXPORT_SYMBOL_GPL(nf_register_sysctl_table); + +void +nf_unregister_sysctl_table(struct ctl_table_header *header, + struct ctl_table *table) +{ + struct ctl_table *path = header->ctl_table; + + unregister_sysctl_table(header); + path_free(path, table); +} +EXPORT_SYMBOL_GPL(nf_unregister_sysctl_table); + +/* net/netfilter */ +static struct ctl_table nf_net_netfilter_table[] = { + { + .ctl_name = NET_NETFILTER, + .procname = "netfilter", + .mode = 0555, + }, + { + .ctl_name = 0 + } +}; +struct ctl_table nf_net_netfilter_sysctl_path[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = nf_net_netfilter_table, + }, + { + .ctl_name = 0 + } +}; +EXPORT_SYMBOL_GPL(nf_net_netfilter_sysctl_path); + +/* net/ipv4/netfilter */ +static struct ctl_table nf_net_ipv4_netfilter_table[] = { + { + .ctl_name = NET_IPV4_NETFILTER, + .procname = "netfilter", + .mode = 0555, + }, + { + .ctl_name = 0 + } +}; +static struct ctl_table nf_net_ipv4_table[] = { + { + .ctl_name = NET_IPV4, + .procname = "ipv4", + .mode = 0555, + .child = nf_net_ipv4_netfilter_table, + }, + { + .ctl_name = 0 + } +}; +struct ctl_table nf_net_ipv4_netfilter_sysctl_path[] = { + { + .ctl_name = CTL_NET, + .procname = "net", + .mode = 0555, + .child = nf_net_ipv4_table, + }, + { + .ctl_name = 0 + } +}; +EXPORT_SYMBOL_GPL(nf_net_ipv4_netfilter_sysctl_path); -- cgit v1.2.3