Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <eric@inl.fr>
Signed-off-by: Patrick McHardy <kaber@trash.net>

authored by

Eric Leblond and committed by
Patrick McHardy
ca735b3a 28337ff5

+85 -42
+8 -3
include/net/netfilter/nf_log.h
··· 1 1 #ifndef _NF_LOG_H 2 2 #define _NF_LOG_H 3 3 4 + #include <linux/netfilter.h> 5 + 4 6 /* those NF_LOG_* defines and struct nf_loginfo are legacy definitios that will 5 7 * disappear once iptables is replaced with pkttables. Please DO NOT use them 6 8 * for any new code! */ ··· 42 40 struct module *me; 43 41 nf_logfn *logfn; 44 42 char *name; 43 + struct list_head list[NFPROTO_NUMPROTO]; 45 44 }; 46 45 47 46 /* Function to register/unregister log function. */ 48 - int nf_log_register(u_int8_t pf, const struct nf_logger *logger); 49 - void nf_log_unregister(const struct nf_logger *logger); 50 - void nf_log_unregister_pf(u_int8_t pf); 47 + int nf_log_register(u_int8_t pf, struct nf_logger *logger); 48 + void nf_log_unregister(struct nf_logger *logger); 49 + 50 + int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger); 51 + void nf_log_unbind_pf(u_int8_t pf); 51 52 52 53 /* Calls the registered backend logging function */ 53 54 void nf_log_packet(u_int8_t pf,
+1 -1
net/ipv4/netfilter/ipt_LOG.c
··· 464 464 .me = THIS_MODULE, 465 465 }; 466 466 467 - static const struct nf_logger ipt_log_logger ={ 467 + static struct nf_logger ipt_log_logger __read_mostly = { 468 468 .name = "ipt_LOG", 469 469 .logfn = &ipt_log_packet, 470 470 .me = THIS_MODULE,
+1 -1
net/ipv4/netfilter/ipt_ULOG.c
··· 379 379 .me = THIS_MODULE, 380 380 }; 381 381 382 - static struct nf_logger ipt_ulog_logger = { 382 + static struct nf_logger ipt_ulog_logger __read_mostly = { 383 383 .name = "ipt_ULOG", 384 384 .logfn = ipt_logfn, 385 385 .me = THIS_MODULE,
+1 -1
net/ipv6/netfilter/ip6t_LOG.c
··· 477 477 .me = THIS_MODULE, 478 478 }; 479 479 480 - static const struct nf_logger ip6t_logger = { 480 + static struct nf_logger ip6t_logger __read_mostly = { 481 481 .name = "ip6t_LOG", 482 482 .logfn = &ip6t_log_packet, 483 483 .me = THIS_MODULE,
+61 -31
net/netfilter/nf_log.c
··· 16 16 #define NF_LOG_PREFIXLEN 128 17 17 18 18 static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; 19 + static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; 19 20 static DEFINE_MUTEX(nf_log_mutex); 20 21 21 - /* return EBUSY if somebody else is registered, EEXIST if the same logger 22 - * is registred, 0 on success. */ 23 - int nf_log_register(u_int8_t pf, const struct nf_logger *logger) 22 + static struct nf_logger *__find_logger(int pf, const char *str_logger) 24 23 { 25 - int ret; 24 + struct nf_logger *t; 25 + 26 + list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) { 27 + if (!strnicmp(str_logger, t->name, strlen(t->name))) 28 + return t; 29 + } 30 + 31 + return NULL; 32 + } 33 + 34 + /* return EEXIST if the same logger is registred, 0 on success. */ 35 + int nf_log_register(u_int8_t pf, struct nf_logger *logger) 36 + { 37 + const struct nf_logger *llog; 26 38 27 39 if (pf >= ARRAY_SIZE(nf_loggers)) 28 40 return -EINVAL; 29 41 30 - /* Any setup of logging members must be done before 31 - * substituting pointer. */ 32 - ret = mutex_lock_interruptible(&nf_log_mutex); 33 - if (ret < 0) 34 - return ret; 42 + mutex_lock(&nf_log_mutex); 35 43 36 - if (!nf_loggers[pf]) 37 - rcu_assign_pointer(nf_loggers[pf], logger); 38 - else if (nf_loggers[pf] == logger) 39 - ret = -EEXIST; 40 - else 41 - ret = -EBUSY; 44 + if (pf == NFPROTO_UNSPEC) { 45 + int i; 46 + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) 47 + list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); 48 + } else { 49 + /* register at end of list to honor first register win */ 50 + list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); 51 + llog = rcu_dereference(nf_loggers[pf]); 52 + if (llog == NULL) 53 + rcu_assign_pointer(nf_loggers[pf], logger); 54 + } 42 55 43 56 mutex_unlock(&nf_log_mutex); 44 - return ret; 57 + 58 + return 0; 45 59 } 46 60 EXPORT_SYMBOL(nf_log_register); 47 61 48 - void nf_log_unregister_pf(u_int8_t pf) 62 + void nf_log_unregister(struct nf_logger *logger) 49 63 { 50 - if (pf >= ARRAY_SIZE(nf_loggers)) 51 - return; 52 - mutex_lock(&nf_log_mutex); 53 - rcu_assign_pointer(nf_loggers[pf], NULL); 54 - mutex_unlock(&nf_log_mutex); 55 - 56 - /* Give time to concurrent readers. */ 57 - synchronize_rcu(); 58 - } 59 - EXPORT_SYMBOL(nf_log_unregister_pf); 60 - 61 - void nf_log_unregister(const struct nf_logger *logger) 62 - { 64 + const struct nf_logger *c_logger; 63 65 int i; 64 66 65 67 mutex_lock(&nf_log_mutex); 66 68 for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { 67 - if (nf_loggers[i] == logger) 69 + c_logger = rcu_dereference(nf_loggers[i]); 70 + if (c_logger == logger) 68 71 rcu_assign_pointer(nf_loggers[i], NULL); 72 + list_del(&logger->list[i]); 69 73 } 70 74 mutex_unlock(&nf_log_mutex); 71 75 72 76 synchronize_rcu(); 73 77 } 74 78 EXPORT_SYMBOL(nf_log_unregister); 79 + 80 + int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger) 81 + { 82 + mutex_lock(&nf_log_mutex); 83 + if (__find_logger(pf, logger->name) == NULL) { 84 + mutex_unlock(&nf_log_mutex); 85 + return -ENOENT; 86 + } 87 + rcu_assign_pointer(nf_loggers[pf], logger); 88 + mutex_unlock(&nf_log_mutex); 89 + return 0; 90 + } 91 + EXPORT_SYMBOL(nf_log_bind_pf); 92 + 93 + void nf_log_unbind_pf(u_int8_t pf) 94 + { 95 + mutex_lock(&nf_log_mutex); 96 + rcu_assign_pointer(nf_loggers[pf], NULL); 97 + mutex_unlock(&nf_log_mutex); 98 + } 99 + EXPORT_SYMBOL(nf_log_unbind_pf); 75 100 76 101 void nf_log_packet(u_int8_t pf, 77 102 unsigned int hooknum, ··· 188 163 189 164 int __init netfilter_log_init(void) 190 165 { 166 + int i; 191 167 #ifdef CONFIG_PROC_FS 192 168 if (!proc_create("nf_log", S_IRUGO, 193 169 proc_net_netfilter, &nflog_file_ops)) 194 170 return -1; 195 171 #endif 172 + 173 + for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) 174 + INIT_LIST_HEAD(&(nf_loggers_l[i])); 175 + 196 176 return 0; 197 177 }