diff options
author | Eric Leblond <eric@inl.fr> | 2009-03-16 09:54:21 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2009-03-16 09:54:21 -0400 |
commit | ca735b3aaa945626ba65a3e51145bfe4ecd9e222 (patch) | |
tree | 5fe88e398080a1287fefc10a8bbc54f7eb8c99ba /net | |
parent | 28337ff5438a640afa713d874d076e3a8a9150da (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.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_ULOG.c | 2 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6t_LOG.c | 2 | ||||
-rw-r--r-- | net/netfilter/nf_log.c | 90 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 18 |
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 | ||
467 | static const struct nf_logger ipt_log_logger ={ | 467 | static 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 | ||
382 | static struct nf_logger ipt_ulog_logger = { | 382 | static 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 | ||
480 | static const struct nf_logger ip6t_logger = { | 480 | static 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 | ||
18 | static const struct nf_logger *nf_loggers[NFPROTO_NUMPROTO] __read_mostly; | 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 | static DEFINE_MUTEX(nf_log_mutex); | 20 | static DEFINE_MUTEX(nf_log_mutex); |
20 | 21 | ||
21 | /* return EBUSY if somebody else is registered, EEXIST if the same logger | 22 | static struct nf_logger *__find_logger(int pf, const char *str_logger) |
22 | * is registred, 0 on success. */ | ||
23 | int 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 | } |
46 | EXPORT_SYMBOL(nf_log_register); | ||
47 | 33 | ||
48 | void nf_log_unregister_pf(u_int8_t pf) | 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) | ||
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 | } |
59 | EXPORT_SYMBOL(nf_log_unregister_pf); | 60 | EXPORT_SYMBOL(nf_log_register); |
60 | 61 | ||
61 | void nf_log_unregister(const struct nf_logger *logger) | 62 | void 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 | } |
74 | EXPORT_SYMBOL(nf_log_unregister); | 78 | EXPORT_SYMBOL(nf_log_unregister); |
75 | 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); | ||
100 | |||
76 | void nf_log_packet(u_int8_t pf, | 101 | void 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 | ||
164 | int __init netfilter_log_init(void) | 189 | int __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 | ||
694 | static const struct nf_logger nfulnl_logger = { | 694 | static 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 |
967 | cleanup_logger: | ||
968 | nf_log_unregister(&nfulnl_logger); | ||
969 | #endif | ||
961 | cleanup_subsys: | 970 | cleanup_subsys: |
962 | nfnetlink_subsys_unregister(&nfulnl_subsys); | 971 | nfnetlink_subsys_unregister(&nfulnl_subsys); |
963 | #endif | ||
964 | cleanup_netlink_notifier: | 972 | cleanup_netlink_notifier: |
965 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); | 973 | netlink_unregister_notifier(&nfulnl_rtnl_notifier); |
966 | return status; | 974 | return status; |