aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric Leblond <eric@inl.fr>2009-03-16 09:54:21 -0400
committerPatrick McHardy <kaber@trash.net>2009-03-16 09:54:21 -0400
commitca735b3aaa945626ba65a3e51145bfe4ecd9e222 (patch)
tree5fe88e398080a1287fefc10a8bbc54f7eb8c99ba /net
parent28337ff5438a640afa713d874d076e3a8a9150da (diff)
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>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ipt_LOG.c2
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c2
-rw-r--r--net/ipv6/netfilter/ip6t_LOG.c2
-rw-r--r--net/netfilter/nf_log.c90
-rw-r--r--net/netfilter/nfnetlink_log.c18
5 files changed, 76 insertions, 38 deletions
diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
index 27a78fbbd92b..acc44c69eb68 100644
--- a/net/ipv4/netfilter/ipt_LOG.c
+++ b/net/ipv4/netfilter/ipt_LOG.c
@@ -464,7 +464,7 @@ static struct xt_target log_tg_reg __read_mostly = {
464 .me = THIS_MODULE, 464 .me = THIS_MODULE,
465}; 465};
466 466
467static const struct nf_logger ipt_log_logger ={ 467static struct nf_logger ipt_log_logger __read_mostly = {
468 .name = "ipt_LOG", 468 .name = "ipt_LOG",
469 .logfn = &ipt_log_packet, 469 .logfn = &ipt_log_packet,
470 .me = THIS_MODULE, 470 .me = THIS_MODULE,
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 18a2826b57c6..d32cc4bb328a 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -379,7 +379,7 @@ static struct xt_target ulog_tg_reg __read_mostly = {
379 .me = THIS_MODULE, 379 .me = THIS_MODULE,
380}; 380};
381 381
382static struct nf_logger ipt_ulog_logger = { 382static struct nf_logger ipt_ulog_logger __read_mostly = {
383 .name = "ipt_ULOG", 383 .name = "ipt_ULOG",
384 .logfn = ipt_logfn, 384 .logfn = ipt_logfn,
385 .me = THIS_MODULE, 385 .me = THIS_MODULE,
diff --git a/net/ipv6/netfilter/ip6t_LOG.c b/net/ipv6/netfilter/ip6t_LOG.c
index 37adf5abc51e..7018cac4fddc 100644
--- a/net/ipv6/netfilter/ip6t_LOG.c
+++ b/net/ipv6/netfilter/ip6t_LOG.c
@@ -477,7 +477,7 @@ static struct xt_target log_tg6_reg __read_mostly = {
477 .me = THIS_MODULE, 477 .me = THIS_MODULE,
478}; 478};
479 479
480static const struct nf_logger ip6t_logger = { 480static struct nf_logger ip6t_logger __read_mostly = {
481 .name = "ip6t_LOG", 481 .name = "ip6t_LOG",
482 .logfn = &ip6t_log_packet, 482 .logfn = &ip6t_log_packet,
483 .me = THIS_MODULE, 483 .me = THIS_MODULE,
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index fa8ae5d2659c..a228b5fbcf7c 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -16,56 +16,60 @@
16#define NF_LOG_PREFIXLEN 128 16#define NF_LOG_PREFIXLEN 128
17 17
18static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; 18static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly;
19static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly;
19static DEFINE_MUTEX(nf_log_mutex); 20static DEFINE_MUTEX(nf_log_mutex);
20 21
21/* return EBUSY if somebody else is registered, EEXIST if the same logger 22static struct nf_logger *__find_logger(int pf, const char *str_logger)
22 * is registred, 0 on success. */
23int nf_log_register(u_int8_t pf, const struct nf_logger *logger)
24{ 23{
25 int ret; 24 struct nf_logger *t;
26 25
27 if (pf >= ARRAY_SIZE(nf_loggers)) 26 list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) {
28 return -EINVAL; 27 if (!strnicmp(str_logger, t->name, strlen(t->name)))
29 28 return t;
30 /* Any setup of logging members must be done before 29 }
31 * substituting pointer. */
32 ret = mutex_lock_interruptible(&nf_log_mutex);
33 if (ret < 0)
34 return ret;
35
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;
42 30
43 mutex_unlock(&nf_log_mutex); 31 return NULL;
44 return ret;
45} 32}
46EXPORT_SYMBOL(nf_log_register);
47 33
48void nf_log_unregister_pf(u_int8_t pf) 34/* return EEXIST if the same logger is registred, 0 on success. */
35int nf_log_register(u_int8_t pf, struct nf_logger *logger)
49{ 36{
37 const struct nf_logger *llog;
38
50 if (pf >= ARRAY_SIZE(nf_loggers)) 39 if (pf >= ARRAY_SIZE(nf_loggers))
51 return; 40 return -EINVAL;
41
52 mutex_lock(&nf_log_mutex); 42 mutex_lock(&nf_log_mutex);
53 rcu_assign_pointer(nf_loggers[pf], NULL); 43
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 }
55
54 mutex_unlock(&nf_log_mutex); 56 mutex_unlock(&nf_log_mutex);
55 57
56 /* Give time to concurrent readers. */ 58 return 0;
57 synchronize_rcu();
58} 59}
59EXPORT_SYMBOL(nf_log_unregister_pf); 60EXPORT_SYMBOL(nf_log_register);
60 61
61void nf_log_unregister(const struct nf_logger *logger) 62void nf_log_unregister(struct nf_logger *logger)
62{ 63{
64 const struct nf_logger *c_logger;
63 int i; 65 int i;
64 66
65 mutex_lock(&nf_log_mutex); 67 mutex_lock(&nf_log_mutex);
66 for (i = 0; i < ARRAY_SIZE(nf_loggers); i++) { 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 rcu_assign_pointer(nf_loggers[i], NULL); 71 rcu_assign_pointer(nf_loggers[i], NULL);
72 list_del(&logger->list[i]);
69 } 73 }
70 mutex_unlock(&nf_log_mutex); 74 mutex_unlock(&nf_log_mutex);
71 75
@@ -73,6 +77,27 @@ void nf_log_unregister(const struct nf_logger *logger)
73} 77}
74EXPORT_SYMBOL(nf_log_unregister); 78EXPORT_SYMBOL(nf_log_unregister);
75 79
80int 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}
91EXPORT_SYMBOL(nf_log_bind_pf);
92
93void 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}
99EXPORT_SYMBOL(nf_log_unbind_pf);
100
76void nf_log_packet(u_int8_t pf, 101void nf_log_packet(u_int8_t pf,
77 unsigned int hooknum, 102 unsigned int hooknum,
78 const struct sk_buff *skb, 103 const struct sk_buff *skb,
@@ -163,10 +188,15 @@ static const struct file_operations nflog_file_ops = {
163 188
164int __init netfilter_log_init(void) 189int __init netfilter_log_init(void)
165{ 190{
191 int i;
166#ifdef CONFIG_PROC_FS 192#ifdef CONFIG_PROC_FS
167 if (!proc_create("nf_log", S_IRUGO, 193 if (!proc_create("nf_log", S_IRUGO,
168 proc_net_netfilter, &nflog_file_ops)) 194 proc_net_netfilter, &nflog_file_ops))
169 return -1; 195 return -1;
170#endif 196#endif
197
198 for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
199 INIT_LIST_HEAD(&(nf_loggers_l[i]));
200
171 return 0; 201 return 0;
172} 202}
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index fa49dc7fe100..3eae3fca29d8 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -691,7 +691,7 @@ nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb,
691 return -ENOTSUPP; 691 return -ENOTSUPP;
692} 692}
693 693
694static const struct nf_logger nfulnl_logger = { 694static struct nf_logger nfulnl_logger __read_mostly = {
695 .name = "nfnetlink_log", 695 .name = "nfnetlink_log",
696 .logfn = &nfulnl_log_packet, 696 .logfn = &nfulnl_log_packet,
697 .me = THIS_MODULE, 697 .me = THIS_MODULE,
@@ -723,9 +723,9 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
723 /* Commands without queue context */ 723 /* Commands without queue context */
724 switch (cmd->command) { 724 switch (cmd->command) {
725 case NFULNL_CFG_CMD_PF_BIND: 725 case NFULNL_CFG_CMD_PF_BIND:
726 return nf_log_register(pf, &nfulnl_logger); 726 return nf_log_bind_pf(pf, &nfulnl_logger);
727 case NFULNL_CFG_CMD_PF_UNBIND: 727 case NFULNL_CFG_CMD_PF_UNBIND:
728 nf_log_unregister_pf(pf); 728 nf_log_unbind_pf(pf);
729 return 0; 729 return 0;
730 } 730 }
731 } 731 }
@@ -950,17 +950,25 @@ static int __init nfnetlink_log_init(void)
950 goto cleanup_netlink_notifier; 950 goto cleanup_netlink_notifier;
951 } 951 }
952 952
953 status = nf_log_register(NFPROTO_UNSPEC, &nfulnl_logger);
954 if (status < 0) {
955 printk(KERN_ERR "log: failed to register logger\n");
956 goto cleanup_subsys;
957 }
958
953#ifdef CONFIG_PROC_FS 959#ifdef CONFIG_PROC_FS
954 if (!proc_create("nfnetlink_log", 0440, 960 if (!proc_create("nfnetlink_log", 0440,
955 proc_net_netfilter, &nful_file_ops)) 961 proc_net_netfilter, &nful_file_ops))
956 goto cleanup_subsys; 962 goto cleanup_logger;
957#endif 963#endif
958 return status; 964 return status;
959 965
960#ifdef CONFIG_PROC_FS 966#ifdef CONFIG_PROC_FS
967cleanup_logger:
968 nf_log_unregister(&nfulnl_logger);
969#endif
961cleanup_subsys: 970cleanup_subsys:
962 nfnetlink_subsys_unregister(&nfulnl_subsys); 971 nfnetlink_subsys_unregister(&nfulnl_subsys);
963#endif
964cleanup_netlink_notifier: 972cleanup_netlink_notifier:
965 netlink_unregister_notifier(&nfulnl_rtnl_notifier); 973 netlink_unregister_notifier(&nfulnl_rtnl_notifier);
966 return status; 974 return status;