Blame view

net/netfilter/nf_log.c 12.9 KB
f6ebe77f9   Harald Welte   [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   Harald Welte   [NETFILTER]: add ...
7
  #include <linux/seq_file.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
8
  #include <net/protocol.h>
f01ffbd6e   Patrick McHardy   [NETFILTER]: nf_l...
9
  #include <net/netfilter/nf_log.h>
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
10
11
  
  #include "nf_internals.h"
a5d292646   YOSHIFUJI Hideaki   [NET] NETFILTER: ...
12
  /* Internal logging interface, which relies on the real
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
13
     LOG target modules */
176252746   Eric Leblond   netfilter: sysctl...
14
  #define NFLOGGER_NAME_LEN		64
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
15

2851940ff   Michal Kubeček   netfilter: allow ...
16
17
  int sysctl_nf_log_all_netns __read_mostly;
  EXPORT_SYMBOL(sysctl_nf_log_all_netns);
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
18
  static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly;
9b73534dc   Patrick McHardy   [NETFILTER]: nf_l...
19
  static DEFINE_MUTEX(nf_log_mutex);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
20

0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
21
22
  #define nft_log_dereference(logger) \
  	rcu_dereference_protected(logger, lockdep_is_held(&nf_log_mutex))
ca735b3aa   Eric Leblond   netfilter: use a ...
23
  static struct nf_logger *__find_logger(int pf, const char *str_logger)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
24
  {
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
25
26
27
28
29
30
  	struct nf_logger *log;
  	int i;
  
  	for (i = 0; i < NF_LOG_TYPE_MAX; i++) {
  		if (loggers[pf][i] == NULL)
  			continue;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
31

0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
32
  		log = nft_log_dereference(loggers[pf][i]);
18082746a   Rasmus Villemoes   netfilter: replac...
33
  		if (!strncasecmp(str_logger, log->name, strlen(log->name)))
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
34
  			return log;
ca735b3aa   Eric Leblond   netfilter: use a ...
35
  	}
d72367b6f   Harald Welte   [NETFILTER]: more...
36

ca735b3aa   Eric Leblond   netfilter: use a ...
37
  	return NULL;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
38
  }
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
39

779994fa3   Gao Feng   netfilter: log: C...
40
  int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger)
30e0c6a6b   Gao feng   netfilter: nf_log...
41
42
  {
  	const struct nf_logger *log;
779994fa3   Gao Feng   netfilter: log: C...
43
44
  	if (pf == NFPROTO_UNSPEC || pf >= ARRAY_SIZE(net->nf.nf_loggers))
  		return -EOPNOTSUPP;
30e0c6a6b   Gao feng   netfilter: nf_log...
45
46
  
  	mutex_lock(&nf_log_mutex);
0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
47
  	log = nft_log_dereference(net->nf.nf_loggers[pf]);
30e0c6a6b   Gao feng   netfilter: nf_log...
48
49
50
51
  	if (log == NULL)
  		rcu_assign_pointer(net->nf.nf_loggers[pf], logger);
  
  	mutex_unlock(&nf_log_mutex);
779994fa3   Gao Feng   netfilter: log: C...
52
53
  
  	return 0;
30e0c6a6b   Gao feng   netfilter: nf_log...
54
55
56
57
58
59
60
  }
  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   Gao feng   netfilter: nf_log...
61
62
  	mutex_lock(&nf_log_mutex);
  	for (i = 0; i < NFPROTO_NUMPROTO; i++) {
0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
63
  		log = nft_log_dereference(net->nf.nf_loggers[i]);
30e0c6a6b   Gao feng   netfilter: nf_log...
64
65
66
67
  		if (log == logger)
  			RCU_INIT_POINTER(net->nf.nf_loggers[i], NULL);
  	}
  	mutex_unlock(&nf_log_mutex);
30e0c6a6b   Gao feng   netfilter: nf_log...
68
69
  }
  EXPORT_SYMBOL(nf_log_unset);
d93cf0687   Adam Buchbinder   various: Fix spel...
70
  /* return EEXIST if the same logger is registered, 0 on success. */
ca735b3aa   Eric Leblond   netfilter: use a ...
71
  int nf_log_register(u_int8_t pf, struct nf_logger *logger)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
