From ca735b3aaa945626ba65a3e51145bfe4ecd9e222 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 16 Mar 2009 14:54:21 +0100 Subject: netfilter: use a linked list of loggers This patch modifies nf_log to use a linked list of loggers for each protocol. This list of loggers is read and write protected with a mutex. This patch separates registration and binding. To be used as logging module, a module has to register calling nf_log_register() and to bind to a protocol it has to call nf_log_bind_pf(). This patch also converts the logging modules to the new API. For nfnetlink_log, it simply switchs call to register functions to call to bind function and adds a call to nf_log_register() during init. For other modules, it just remove a const flag from the logger structure and replace it with a __read_mostly. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy --- net/netfilter/nf_log.c | 90 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 30 deletions(-) (limited to 'net/netfilter/nf_log.c') diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index fa8ae5d2659..a228b5fbcf7 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c @@ -16,56 +16,60 @@ #define NF_LOG_PREFIXLEN 128 static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; +static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; static DEFINE_MUTEX(nf_log_mutex); -/* return EBUSY if somebody else is registered, EEXIST if the same logger - * is registred, 0 on success. */ -int nf_log_register(u_int8_t pf, const struct nf_logger *logger) +static struct nf_logger *__find_logger(int pf, const char *str_logger) { - int ret; + struct nf_logger *t; - if (pf >= ARRAY_SIZE(nf_loggers)) - return -EINVAL; - - /* Any setup of logging members must be done before - * substituting pointer. */ - ret = mutex_lock_interruptible(&nf_log_mutex); - if (ret < 0) - return ret; - - if (!nf_loggers[pf]) - rcu_assign_pointer(nf_loggers[pf], logger); - else if (nf_loggers[pf] == logger) - ret = -EEXIST; - else - ret = -EBUSY; + list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) { + if (!strnicmp(str_logger, t->name, strlen(t->name))) + return t; + } - mutex_unlock(&nf_log_mutex); - return ret; + return NULL; } -EXPORT_SYMBOL(nf_log_register); -void nf_log_unregister_pf(u_int8_t pf) +/* return EEXIST if the same logger is registred, 0 on success. */ +int nf_log_register(u_int8_t pf, struct nf_logger *logger) { + const struct nf_logger *llog; + if (pf >= ARRAY_SIZE(nf_loggers)) - return; + return -EINVAL; + mutex_lock(&nf_log_mutex); - rcu_assign_pointer(nf_loggers[pf], NULL); + + if (pf == NFPROTO_UNSPEC) { + int i; + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) + list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); + } else { + /* register at end of list to honor first register win */ + list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); + llog = rcu_dereference(nf_loggers[pf]); + if (llog == NULL) + rcu_assign_pointer(nf_loggers[pf], logger); + } + mutex_unlock(&nf_log_mutex); - /* Give time to concurrent readers. */ - synchronize_rcu(); + return 0; } -EXPORT_SYMBOL(nf_log_unregister_pf); +EXPORT_SYMBOL(nf_log_register); -void nf_log_unregister(const struct nf_logger *logger) +void nf_log_unregister(struct nf_logger *logger) { + const struct nf_logger *c_logger; int i; mutex_lock(&nf_log_mutex); for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { - if (nf_loggers[i] == logger) + c_logger = rcu_dereference(nf_loggers[i]); + if (c_logger == logger) rcu_assign_pointer(nf_loggers[i], NULL); + list_del(&logger->list[i]); } mutex_unlock(&nf_log_mutex); @@ -73,6 +77,27 @@ void nf_log_unregister(const struct nf_logger *logger) } EXPORT_SYMBOL(nf_log_unregister); +int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) +{ + mutex_lock(&nf_log_mutex); + if (__find_logger(pf, logger->name) == NULL) { + mutex_unlock(&nf_log_mutex); + return -ENOENT; + } + rcu_assign_pointer(nf_loggers[pf], logger); + mutex_unlock(&nf_log_mutex); + return 0; +} +EXPORT_SYMBOL(nf_log_bind_pf); + +void nf_log_unbind_pf(u_int8_t pf) +{ + mutex_lock(&nf_log_mutex); + rcu_assign_pointer(nf_loggers[pf], NULL); + mutex_unlock(&nf_log_mutex); +} +EXPORT_SYMBOL(nf_log_unbind_pf); + void nf_log_packet(u_int8_t pf, unsigned int hooknum, const struct sk_buff *skb, @@ -163,10 +188,15 @@ static const struct file_operations nflog_file_ops = { int __init netfilter_log_init(void) { + int i; #ifdef CONFIG_PROC_FS if (!proc_create("nf_log", S_IRUGO, proc_net_netfilter, &nflog_file_ops)) return -1; #endif + + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) + INIT_LIST_HEAD(&(nf_loggers_l[i])); + return 0; } -- cgit v1.2.3