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