72
  {
b6f0a3652   Eric Dumazet   netfilter: nf_log...
73
  	int i;
8ac2bde2a   Marcelo Leitner   netfilter: log: p...
74
  	int ret = 0;
ca735b3aa   Eric Leblond   netfilter: use a ...
75

30e0c6a6b   Gao feng   netfilter: nf_log...
76
  	if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers))
ca735b3aa   Eric Leblond   netfilter: use a ...
77
  		return -EINVAL;
9b73534dc   Patrick McHardy   [NETFILTER]: nf_l...
78
  	mutex_lock(&nf_log_mutex);
ca735b3aa   Eric Leblond   netfilter: use a ...
79
80
  
  	if (pf == NFPROTO_UNSPEC) {
8ac2bde2a   Marcelo Leitner   netfilter: log: p...
81
82
83
84
85
86
  		for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) {
  			if (rcu_access_pointer(loggers[i][logger->type])) {
  				ret = -EEXIST;
  				goto unlock;
  			}
  		}
ca735b3aa   Eric Leblond   netfilter: use a ...
87
  		for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
88
  			rcu_assign_pointer(loggers[i][logger->type], logger);
ca735b3aa   Eric Leblond   netfilter: use a ...
89
  	} else {
8ac2bde2a   Marcelo Leitner   netfilter: log: p...
90
91
92
93
  		if (rcu_access_pointer(loggers[pf][logger->type])) {
  			ret = -EEXIST;
  			goto unlock;
  		}
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
94
  		rcu_assign_pointer(loggers[pf][logger->type], logger);
ca735b3aa   Eric Leblond   netfilter: use a ...
95
  	}
8ac2bde2a   Marcelo Leitner   netfilter: log: p...
96
  unlock:
9b73534dc   Patrick McHardy   [NETFILTER]: nf_l...
97
  	mutex_unlock(&nf_log_mutex);
8ac2bde2a   Marcelo Leitner   netfilter: log: p...
98
  	return ret;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
99
  }
ca735b3aa   Eric Leblond   netfilter: use a ...
100
  EXPORT_SYMBOL(nf_log_register);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
101

ca735b3aa   Eric Leblond   netfilter: use a ...
102
  void nf_log_unregister(struct nf_logger *logger)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
103
  {
205ee117d   Florian Westphal   netfilter: nf_log...
104
  	const struct nf_logger *log;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
105
  	int i;
9b73534dc   Patrick McHardy   [NETFILTER]: nf_l...
106
  	mutex_lock(&nf_log_mutex);
205ee117d   Florian Westphal   netfilter: nf_log...
107
108
109
110
111
  	for (i = 0; i < NFPROTO_NUMPROTO; i++) {
  		log = nft_log_dereference(loggers[i][logger->type]);
  		if (log == logger)
  			RCU_INIT_POINTER(loggers[i][logger->type], NULL);
  	}
9b73534dc   Patrick McHardy   [NETFILTER]: nf_l...
112
  	mutex_unlock(&nf_log_mutex);
ad5001cc7   Pablo Neira Ayuso   netfilter: nf_log...
113
  	synchronize_rcu();
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
114
  }
e92ad99c7   Patrick McHardy   [NETFILTER]: nf_l...
115
  EXPORT_SYMBOL(nf_log_unregister);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
116

30e0c6a6b   Gao feng   netfilter: nf_log...
117
118
  int nf_log_bind_pf(struct net *net, u_int8_t pf,
  		   const struct nf_logger *logger)
ca735b3aa   Eric Leblond   netfilter: use a ...
119
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
120
  	if (pf >= ARRAY_SIZE(net->nf.nf_loggers))
9ef0298a8   Jan Engelhardt   netfilter: nf_log...
121
  		return -EINVAL;
ca735b3aa   Eric Leblond   netfilter: use a ...
122
123
124
125
126
  	mutex_lock(&nf_log_mutex);
  	if (__find_logger(pf, logger->name) == NULL) {
  		mutex_unlock(&nf_log_mutex);
  		return -ENOENT;
  	}
30e0c6a6b   Gao feng   netfilter: nf_log...
127
  	rcu_assign_pointer(net->nf.nf_loggers[pf], logger);
ca735b3aa   Eric Leblond   netfilter: use a ...
128
129
130
131
  	mutex_unlock(&nf_log_mutex);
  	return 0;
  }
  EXPORT_SYMBOL(nf_log_bind_pf);
