]>
Commit | Line | Data |
---|---|---|
f6ebe77f HW |
1 | #include <linux/config.h> |
2 | #include <linux/kernel.h> | |
3 | #include <linux/init.h> | |
4 | #include <linux/module.h> | |
5 | #include <linux/proc_fs.h> | |
6 | #include <linux/skbuff.h> | |
7 | #include <linux/netfilter.h> | |
bbd86b9f | 8 | #include <linux/seq_file.h> |
f6ebe77f HW |
9 | #include <net/protocol.h> |
10 | ||
11 | #include "nf_internals.h" | |
12 | ||
13 | /* Internal logging interface, which relies on the real | |
14 | LOG target modules */ | |
15 | ||
16 | #define NF_LOG_PREFIXLEN 128 | |
17 | ||
18 | static struct nf_logger *nf_logging[NPROTO]; /* = NULL */ | |
19 | static DEFINE_SPINLOCK(nf_log_lock); | |
20 | ||
d72367b6 HW |
21 | /* return EBUSY if somebody else is registered, EEXIST if the same logger |
22 | * is registred, 0 on success. */ | |
f6ebe77f HW |
23 | int nf_log_register(int pf, struct nf_logger *logger) |
24 | { | |
25 | int ret = -EBUSY; | |
26 | ||
8a61fadb HW |
27 | if (pf >= NPROTO) |
28 | return -EINVAL; | |
29 | ||
f6ebe77f HW |
30 | /* Any setup of logging members must be done before |
31 | * substituting pointer. */ | |
32 | spin_lock(&nf_log_lock); | |
33 | if (!nf_logging[pf]) { | |
34 | rcu_assign_pointer(nf_logging[pf], logger); | |
35 | ret = 0; | |
d72367b6 HW |
36 | } else if (nf_logging[pf] == logger) |
37 | ret = -EEXIST; | |
38 | ||
f6ebe77f HW |
39 | spin_unlock(&nf_log_lock); |
40 | return ret; | |
41 | } | |
42 | EXPORT_SYMBOL(nf_log_register); | |
43 | ||
8a61fadb | 44 | int nf_log_unregister_pf(int pf) |
f6ebe77f | 45 | { |
8a61fadb HW |
46 | if (pf >= NPROTO) |
47 | return -EINVAL; | |
48 | ||
f6ebe77f HW |
49 | spin_lock(&nf_log_lock); |
50 | nf_logging[pf] = NULL; | |
51 | spin_unlock(&nf_log_lock); | |
52 | ||
53 | /* Give time to concurrent readers. */ | |
54 | synchronize_net(); | |
8a61fadb HW |
55 | |
56 | return 0; | |
f6ebe77f HW |
57 | } |
58 | EXPORT_SYMBOL(nf_log_unregister_pf); | |
59 | ||
60 | void nf_log_unregister_logger(struct nf_logger *logger) | |
61 | { | |
62 | int i; | |
63 | ||
64 | spin_lock(&nf_log_lock); | |
65 | for (i = 0; i < NPROTO; i++) { | |
66 | if (nf_logging[i] == logger) | |
67 | nf_logging[i] = NULL; | |
68 | } | |
69 | spin_unlock(&nf_log_lock); | |
70 | ||
71 | synchronize_net(); | |
72 | } | |
73 | EXPORT_SYMBOL(nf_log_unregister_logger); | |
74 | ||
75 | void nf_log_packet(int pf, | |
76 | unsigned int hooknum, | |
77 | const struct sk_buff *skb, | |
78 | const struct net_device *in, | |
79 | const struct net_device *out, | |
80 | struct nf_loginfo *loginfo, | |
81 | const char *fmt, ...) | |
82 | { | |
83 | va_list args; | |
84 | char prefix[NF_LOG_PREFIXLEN]; | |
85 | struct nf_logger *logger; | |
86 | ||
87 | rcu_read_lock(); | |
88 | logger = rcu_dereference(nf_logging[pf]); | |
89 | if (logger) { | |
90 | va_start(args, fmt); | |
91 | vsnprintf(prefix, sizeof(prefix), fmt, args); | |
92 | va_end(args); | |
93 | /* We must read logging before nf_logfn[pf] */ | |
94 | logger->logfn(pf, hooknum, skb, in, out, loginfo, prefix); | |
95 | } else if (net_ratelimit()) { | |
96 | printk(KERN_WARNING "nf_log_packet: can\'t log since " | |
97 | "no backend logging module loaded in! Please either " | |
98 | "load one, or disable logging explicitly\n"); | |
99 | } | |
100 | rcu_read_unlock(); | |
101 | } | |
102 | EXPORT_SYMBOL(nf_log_packet); | |
103 | ||
104 | #ifdef CONFIG_PROC_FS | |
105 | static void *seq_start(struct seq_file *seq, loff_t *pos) | |
106 | { | |
107 | rcu_read_lock(); | |
108 | ||
109 | if (*pos >= NPROTO) | |
110 | return NULL; | |
111 | ||
112 | return pos; | |
113 | } | |
114 | ||
115 | static void *seq_next(struct seq_file *s, void *v, loff_t *pos) | |
116 | { | |
117 | (*pos)++; | |
118 | ||
119 | if (*pos >= NPROTO) | |
120 | return NULL; | |
121 | ||
122 | return pos; | |
123 | } | |
124 | ||
125 | static void seq_stop(struct seq_file *s, void *v) | |
126 | { | |
127 | rcu_read_unlock(); | |
128 | } | |
129 | ||
130 | static int seq_show(struct seq_file *s, void *v) | |
131 | { | |
132 | loff_t *pos = v; | |
133 | const struct nf_logger *logger; | |
134 | ||
135 | logger = rcu_dereference(nf_logging[*pos]); | |
136 | ||
137 | if (!logger) | |
138 | return seq_printf(s, "%2lld NONE\n", *pos); | |
139 | ||
140 | return seq_printf(s, "%2lld %s\n", *pos, logger->name); | |
141 | } | |
142 | ||
143 | static struct seq_operations nflog_seq_ops = { | |
144 | .start = seq_start, | |
145 | .next = seq_next, | |
146 | .stop = seq_stop, | |
147 | .show = seq_show, | |
148 | }; | |
149 | ||
150 | static int nflog_open(struct inode *inode, struct file *file) | |
151 | { | |
152 | return seq_open(file, &nflog_seq_ops); | |
153 | } | |
154 | ||
155 | static struct file_operations nflog_file_ops = { | |
156 | .owner = THIS_MODULE, | |
157 | .open = nflog_open, | |
158 | .read = seq_read, | |
159 | .llseek = seq_lseek, | |
160 | .release = seq_release, | |
161 | }; | |
162 | ||
163 | #endif /* PROC_FS */ | |
164 | ||
165 | ||
166 | int __init netfilter_log_init(void) | |
167 | { | |
168 | #ifdef CONFIG_PROC_FS | |
169 | struct proc_dir_entry *pde; | |
170 | pde = create_proc_entry("nf_log", S_IRUGO, proc_net_netfilter); | |
171 | #endif | |
172 | if (!pde) | |
173 | return -1; | |
174 | ||
175 | pde->proc_fops = &nflog_file_ops; | |
176 | ||
177 | return 0; | |
178 | } |