aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@netfilter.org>2005-08-09 23:23:11 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 18:51:18 -0400
commitbbd86b9fc469b7e91dc7444e6abb8930811d79cb (patch)
tree0d1133f5f499cab639784407f53938ba5060807f
parentfbcd923c3e0c8ec9e4ed64f5a4e5766807b32729 (diff)
[NETFILTER]: add /proc/net/netfilter interface to nf_queue
This patch adds a /proc/net/netfilter/nf_queue file, similar to the recently-added /proc/net/netfilter/nf_log. It indicates which queue handler is registered to which protocol family. This is useful since there are now multiple queue handlers in the treee (ip[6]_queue, nfnetlink_queue). Signed-off-by: Harald Welte <laforge@netfilter.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netfilter.h13
-rw-r--r--net/ipv4/netfilter/ip_queue.c9
-rw-r--r--net/ipv6/netfilter/ip6_queue.c9
-rw-r--r--net/netfilter/nf_log.c1
-rw-r--r--net/netfilter/nf_queue.c106
-rw-r--r--net/netfilter/nfnetlink_queue.c12
6 files changed, 116 insertions, 34 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 815583af06c2..bf430fcbe364 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -225,13 +225,16 @@ int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt,
225 int *len); 225 int *len);
226 226
227/* Packet queuing */ 227/* Packet queuing */
228typedef int (*nf_queue_outfn_t)(struct sk_buff *skb, 228struct nf_queue_handler {
229 struct nf_info *info, 229 int (*outfn)(struct sk_buff *skb, struct nf_info *info,
230 unsigned int queuenum, void *data); 230 unsigned int queuenum, void *data);
231 void *data;
232 char *name;
233};
231extern int nf_register_queue_handler(int pf, 234extern int nf_register_queue_handler(int pf,
232 nf_queue_outfn_t outfn, void *data); 235 struct nf_queue_handler *qh);
233extern int nf_unregister_queue_handler(int pf); 236extern int nf_unregister_queue_handler(int pf);
234extern void nf_unregister_queue_handlers(nf_queue_outfn_t outfn); 237extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh);
235extern void nf_reinject(struct sk_buff *skb, 238extern void nf_reinject(struct sk_buff *skb,
236 struct nf_info *info, 239 struct nf_info *info,
237 unsigned int verdict); 240 unsigned int verdict);
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 629de649f130..1c49833e00a9 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -656,6 +656,11 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
656} 656}
657#endif /* CONFIG_PROC_FS */ 657#endif /* CONFIG_PROC_FS */
658 658
659static struct nf_queue_handler nfqh = {
660 .name = "ip_queue",
661 .outfn = &ipq_enqueue_packet,
662};
663
659static int 664static int
660init_or_cleanup(int init) 665init_or_cleanup(int init)
661{ 666{
@@ -684,7 +689,7 @@ init_or_cleanup(int init)
684 register_netdevice_notifier(&ipq_dev_notifier); 689 register_netdevice_notifier(&ipq_dev_notifier);
685 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); 690 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
686 691
687 status = nf_register_queue_handler(PF_INET, ipq_enqueue_packet, NULL); 692 status = nf_register_queue_handler(PF_INET, &nfqh);
688 if (status < 0) { 693 if (status < 0) {
689 printk(KERN_ERR "ip_queue: failed to register queue handler\n"); 694 printk(KERN_ERR "ip_queue: failed to register queue handler\n");
690 goto cleanup_sysctl; 695 goto cleanup_sysctl;
@@ -692,7 +697,7 @@ init_or_cleanup(int init)
692 return status; 697 return status;
693 698
694cleanup: 699cleanup:
695 nf_unregister_queue_handlers(&ipq_enqueue_packet); 700 nf_unregister_queue_handlers(&nfqh);
696 synchronize_net(); 701 synchronize_net();
697 ipq_flush(NF_DROP); 702 ipq_flush(NF_DROP);
698 703
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 56ffec3568fa..7ecb91e24a34 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -652,6 +652,11 @@ ipq_get_info(char *buffer, char **start, off_t offset, int length)
652 return len; 652 return len;
653} 653}
654 654
655static struct nf_queue_handler nfqh = {
656 .name = "ip6_queue",
657 .outfn = &ipq_enqueue_packet,
658};
659
655static int 660static int
656init_or_cleanup(int init) 661init_or_cleanup(int init)
657{ 662{
@@ -679,7 +684,7 @@ init_or_cleanup(int init)
679 register_netdevice_notifier(&ipq_dev_notifier); 684 register_netdevice_notifier(&ipq_dev_notifier);
680 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0); 685 ipq_sysctl_header = register_sysctl_table(ipq_root_table, 0);
681 686
682 status = nf_register_queue_handler(PF_INET6, ipq_enqueue_packet, NULL); 687 status = nf_register_queue_handler(PF_INET6, &nfqh);
683 if (status < 0) { 688 if (status < 0) {
684 printk(KERN_ERR "ip6_queue: failed to register queue handler\n"); 689 printk(KERN_ERR "ip6_queue: failed to register queue handler\n");
685 goto cleanup_sysctl; 690 goto cleanup_sysctl;
@@ -687,7 +692,7 @@ init_or_cleanup(int init)
687 return status; 692 return status;
688 693
689cleanup: 694cleanup:
690 nf_unregister_queue_handlers(&ipq_enqueue_packet); 695 nf_unregister_queue_handlers(&nfqh);
691 synchronize_net(); 696 synchronize_net();
692 ipq_flush(NF_DROP); 697 ipq_flush(NF_DROP);
693 698
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index ec58c4d2c667..31a9d63921d6 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -5,6 +5,7 @@
5#include <linux/proc_fs.h> 5#include <linux/proc_fs.h>
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7#include <linux/netfilter.h> 7#include <linux/netfilter.h>
8#include <linux/seq_file.h>
8#include <net/protocol.h> 9#include <net/protocol.h>
9 10
10#include "nf_internals.h" 11#include "nf_internals.h"
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index 5586f843ed45..8a67bde8b640 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -5,6 +5,7 @@
5#include <linux/proc_fs.h> 5#include <linux/proc_fs.h>
6#include <linux/skbuff.h> 6#include <linux/skbuff.h>
7#include <linux/netfilter.h> 7#include <linux/netfilter.h>
8#include <linux/seq_file.h>
8#include <net/protocol.h> 9#include <net/protocol.h>
9 10
10#include "nf_internals.h" 11#include "nf_internals.h"
@@ -14,17 +15,12 @@
14 * long term mutex. The handler must provide an an outfn() to accept packets 15 * long term mutex. The handler must provide an an outfn() to accept packets
15 * for queueing and must reinject all packets it receives, no matter what. 16 * for queueing and must reinject all packets it receives, no matter what.
16 */ 17 */
17static struct nf_queue_handler_t { 18static struct nf_queue_handler *queue_handler[NPROTO];
18 nf_queue_outfn_t outfn;
19 void *data;
20} queue_handler[NPROTO];
21
22static struct nf_queue_rerouter *queue_rerouter; 19static struct nf_queue_rerouter *queue_rerouter;
23 20
24static DEFINE_RWLOCK(queue_handler_lock); 21static DEFINE_RWLOCK(queue_handler_lock);
25 22
26 23int nf_register_queue_handler(int pf, struct nf_queue_handler *qh)
27int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
28{ 24{
29 int ret; 25 int ret;
30 26
@@ -32,11 +28,10 @@ int nf_register_queue_handler(int pf, nf_queue_outfn_t outfn, void *data)
32 return -EINVAL; 28 return -EINVAL;
33 29
34 write_lock_bh(&queue_handler_lock); 30 write_lock_bh(&queue_handler_lock);
35 if (queue_handler[pf].outfn) 31 if (queue_handler[pf])
36 ret = -EBUSY; 32 ret = -EBUSY;
37 else { 33 else {
38 queue_handler[pf].outfn = outfn; 34 queue_handler[pf] = qh;
39 queue_handler[pf].data = data;
40 ret = 0; 35 ret = 0;
41 } 36 }
42 write_unlock_bh(&queue_handler_lock); 37 write_unlock_bh(&queue_handler_lock);
@@ -52,8 +47,7 @@ int nf_unregister_queue_handler(int pf)
52 return -EINVAL; 47 return -EINVAL;
53 48
54 write_lock_bh(&queue_handler_lock); 49 write_lock_bh(&queue_handler_lock);
55 queue_handler[pf].outfn = NULL; 50 queue_handler[pf] = NULL;
56 queue_handler[pf].data = NULL;
57 write_unlock_bh(&queue_handler_lock); 51 write_unlock_bh(&queue_handler_lock);
58 52
59 return 0; 53 return 0;
@@ -85,16 +79,14 @@ int nf_unregister_queue_rerouter(int pf)
85} 79}
86EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); 80EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter);
87 81
88void nf_unregister_queue_handlers(nf_queue_outfn_t outfn) 82void nf_unregister_queue_handlers(struct nf_queue_handler *qh)
89{ 83{
90 int pf; 84 int pf;
91 85
92 write_lock_bh(&queue_handler_lock); 86 write_lock_bh(&queue_handler_lock);
93 for (pf = 0; pf < NPROTO; pf++) { 87 for (pf = 0; pf < NPROTO; pf++) {
94 if (queue_handler[pf].outfn == outfn) { 88 if (queue_handler[pf] == qh)
95 queue_handler[pf].outfn = NULL; 89 queue_handler[pf] = NULL;
96 queue_handler[pf].data = NULL;
97 }
98 } 90 }
99 write_unlock_bh(&queue_handler_lock); 91 write_unlock_bh(&queue_handler_lock);
100} 92}
@@ -121,7 +113,7 @@ int nf_queue(struct sk_buff **skb,
121 113
122 /* QUEUE == DROP if noone is waiting, to be safe. */ 114 /* QUEUE == DROP if noone is waiting, to be safe. */
123 read_lock(&queue_handler_lock); 115 read_lock(&queue_handler_lock);
124 if (!queue_handler[pf].outfn) { 116 if (!queue_handler[pf]->outfn) {
125 read_unlock(&queue_handler_lock); 117 read_unlock(&queue_handler_lock);
126 kfree_skb(*skb); 118 kfree_skb(*skb);
127 return 1; 119 return 1;
@@ -162,8 +154,8 @@ int nf_queue(struct sk_buff **skb,
162 if (queue_rerouter[pf].save) 154 if (queue_rerouter[pf].save)
163 queue_rerouter[pf].save(*skb, info); 155 queue_rerouter[pf].save(*skb, info);
164 156
165 status = queue_handler[pf].outfn(*skb, info, queuenum, 157 status = queue_handler[pf]->outfn(*skb, info, queuenum,
166 queue_handler[pf].data); 158 queue_handler[pf]->data);
167 159
168 if (status >= 0 && queue_rerouter[pf].reroute) 160 if (status >= 0 && queue_rerouter[pf].reroute)
169 status = queue_rerouter[pf].reroute(skb, info); 161 status = queue_rerouter[pf].reroute(skb, info);
@@ -259,13 +251,87 @@ void nf_reinject(struct sk_buff *skb, struct nf_info *info,
259} 251}
260EXPORT_SYMBOL(nf_reinject); 252EXPORT_SYMBOL(nf_reinject);
261 253
254#ifdef CONFIG_PROC_FS
255static void *seq_start(struct seq_file *seq, loff_t *pos)
256{
257 if (*pos >= NPROTO)
258 return NULL;
259
260 return pos;
261}
262
263static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
264{
265 (*pos)++;
266
267 if (*pos >= NPROTO)
268 return NULL;
269
270 return pos;
271}
272
273static void seq_stop(struct seq_file *s, void *v)
274{
275
276}
277
278static int seq_show(struct seq_file *s, void *v)
279{
280 int ret;
281 loff_t *pos = v;
282 struct nf_queue_handler *qh;
283
284 read_lock_bh(&queue_handler_lock);
285 qh = queue_handler[*pos];
286 if (!qh)
287 ret = seq_printf(s, "%2lld NONE\n", *pos);
288 else
289 ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
290 read_unlock_bh(&queue_handler_lock);
291
292 return ret;
293}
294
295static struct seq_operations nfqueue_seq_ops = {
296 .start = seq_start,
297 .next = seq_next,
298 .stop = seq_stop,
299 .show = seq_show,
300};
301
302static int nfqueue_open(struct inode *inode, struct file *file)
303{
304 return seq_open(file, &nfqueue_seq_ops);
305}
306
307static struct file_operations nfqueue_file_ops = {
308 .owner = THIS_MODULE,
309 .open = nfqueue_open,
310 .read = seq_read,
311 .llseek = seq_lseek,
312 .release = seq_release,
313};
314#endif /* PROC_FS */
315
316
262int __init netfilter_queue_init(void) 317int __init netfilter_queue_init(void)
263{ 318{
319#ifdef CONFIG_PROC_FS
320 struct proc_dir_entry *pde;
321#endif
264 queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter), 322 queue_rerouter = kmalloc(NPROTO * sizeof(struct nf_queue_rerouter),
265 GFP_KERNEL); 323 GFP_KERNEL);
266 if (!queue_rerouter) 324 if (!queue_rerouter)
267 return -ENOMEM; 325 return -ENOMEM;
268 326
327#ifdef CONFIG_PROC_FS
328 pde = create_proc_entry("nf_queue", S_IRUGO, proc_net_netfilter);
329 if (!pde) {
330 kfree(queue_rerouter);
331 return -1;
332 }
333 pde->proc_fops = &nfqueue_file_ops;
334#endif
269 memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter)); 335 memset(queue_rerouter, 0, NPROTO * sizeof(struct nf_queue_rerouter));
270 336
271 return 0; 337 return 0;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index bf9223084b4a..741686ff71d8 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -845,6 +845,11 @@ static const int nfqa_cfg_min[NFQA_CFG_MAX] = {
845 [NFQA_CFG_PARAMS-1] = sizeof(struct nfqnl_msg_config_params), 845 [NFQA_CFG_PARAMS-1] = sizeof(struct nfqnl_msg_config_params),
846}; 846};
847 847
848static struct nf_queue_handler nfqh = {
849 .name = "nf_queue",
850 .outfn = &nfqnl_enqueue_packet,
851};
852
848static int 853static int
849nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, 854nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
850 struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp) 855 struct nlmsghdr *nlh, struct nfattr *nfqa[], int *errp)
@@ -890,10 +895,7 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
890 case NFQNL_CFG_CMD_PF_BIND: 895 case NFQNL_CFG_CMD_PF_BIND:
891 QDEBUG("registering queue handler for pf=%u\n", 896 QDEBUG("registering queue handler for pf=%u\n",
892 ntohs(cmd->pf)); 897 ntohs(cmd->pf));
893 ret = nf_register_queue_handler(ntohs(cmd->pf), 898 ret = nf_register_queue_handler(ntohs(cmd->pf), &nfqh);
894 nfqnl_enqueue_packet,
895 NULL);
896
897 break; 899 break;
898 case NFQNL_CFG_CMD_PF_UNBIND: 900 case NFQNL_CFG_CMD_PF_UNBIND:
899 QDEBUG("unregistering queue handler for pf=%u\n", 901 QDEBUG("unregistering queue handler for pf=%u\n",
@@ -1098,7 +1100,7 @@ init_or_cleanup(int init)
1098 return status; 1100 return status;
1099 1101
1100cleanup: 1102cleanup:
1101 nf_unregister_queue_handlers(nfqnl_enqueue_packet); 1103 nf_unregister_queue_handlers(&nfqh);
1102 unregister_netdevice_notifier(&nfqnl_dev_notifier); 1104 unregister_netdevice_notifier(&nfqnl_dev_notifier);
1103#ifdef CONFIG_PROC_FS 1105#ifdef CONFIG_PROC_FS
1104 remove_proc_entry("nfnetlink_queue", proc_net_netfilter); 1106 remove_proc_entry("nfnetlink_queue", proc_net_netfilter);