30e0c6a6b   Gao feng   netfilter: nf_log...
132
  void nf_log_unbind_pf(struct net *net, u_int8_t pf)
ca735b3aa   Eric Leblond   netfilter: use a ...
133
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
134
  	if (pf >= ARRAY_SIZE(net->nf.nf_loggers))
9ef0298a8   Jan Engelhardt   netfilter: nf_log...
135
  		return;
ca735b3aa   Eric Leblond   netfilter: use a ...
136
  	mutex_lock(&nf_log_mutex);
30e0c6a6b   Gao feng   netfilter: nf_log...
137
  	RCU_INIT_POINTER(net->nf.nf_loggers[pf], NULL);
ca735b3aa   Eric Leblond   netfilter: use a ...
138
139
140
  	mutex_unlock(&nf_log_mutex);
  }
  EXPORT_SYMBOL(nf_log_unbind_pf);
960649d19   Pablo Neira Ayuso   netfilter: bridge...
141
142
143
144
145
146
  void nf_logger_request_module(int pf, enum nf_log_type type)
  {
  	if (loggers[pf][type] == NULL)
  		request_module("nf-logger-%u-%u", pf, type);
  }
  EXPORT_SYMBOL_GPL(nf_logger_request_module);
fab4085f4   Pablo Neira Ayuso   netfilter: log: n...
147
148
149
150
  int nf_logger_find_get(int pf, enum nf_log_type type)
  {
  	struct nf_logger *logger;
  	int ret = -ENOENT;
f3bb53338   Liping Zhang   netfilter: nf_log...
151
152
153
154
155
156
157
158
159
160
161
162
163
  	if (pf == NFPROTO_INET) {
  		ret = nf_logger_find_get(NFPROTO_IPV4, type);
  		if (ret < 0)
  			return ret;
  
  		ret = nf_logger_find_get(NFPROTO_IPV6, type);
  		if (ret < 0) {
  			nf_logger_put(NFPROTO_IPV4, type);
  			return ret;
  		}
  
  		return 0;
  	}
c5a589cc3   Pablo Neira Ayuso   netfilter: nf_log...
164
  	if (rcu_access_pointer(loggers[pf][type]) == NULL)
fab4085f4   Pablo Neira Ayuso   netfilter: log: n...
165
166
167
168
169
170
  		request_module("nf-logger-%u-%u", pf, type);
  
  	rcu_read_lock();
  	logger = rcu_dereference(loggers[pf][type]);
  	if (logger == NULL)
  		goto out;
7e53e7f8c   Shivani Bhardwaj   netfilter: nf_log...
171
  	if (try_module_get(logger->me))
fab4085f4   Pablo Neira Ayuso   netfilter: log: n...
172
173
174
175
176
177
178
179
180
181
  		ret = 0;
  out:
  	rcu_read_unlock();
  	return ret;
  }
  EXPORT_SYMBOL_GPL(nf_logger_find_get);
  
  void nf_logger_put(int pf, enum nf_log_type type)
  {
  	struct nf_logger *logger;
f3bb53338   Liping Zhang   netfilter: nf_log...
182
183
184
185
186
  	if (pf == NFPROTO_INET) {
  		nf_logger_put(NFPROTO_IPV4, type);
  		nf_logger_put(NFPROTO_IPV6, type);
  		return;
  	}
fab4085f4   Pablo Neira Ayuso   netfilter: log: n...
187
188
189
190
191
192
193
194
  	BUG_ON(loggers[pf][type] == NULL);
  
  	rcu_read_lock();
  	logger = rcu_dereference(loggers[pf][type]);
  	module_put(logger->me);
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL_GPL(nf_logger_put);
30e0c6a6b   Gao feng   netfilter: nf_log...
195
196
  void nf_log_packet(struct net *net,
  		   u_int8_t pf,
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
197
198
199
200
  		   unsigned int hooknum,
  		   const struct sk_buff *skb,
  		   const struct net_device *in,
  		   const struct net_device *out,
7b2f9631e   Patrick McHardy   [NETFILTER]: nf_l...
201
  		   const struct nf_loginfo *loginfo,
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
202
203
204
205
  		   const char *fmt, ...)
  {
  	va_list args;
  	char prefix[NF_LOG_PREFIXLEN];
7b2f9631e   Patrick McHardy   [NETFILTER]: nf_l...
206
  	const struct nf_logger *logger;
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
207

f6ebe77f9   Harald Welte   [NETFILTER]: spli...
208
  	rcu_read_lock();
fab4085f4   Pablo Neira Ayuso   netfilter: log: n...
209
210
211
212
  	if (loginfo != NULL)
  		logger = rcu_dereference(loggers[pf][loginfo->type]);
  	else
  		logger = rcu_dereference(net->nf.nf_loggers[pf]);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
213
214
215
216
  	if (logger) {
  		va_start(args, fmt);
  		vsnprintf(prefix, sizeof(prefix), fmt, args);
  		va_end(args);
8cdb46da0   Hans Schillstrom   netfilter: log: n...
217
  		logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
218
219
220
221
  	}
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL(nf_log_packet);
4017a7ee6   Pablo Neira Ayuso   netfilter: restor...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  void nf_log_trace(struct net *net,
  		  u_int8_t pf,
  		  unsigned int hooknum,
  		  const struct sk_buff *skb,
  		  const struct net_device *in,
  		  const struct net_device *out,
  		  const struct nf_loginfo *loginfo, const char *fmt, ...)
  {
  	va_list args;
  	char prefix[NF_LOG_PREFIXLEN];
  	const struct nf_logger *logger;
  
  	rcu_read_lock();
  	logger = rcu_dereference(net->nf.nf_loggers[pf]);
  	if (logger) {
  		va_start(args, fmt);
  		vsnprintf(prefix, sizeof(prefix), fmt, args);
  		va_end(args);
  		logger->logfn(net, pf, hooknum, skb, in, out, loginfo, prefix);
  	}
  	rcu_read_unlock();
  }
  EXPORT_SYMBOL(nf_log_trace);
27fd8d90c   Pablo Neira Ayuso   netfilter: nf_log...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  #define S_SIZE (1024 - (sizeof(unsigned int) + 1))
  
  struct nf_log_buf {
  	unsigned int	count;
  	char		buf[S_SIZE + 1];
  };
  static struct nf_log_buf emergency, *emergency_ptr = &emergency;
  
  __printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...)
  {
  	va_list args;
  	int len;
  
  	if (likely(m->count < S_SIZE)) {
  		va_start(args, f);
  		len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args);
  		va_end(args);
  		if (likely(m->count + len < S_SIZE)) {
  			m->count += len;
  			return 0;
  		}
  	}
  	m->count = S_SIZE;
  	printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE
  ");
  	return -1;
  }
  EXPORT_SYMBOL_GPL(nf_log_buf_add);
  
  struct nf_log_buf *nf_log_buf_open(void)
  {
  	struct nf_log_buf *m = kmalloc(sizeof(*m), GFP_ATOMIC);
  
  	if (unlikely(!m)) {
  		local_bh_disable();
  		do {
  			m = xchg(&emergency_ptr, NULL);
  		} while (!m);
  	}
  	m->count = 0;
  	return m;
  }
  EXPORT_SYMBOL_GPL(nf_log_buf_open);
  
  void nf_log_buf_close(struct nf_log_buf *m)
  {
  	m->buf[m->count] = 0;
  	printk("%s
  ", m->buf);
  
  	if (likely(m != &emergency))
  		kfree(m);
  	else {
  		emergency_ptr = m;
  		local_bh_enable();
  	}
  }
  EXPORT_SYMBOL_GPL(nf_log_buf_close);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
303
304
305
  #ifdef CONFIG_PROC_FS
  static void *seq_start(struct seq_file *seq, loff_t *pos)
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
306
  	struct net *net = seq_file_net(seq);
6440fe059   Patrick McHardy   netfilter: nf_log...
307
  	mutex_lock(&nf_log_mutex);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
308

30e0c6a6b   Gao feng   netfilter: nf_log...
309
  	if (*pos >= ARRAY_SIZE(net->nf.nf_loggers))
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
310
311
312
313
314
315
316
  		return NULL;
  
  	return pos;
  }
  
  static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
