Blame view
net/netfilter/nf_log.c
8.82 KB
f6ebe77f9 [NETFILTER]: spli... |
1 2 3 4 5 6 |
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/proc_fs.h> #include <linux/skbuff.h> #include <linux/netfilter.h> |
bbd86b9fc [NETFILTER]: add ... |
7 |
#include <linux/seq_file.h> |
f6ebe77f9 [NETFILTER]: spli... |
8 |
#include <net/protocol.h> |
f01ffbd6e [NETFILTER]: nf_l... |
9 |
#include <net/netfilter/nf_log.h> |
f6ebe77f9 [NETFILTER]: spli... |
10 11 |
#include "nf_internals.h" |
a5d292646 [NET] NETFILTER: ... |
12 |
/* Internal logging interface, which relies on the real |
f6ebe77f9 [NETFILTER]: spli... |
13 14 15 |
LOG target modules */ #define NF_LOG_PREFIXLEN 128 |
176252746 netfilter: sysctl... |
16 |
#define NFLOGGER_NAME_LEN 64 |
f6ebe77f9 [NETFILTER]: spli... |
17 |
|
ca735b3aa netfilter: use a ... |
18 |
static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; |
9b73534dc [NETFILTER]: nf_l... |
19 |
static DEFINE_MUTEX(nf_log_mutex); |
f6ebe77f9 [NETFILTER]: spli... |
20 |
|
ca735b3aa netfilter: use a ... |
21 |
static struct nf_logger *__find_logger(int pf, const char *str_logger) |
f6ebe77f9 [NETFILTER]: spli... |
22 |
{ |
ca735b3aa netfilter: use a ... |
23 |
struct nf_logger *t; |
f6ebe77f9 [NETFILTER]: spli... |
24 |
|
ca735b3aa netfilter: use a ... |
25 26 27 28 |
list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) { if (!strnicmp(str_logger, t->name, strlen(t->name))) return t; } |
d72367b6f [NETFILTER]: more... |
29 |
|
ca735b3aa netfilter: use a ... |
30 |
return NULL; |
601e68e10 [NETFILTER]: Fix ... |
31 |
} |
f6ebe77f9 [NETFILTER]: spli... |
32 |
|
30e0c6a6b netfilter: nf_log... |
33 34 35 |
void nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger) { const struct nf_logger *log; |
30e0c6a6b netfilter: nf_log... |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
if (pf == NFPROTO_UNSPEC) return; mutex_lock(&nf_log_mutex); log = rcu_dereference_protected(net->nf.nf_loggers[pf], lockdep_is_held(&nf_log_mutex)); if (log == NULL) rcu_assign_pointer(net->nf.nf_loggers[pf], logger); mutex_unlock(&nf_log_mutex); } EXPORT_SYMBOL(nf_log_set); void nf_log_unset(struct net *net, const struct nf_logger *logger) { int i; const struct nf_logger *log; |
30e0c6a6b netfilter: nf_log... |
53 54 55 56 57 58 59 60 61 62 63 |
mutex_lock(&nf_log_mutex); for (i = 0; i < NFPROTO_NUMPROTO; i++) { log = rcu_dereference_protected(net->nf.nf_loggers[i], lockdep_is_held(&nf_log_mutex)); if (log == logger) RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL); } mutex_unlock(&nf_log_mutex); synchronize_rcu(); } EXPORT_SYMBOL(nf_log_unset); |
d93cf0687 various: Fix spel... |
64 |
/* return EEXIST if the same logger is registered, 0 on success. */ |
ca735b3aa netfilter: use a ... |
65 |
int nf_log_register(u_int8_t pf, struct nf_logger *logger) |
f6ebe77f9 [NETFILTER]: spli... |
66 |
{ |
b6f0a3652 netfilter: nf_log... |
67 |
int i; |
ca735b3aa netfilter: use a ... |
68 |
|
30e0c6a6b netfilter: nf_log... |
69 |
if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) |
ca735b3aa netfilter: use a ... |
70 |
return -EINVAL; |
b6f0a3652 netfilter: nf_log... |
71 72 |
for (i = 0; i < ARRAY_SIZE(logger->list); i++) INIT_LIST_HEAD(&logger->list[i]); |
9b73534dc [NETFILTER]: nf_l... |
73 |
mutex_lock(&nf_log_mutex); |
ca735b3aa netfilter: use a ... |
74 75 |
if (pf == NFPROTO_UNSPEC) { |
ca735b3aa netfilter: use a ... |
76 77 78 79 80 |
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); } else { /* register at end of list to honor first register win */ list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); |
ca735b3aa netfilter: use a ... |
81 |
} |
9b73534dc [NETFILTER]: nf_l... |
82 |
mutex_unlock(&nf_log_mutex); |
f6ebe77f9 [NETFILTER]: spli... |
83 |
|
ca735b3aa netfilter: use a ... |
84 |
return 0; |
f6ebe77f9 [NETFILTER]: spli... |
85 |
} |
ca735b3aa netfilter: use a ... |
86 |
EXPORT_SYMBOL(nf_log_register); |
f6ebe77f9 [NETFILTER]: spli... |
87 |
|
ca735b3aa netfilter: use a ... |
88 |
void nf_log_unregister(struct nf_logger *logger) |
f6ebe77f9 [NETFILTER]: spli... |
89 90 |
{ int i; |
9b73534dc [NETFILTER]: nf_l... |
91 |
mutex_lock(&nf_log_mutex); |
30e0c6a6b netfilter: nf_log... |
92 |
for (i = 0; i < NFPROTO_NUMPROTO; i++) |
ca735b3aa netfilter: use a ... |
93 |
list_del(&logger->list[i]); |
9b73534dc [NETFILTER]: nf_l... |
94 |
mutex_unlock(&nf_log_mutex); |
f6ebe77f9 [NETFILTER]: spli... |
95 |
} |
e92ad99c7 [NETFILTER]: nf_l... |
96 |
EXPORT_SYMBOL(nf_log_unregister); |
f6ebe77f9 [NETFILTER]: spli... |
97 |
|
30e0c6a6b netfilter: nf_log... |
98 99 |
int nf_log_bind_pf(struct net *net, u_int8_t pf, const struct nf_logger *logger) |
ca735b3aa netfilter: use a ... |
100 |
{ |
30e0c6a6b netfilter: nf_log... |
101 |
if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) |
9ef0298a8 netfilter: nf_log... |
102 |
return -EINVAL; |
ca735b3aa netfilter: use a ... |
103 104 105 106 107 |
mutex_lock(&nf_log_mutex); if (__find_logger(pf, logger->name) == NULL) { mutex_unlock(&nf_log_mutex); return -ENOENT; } |
30e0c6a6b netfilter: nf_log... |
108 |
rcu_assign_pointer(net->nf.nf_loggers[pf], logger); |
ca735b3aa netfilter: use a ... |
109 110 111 112 |
mutex_unlock(&nf_log_mutex); return 0; } EXPORT_SYMBOL(nf_log_bind_pf); |
30e0c6a6b netfilter: nf_log... |
113 |
void nf_log_unbind_pf(struct net *net, u_int8_t pf) |
ca735b3aa netfilter: use a ... |
114 |
{ |
30e0c6a6b netfilter: nf_log... |
115 |
if (pf >= ARRAY_SIZE(net->nf.nf_loggers)) |
9ef0298a8 netfilter: nf_log... |
116 |
return; |
ca735b3aa netfilter: use a ... |
117 |
mutex_lock(&nf_log_mutex); |
30e0c6a6b netfilter: nf_log... |
118 |
RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL); |
ca735b3aa netfilter: use a ... |
119 120 121 |
mutex_unlock(&nf_log_mutex); } EXPORT_SYMBOL(nf_log_unbind_pf); |
30e0c6a6b netfilter: nf_log... |
122 123 |
void nf_log_packet(struct net *net, u_int8_t pf, |
f6ebe77f9 [NETFILTER]: spli... |
124 125 126 127 |
unsigned int hooknum, const struct sk_buff *skb, const struct net_device *in, const struct net_device *out, |
7b2f9631e [NETFILTER]: nf_l... |
128 |
const struct nf_loginfo *loginfo, |
f6ebe77f9 [NETFILTER]: spli... |
129 130 131 132 |
const char *fmt, ...) { va_list args; char prefix[NF_LOG_PREFIXLEN]; |
7b2f9631e [NETFILTER]: nf_l... |
133 |
const struct nf_logger *logger; |
601e68e10 [NETFILTER]: Fix ... |
134 |
|
f6ebe77f9 [NETFILTER]: spli... |
135 |
rcu_read_lock(); |
30e0c6a6b netfilter: nf_log... |
136 |
logger = rcu_dereference(net->nf.nf_loggers[pf]); |
f6ebe77f9 [NETFILTER]: spli... |
137 138 139 140 |
if (logger) { va_start(args, fmt); vsnprintf(prefix, sizeof(prefix), fmt, args); va_end(args); |
8cdb46da0 netfilter: log: n... |
141 |
logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix); |
f6ebe77f9 [NETFILTER]: spli... |
142 143 144 145 146 147 148 149 |
} rcu_read_unlock(); } EXPORT_SYMBOL(nf_log_packet); #ifdef CONFIG_PROC_FS static void *seq_start(struct seq_file *seq, loff_t *pos) { |
30e0c6a6b netfilter: nf_log... |
150 |
struct net *net = seq_file_net(seq); |
6440fe059 netfilter: nf_log... |
151 |
mutex_lock(&nf_log_mutex); |
f6ebe77f9 [NETFILTER]: spli... |
152 |
|
30e0c6a6b netfilter: nf_log... |
153 |
if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) |
f6ebe77f9 [NETFILTER]: spli... |
154 155 156 157 158 159 160 |
return NULL; return pos; } static void *seq_next(struct seq_file *s, void *v, loff_t *pos) { |
30e0c6a6b netfilter: nf_log... |
161 |
struct net *net = seq_file_net(s); |
f6ebe77f9 [NETFILTER]: spli... |
162 |
(*pos)++; |
30e0c6a6b netfilter: nf_log... |
163 |
if (*pos >= ARRAY_SIZE(net->nf.nf_loggers)) |
f6ebe77f9 [NETFILTER]: spli... |
164 165 166 167 168 169 170 |
return NULL; return pos; } static void seq_stop(struct seq_file *s, void *v) { |
6440fe059 netfilter: nf_log... |
171 |
mutex_unlock(&nf_log_mutex); |
f6ebe77f9 [NETFILTER]: spli... |
172 173 174 175 176 177 |
} static int seq_show(struct seq_file *s, void *v) { loff_t *pos = v; const struct nf_logger *logger; |
c7a913cd5 netfilter: print ... |
178 179 |
struct nf_logger *t; int ret; |
30e0c6a6b netfilter: nf_log... |
180 |
struct net *net = seq_file_net(s); |
f6ebe77f9 [NETFILTER]: spli... |
181 |
|
30e0c6a6b netfilter: nf_log... |
182 |
logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], |
0e60ebe04 netfilter: add __... |
183 |
lockdep_is_held(&nf_log_mutex)); |
f6ebe77f9 [NETFILTER]: spli... |
184 185 |
if (!logger) |
c7a913cd5 netfilter: print ... |
186 187 188 189 190 191 |
ret = seq_printf(s, "%2lld NONE (", *pos); else ret = seq_printf(s, "%2lld %s (", *pos, logger->name); if (ret < 0) return ret; |
c7a913cd5 netfilter: print ... |
192 193 |
list_for_each_entry(t, &nf_loggers_l[*pos], list[*pos]) { ret = seq_printf(s, "%s", t->name); |
6440fe059 netfilter: nf_log... |
194 |
if (ret < 0) |
c7a913cd5 netfilter: print ... |
195 |
return ret; |
c7a913cd5 netfilter: print ... |
196 197 |
if (&t->list[*pos] != nf_loggers_l[*pos].prev) { ret = seq_printf(s, ","); |
6440fe059 netfilter: nf_log... |
198 |
if (ret < 0) |
c7a913cd5 netfilter: print ... |
199 |
return ret; |
c7a913cd5 netfilter: print ... |
200 201 |
} } |
601e68e10 [NETFILTER]: Fix ... |
202 |
|
c7a913cd5 netfilter: print ... |
203 204 |
return seq_printf(s, ") "); |
f6ebe77f9 [NETFILTER]: spli... |
205 |
} |
56b3d975b [NET]: Make all i... |
206 |
static const struct seq_operations nflog_seq_ops = { |
f6ebe77f9 [NETFILTER]: spli... |
207 208 209 210 211 212 213 214 |
.start = seq_start, .next = seq_next, .stop = seq_stop, .show = seq_show, }; static int nflog_open(struct inode *inode, struct file *file) { |
30e0c6a6b netfilter: nf_log... |
215 216 |
return seq_open_net(inode, file, &nflog_seq_ops, sizeof(struct seq_net_private)); |
f6ebe77f9 [NETFILTER]: spli... |
217 |
} |
da7071d7e [PATCH] mark stru... |
218 |
static const struct file_operations nflog_file_ops = { |
f6ebe77f9 [NETFILTER]: spli... |
219 220 221 222 |
.owner = THIS_MODULE, .open = nflog_open, .read = seq_read, .llseek = seq_lseek, |
30e0c6a6b netfilter: nf_log... |
223 |
.release = seq_release_net, |
f6ebe77f9 [NETFILTER]: spli... |
224 |
}; |
176252746 netfilter: sysctl... |
225 |
|
f6ebe77f9 [NETFILTER]: spli... |
226 |
#endif /* PROC_FS */ |
176252746 netfilter: sysctl... |
227 |
#ifdef CONFIG_SYSCTL |
176252746 netfilter: sysctl... |
228 229 |
static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3]; static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1]; |
f6ebe77f9 [NETFILTER]: spli... |
230 |
|
fe2c6338f net: Convert uses... |
231 |
static int nf_log_proc_dostring(struct ctl_table *table, int write, |
249556192 netfilter: nf_log... |
232 |
void __user *buffer, size_t *lenp, loff_t *ppos) |
176252746 netfilter: sysctl... |
233 234 |
{ const struct nf_logger *logger; |
249556192 netfilter: nf_log... |
235 236 |
char buf[NFLOGGER_NAME_LEN]; size_t size = *lenp; |
176252746 netfilter: sysctl... |
237 238 |
int r = 0; int tindex = (unsigned long)table->extra1; |
30e0c6a6b netfilter: nf_log... |
239 |
struct net *net = current->nsproxy->net_ns; |
176252746 netfilter: sysctl... |
240 241 |
if (write) { |
249556192 netfilter: nf_log... |
242 243 244 245 246 247 |
if (size > sizeof(buf)) size = sizeof(buf); if (copy_from_user(buf, buffer, size)) return -EFAULT; if (!strcmp(buf, "NONE")) { |
30e0c6a6b netfilter: nf_log... |
248 |
nf_log_unbind_pf(net, tindex); |
176252746 netfilter: sysctl... |
249 250 251 |
return 0; } mutex_lock(&nf_log_mutex); |
249556192 netfilter: nf_log... |
252 |
logger = __find_logger(tindex, buf); |
176252746 netfilter: sysctl... |
253 254 255 256 |
if (logger == NULL) { mutex_unlock(&nf_log_mutex); return -ENOENT; } |
30e0c6a6b netfilter: nf_log... |
257 |
rcu_assign_pointer(net->nf.nf_loggers[tindex], logger); |
176252746 netfilter: sysctl... |
258 259 |
mutex_unlock(&nf_log_mutex); } else { |
266d07cb1 netfilter: nf_log... |
260 |
mutex_lock(&nf_log_mutex); |
30e0c6a6b netfilter: nf_log... |
261 |
logger = rcu_dereference_protected(net->nf.nf_loggers[tindex], |
0e60ebe04 netfilter: add __... |
262 |
lockdep_is_held(&nf_log_mutex)); |
176252746 netfilter: sysctl... |
263 264 265 266 |
if (!logger) table->data = "NONE"; else table->data = logger->name; |
8d65af789 sysctl: remove "s... |
267 |
r = proc_dostring(table, write, buffer, lenp, ppos); |
266d07cb1 netfilter: nf_log... |
268 |
mutex_unlock(&nf_log_mutex); |
176252746 netfilter: sysctl... |
269 270 271 272 |
} return r; } |
30e0c6a6b netfilter: nf_log... |
273 |
static int netfilter_log_sysctl_init(struct net *net) |
f6ebe77f9 [NETFILTER]: spli... |
274 |
{ |
ca735b3aa netfilter: use a ... |
275 |
int i; |
30e0c6a6b netfilter: nf_log... |
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 |
struct ctl_table *table; table = nf_log_sysctl_table; if (!net_eq(net, &init_net)) { table = kmemdup(nf_log_sysctl_table, sizeof(nf_log_sysctl_table), GFP_KERNEL); if (!table) goto err_alloc; } else { for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) { snprintf(nf_log_sysctl_fnames[i], 3, "%d", i); nf_log_sysctl_table[i].procname = nf_log_sysctl_fnames[i]; nf_log_sysctl_table[i].data = NULL; nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN * sizeof(char); nf_log_sysctl_table[i].mode = 0644; nf_log_sysctl_table[i].proc_handler = nf_log_proc_dostring; nf_log_sysctl_table[i].extra1 = (void *)(unsigned long) i; } |
176252746 netfilter: sysctl... |
300 |
} |
30e0c6a6b netfilter: nf_log... |
301 302 303 304 305 |
net->nf.nf_log_dir_header = register_net_sysctl(net, "net/netfilter/nf_log", table); if (!net->nf.nf_log_dir_header) goto err_reg; |
176252746 netfilter: sysctl... |
306 307 |
return 0; |
30e0c6a6b netfilter: nf_log... |
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
err_reg: if (!net_eq(net, &init_net)) kfree(table); err_alloc: return -ENOMEM; } static void netfilter_log_sysctl_exit(struct net *net) { struct ctl_table *table; table = net->nf.nf_log_dir_header->ctl_table_arg; unregister_net_sysctl_table(net->nf.nf_log_dir_header); if (!net_eq(net, &init_net)) kfree(table); |
176252746 netfilter: sysctl... |
324 325 |
} #else |
30e0c6a6b netfilter: nf_log... |
326 |
static int netfilter_log_sysctl_init(struct net *net) |
176252746 netfilter: sysctl... |
327 328 329 |
{ return 0; } |
30e0c6a6b netfilter: nf_log... |
330 331 332 333 |
static void netfilter_log_sysctl_exit(struct net *net) { } |
176252746 netfilter: sysctl... |
334 |
#endif /* CONFIG_SYSCTL */ |
30e0c6a6b netfilter: nf_log... |
335 |
static int __net_init nf_log_net_init(struct net *net) |
176252746 netfilter: sysctl... |
336 |
{ |
30e0c6a6b netfilter: nf_log... |
337 |
int ret = -ENOMEM; |
f6ebe77f9 [NETFILTER]: spli... |
338 |
#ifdef CONFIG_PROC_FS |
8eeee8b15 [NETFILTER]: Repl... |
339 |
if (!proc_create("nf_log", S_IRUGO, |
30e0c6a6b netfilter: nf_log... |
340 341 |
net->nf.proc_netfilter, &nflog_file_ops)) return ret; |
622439270 [NETFILTER]: Fix ... |
342 |
#endif |
30e0c6a6b netfilter: nf_log... |
343 344 345 |
ret = netfilter_log_sysctl_init(net); if (ret < 0) goto out_sysctl; |
ca735b3aa netfilter: use a ... |
346 |
|
30e0c6a6b netfilter: nf_log... |
347 348 349 |
return 0; out_sysctl: |
e778f56e2 netfilter: nf_{lo... |
350 |
#ifdef CONFIG_PROC_FS |
6d11cfdba netfilter: don't ... |
351 |
remove_proc_entry("nf_log", net->nf.proc_netfilter); |
e778f56e2 netfilter: nf_{lo... |
352 |
#endif |
30e0c6a6b netfilter: nf_log... |
353 354 355 356 357 358 |
return ret; } static void __net_exit nf_log_net_exit(struct net *net) { netfilter_log_sysctl_exit(net); |
e778f56e2 netfilter: nf_{lo... |
359 |
#ifdef CONFIG_PROC_FS |
30e0c6a6b netfilter: nf_log... |
360 |
remove_proc_entry("nf_log", net->nf.proc_netfilter); |
e778f56e2 netfilter: nf_{lo... |
361 |
#endif |
30e0c6a6b netfilter: nf_log... |
362 363 364 365 366 367 368 369 370 371 372 373 374 375 |
} static struct pernet_operations nf_log_net_ops = { .init = nf_log_net_init, .exit = nf_log_net_exit, }; int __init netfilter_log_init(void) { int i, ret; ret = register_pernet_subsys(&nf_log_net_ops); if (ret < 0) return ret; |
176252746 netfilter: sysctl... |
376 |
|
ca735b3aa netfilter: use a ... |
377 378 |
for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) INIT_LIST_HEAD(&(nf_loggers_l[i])); |
f6ebe77f9 [NETFILTER]: spli... |
379 380 |
return 0; } |