317
  	struct net *net = seq_file_net(s);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
318
  	(*pos)++;
30e0c6a6b   Gao feng   netfilter: nf_log...
319
  	if (*pos >= ARRAY_SIZE(net->nf.nf_loggers))
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
320
321
322
323
324
325
326
  		return NULL;
  
  	return pos;
  }
  
  static void seq_stop(struct seq_file *s, void *v)
  {
6440fe059   Patrick McHardy   netfilter: nf_log...
327
  	mutex_unlock(&nf_log_mutex);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
328
329
330
331
332
333
  }
  
  static int seq_show(struct seq_file *s, void *v)
  {
  	loff_t *pos = v;
  	const struct nf_logger *logger;
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
334
  	int i;
30e0c6a6b   Gao feng   netfilter: nf_log...
335
  	struct net *net = seq_file_net(s);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
336

0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
337
  	logger = nft_log_dereference(net->nf.nf_loggers[*pos]);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
338
339
  
  	if (!logger)
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
340
  		seq_printf(s, "%2lld NONE (", *pos);
c7a913cd5   Eric Leblond   netfilter: print ...
341
  	else
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
342
  		seq_printf(s, "%2lld %s (", *pos, logger->name);
c7a913cd5   Eric Leblond   netfilter: print ...
343

e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
344
345
  	if (seq_has_overflowed(s))
  		return -ENOSPC;
c7a913cd5   Eric Leblond   netfilter: print ...
346

5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
347
348
349
  	for (i = 0; i < NF_LOG_TYPE_MAX; i++) {
  		if (loggers[*pos][i] == NULL)
  			continue;
0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
350
  		logger = nft_log_dereference(loggers[*pos][i]);
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
351
352
  		seq_printf(s, "%s", logger->name);
  		if (i == 0 && loggers[*pos][i + 1] != NULL)
cdec26858   simran singhal   netfilter: Use se...
353
  			seq_puts(s, ",");
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
354
355
356
  
  		if (seq_has_overflowed(s))
  			return -ENOSPC;
c7a913cd5   Eric Leblond   netfilter: print ...
357
  	}
601e68e10   YOSHIFUJI Hideaki   [NETFILTER]: Fix ...
358

cdec26858   simran singhal   netfilter: Use se...
359
360
  	seq_puts(s, ")
  ");
e71456ae9   Steven Rostedt (Red Hat)   netfilter: Remove...
361
362
363
364
  
  	if (seq_has_overflowed(s))
  		return -ENOSPC;
  	return 0;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
365
  }
56b3d975b   Philippe De Muyter   [NET]: Make all i...
366
  static const struct seq_operations nflog_seq_ops = {
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
367
368
369
370
371
372
373
374
  	.start	= seq_start,
  	.next	= seq_next,
  	.stop	= seq_stop,
  	.show	= seq_show,
  };
  
  static int nflog_open(struct inode *inode, struct file *file)
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
375
376
  	return seq_open_net(inode, file, &nflog_seq_ops,
  			    sizeof(struct seq_net_private));
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
377
  }
da7071d7e   Arjan van de Ven   [PATCH] mark stru...
378
  static const struct file_operations nflog_file_ops = {
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
379
380
381
382
  	.owner	 = THIS_MODULE,
  	.open	 = nflog_open,
  	.read	 = seq_read,
  	.llseek	 = seq_lseek,
30e0c6a6b   Gao feng   netfilter: nf_log...
383
  	.release = seq_release_net,
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
384
  };
176252746   Eric Leblond   netfilter: sysctl...
385

f6ebe77f9   Harald Welte   [NETFILTER]: spli...
386
  #endif /* PROC_FS */
176252746   Eric Leblond   netfilter: sysctl...
387
  #ifdef CONFIG_SYSCTL
176252746   Eric Leblond   netfilter: sysctl...
388
389
  static char nf_log_sysctl_fnames[NFPROTO_NUMPROTO-NFPROTO_UNSPEC][3];
  static struct ctl_table nf_log_sysctl_table[NFPROTO_NUMPROTO+1];
2851940ff   Michal Kubeček   netfilter: allow ...
390
391
392
393
394
395
396
397
398
399
400
401
  static struct ctl_table_header *nf_log_sysctl_fhdr;
  
  static struct ctl_table nf_log_sysctl_ftable[] = {
  	{
  		.procname	= "nf_log_all_netns",
  		.data		= &sysctl_nf_log_all_netns,
  		.maxlen		= sizeof(sysctl_nf_log_all_netns),
  		.mode		= 0644,
  		.proc_handler	= proc_dointvec,
  	},
  	{ }
  };
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
402

fe2c6338f   Joe Perches   net: Convert uses...
403
  static int nf_log_proc_dostring(struct ctl_table *table, int write,
249556192   Patrick McHardy   netfilter: nf_log...
404
  			 void __user *buffer, size_t *lenp, loff_t *ppos)
176252746   Eric Leblond   netfilter: sysctl...
405
406
  {
  	const struct nf_logger *logger;
249556192   Patrick McHardy   netfilter: nf_log...
407
  	char buf[NFLOGGER_NAME_LEN];
176252746   Eric Leblond   netfilter: sysctl...
408
409
  	int r = 0;
  	int tindex = (unsigned long)table->extra1;
dbb5918cb   Jann Horn   netfilter: fix na...
410
  	struct net *net = table->extra2;
176252746   Eric Leblond   netfilter: sysctl...
411
412
  
  	if (write) {
c6ac37d8d   Pavel Tikhomirov   netfilter: nf_log...
413
  		struct ctl_table tmp = *table;
4c3b0ae79   Jann Horn   netfilter: nf_log...
414
415
416
417
  		/* proc_dostring() can append to existing strings, so we need to
  		 * initialize it as an empty string.
  		 */
  		buf[0] = '\0';
c6ac37d8d   Pavel Tikhomirov   netfilter: nf_log...
418
419
420
421
  		tmp.data = buf;
  		r = proc_dostring(&tmp, write, buffer, lenp, ppos);
  		if (r)
  			return r;
249556192   Patrick McHardy   netfilter: nf_log...
422
423
  
  		if (!strcmp(buf, "NONE")) {
30e0c6a6b   Gao feng   netfilter: nf_log...
424
  			nf_log_unbind_pf(net, tindex);
176252746   Eric Leblond   netfilter: sysctl...
425
426
427
  			return 0;
  		}
  		mutex_lock(&nf_log_mutex);
249556192   Patrick McHardy   netfilter: nf_log...
428
  		logger = __find_logger(tindex, buf);
176252746   Eric Leblond   netfilter: sysctl...
429
430
431
432
  		if (logger == NULL) {
  			mutex_unlock(&nf_log_mutex);
  			return -ENOENT;
  		}
30e0c6a6b   Gao feng   netfilter: nf_log...
433
  		rcu_assign_pointer(net->nf.nf_loggers[tindex], logger);
176252746   Eric Leblond   netfilter: sysctl...
434
435
  		mutex_unlock(&nf_log_mutex);
  	} else {
6d2b458d3   Jann Horn   netfilter: nf_log...
436
437
438
  		struct ctl_table tmp = *table;
  
  		tmp.data = buf;
266d07cb1   Patrick McHardy   netfilter: nf_log...
439
  		mutex_lock(&nf_log_mutex);
0c26ed1c0   Marcelo Leitner   netfilter: nf_log...
440
  		logger = nft_log_dereference(net->nf.nf_loggers[tindex]);
176252746   Eric Leblond   netfilter: sysctl...
441
  		if (!logger)
6d2b458d3   Jann Horn   netfilter: nf_log...
442
  			strlcpy(buf, "NONE", sizeof(buf));
176252746   Eric Leblond   netfilter: sysctl...
443
  		else
6d2b458d3   Jann Horn   netfilter: nf_log...
444
  			strlcpy(buf, logger->name, sizeof(buf));
266d07cb1   Patrick McHardy   netfilter: nf_log...
445
  		mutex_unlock(&nf_log_mutex);
6d2b458d3   Jann Horn   netfilter: nf_log...
446
  		r = proc_dostring(&tmp, write, buffer, lenp, ppos);
176252746   Eric Leblond   netfilter: sysctl...
447
448
449
450
  	}
  
  	return r;
  }
30e0c6a6b   Gao feng   netfilter: nf_log...
451
  static int netfilter_log_sysctl_init(struct net *net)
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
452
  {
ca735b3aa   Eric Leblond   netfilter: use a ...
453
  	int i;
30e0c6a6b   Gao feng   netfilter: nf_log...
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  	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];
8aefc4d1c   Fabian Frederick   netfilter: log: r...
469
  			nf_log_sysctl_table[i].maxlen = NFLOGGER_NAME_LEN;
30e0c6a6b   Gao feng   netfilter: nf_log...
470
471
472
473
474
475
  			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;
  		}
2851940ff   Michal Kubeček   netfilter: allow ...
476
477
478
479
  		nf_log_sysctl_fhdr = register_net_sysctl(net, "net/netfilter",
  							 nf_log_sysctl_ftable);
  		if (!nf_log_sysctl_fhdr)
  			goto err_freg;
176252746   Eric Leblond   netfilter: sysctl...
480
  	}
dbb5918cb   Jann Horn   netfilter: fix na...
481
482
  	for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++)
  		table[i].extra2 = net;
30e0c6a6b   Gao feng   netfilter: nf_log...
483
484
485
486
487
  	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   Eric Leblond   netfilter: sysctl...
488
489
  
  	return 0;
30e0c6a6b   Gao feng   netfilter: nf_log...
490
491
492
493
  
  err_reg:
  	if (!net_eq(net, &init_net))
  		kfree(table);
2851940ff   Michal Kubeček   netfilter: allow ...
494
495
496
  	else
  		unregister_net_sysctl_table(nf_log_sysctl_fhdr);
  err_freg:
30e0c6a6b   Gao feng   netfilter: nf_log...
497
498
499
500
501
502
503
504
505
506
507
508
  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);
2851940ff   Michal Kubeček   netfilter: allow ...
509
510
  	else
  		unregister_net_sysctl_table(nf_log_sysctl_fhdr);
176252746   Eric Leblond   netfilter: sysctl...
511
512
  }
  #else
30e0c6a6b   Gao feng   netfilter: nf_log...
513
  static int netfilter_log_sysctl_init(struct net *net)
176252746   Eric Leblond   netfilter: sysctl...
514
515
516
  {
  	return 0;
  }
30e0c6a6b   Gao feng   netfilter: nf_log...
517
518
519
520
  
  static void netfilter_log_sysctl_exit(struct net *net)
  {
  }
176252746   Eric Leblond   netfilter: sysctl...
521
  #endif /* CONFIG_SYSCTL */
30e0c6a6b   Gao feng   netfilter: nf_log...
522
  static int __net_init nf_log_net_init(struct net *net)
176252746   Eric Leblond   netfilter: sysctl...
523
  {
30e0c6a6b   Gao feng   netfilter: nf_log...
524
  	int ret = -ENOMEM;
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
525
  #ifdef CONFIG_PROC_FS
8eeee8b15   Denis V. Lunev   [NETFILTER]: Repl...
526
  	if (!proc_create("nf_log", S_IRUGO,
30e0c6a6b   Gao feng   netfilter: nf_log...
527
528
  			 net->nf.proc_netfilter, &nflog_file_ops))
  		return ret;
622439270   Harald Welte   [NETFILTER]: Fix ...
529
  #endif
30e0c6a6b   Gao feng   netfilter: nf_log...
530
531
532
  	ret = netfilter_log_sysctl_init(net);
  	if (ret < 0)
  		goto out_sysctl;
ca735b3aa   Eric Leblond   netfilter: use a ...
533

30e0c6a6b   Gao feng   netfilter: nf_log...
534
535
536
  	return 0;
  
  out_sysctl:
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
537
  #ifdef CONFIG_PROC_FS
6d11cfdba   Pablo Neira Ayuso   netfilter: don't ...
538
  	remove_proc_entry("nf_log", net->nf.proc_netfilter);
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
539
  #endif
30e0c6a6b   Gao feng   netfilter: nf_log...
540
541
542
543
544
545
  	return ret;
  }
  
  static void __net_exit nf_log_net_exit(struct net *net)
  {
  	netfilter_log_sysctl_exit(net);
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
546
  #ifdef CONFIG_PROC_FS
30e0c6a6b   Gao feng   netfilter: nf_log...
547
  	remove_proc_entry("nf_log", net->nf.proc_netfilter);
e778f56e2   Pablo Neira Ayuso   netfilter: nf_{lo...
548
  #endif
30e0c6a6b   Gao feng   netfilter: nf_log...
549
550
551
552
553
554
555
556
557
  }
  
  static struct pernet_operations nf_log_net_ops = {
  	.init = nf_log_net_init,
  	.exit = nf_log_net_exit,
  };
  
  int __init netfilter_log_init(void)
  {
5962815a6   Pablo Neira Ayuso   netfilter: nf_log...
558
  	return register_pernet_subsys(&nf_log_net_ops);
f6ebe77f9   Harald Welte   [NETFILTER]: spli...
559
  }