diff options
author | Harald Welte <laforge@netfilter.org> | 2005-08-09 23:23:11 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 18:51:18 -0400 |
commit | bbd86b9fc469b7e91dc7444e6abb8930811d79cb (patch) | |
tree | 0d1133f5f499cab639784407f53938ba5060807f | |
parent | fbcd923c3e0c8ec9e4ed64f5a4e5766807b32729 (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.h | 13 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 9 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 9 | ||||
-rw-r--r-- | net/netfilter/nf_log.c | 1 | ||||
-rw-r--r-- | net/netfilter/nf_queue.c | 106 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 12 |
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 */ |
228 | typedef int (*nf_queue_outfn_t)(struct sk_buff *skb, | 228 | struct 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 | }; | ||
231 | extern int nf_register_queue_handler(int pf, | 234 | extern int nf_register_queue_handler(int pf, |
232 | nf_queue_outfn_t outfn, void *data); | 235 | struct nf_queue_handler *qh); |
233 | extern int nf_unregister_queue_handler(int pf); | 236 | extern int nf_unregister_queue_handler(int pf); |
234 | extern void nf_unregister_queue_handlers(nf_queue_outfn_t outfn); | 237 | extern void nf_unregister_queue_handlers(struct nf_queue_handler *qh); |
235 | extern void nf_reinject(struct sk_buff *skb, | 238 | extern 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 | ||
659 | static struct nf_queue_handler nfqh = { | ||
660 | .name = "ip_queue", | ||
661 | .outfn = &ipq_enqueue_packet, | ||
662 | }; | ||
663 | |||
659 | static int | 664 | static int |
660 | init_or_cleanup(int init) | 665 | init_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 | ||
694 | cleanup: | 699 | cleanup: |
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 | ||
655 | static struct nf_queue_handler nfqh = { | ||
656 | .name = "ip6_queue", | ||
657 | .outfn = &ipq_enqueue_packet, | ||
658 | }; | ||
659 | |||
655 | static int | 660 | static int |
656 | init_or_cleanup(int init) | 661 | init_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 | ||
689 | cleanup: | 694 | cleanup: |
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 | */ |
17 | static struct nf_queue_handler_t { | 18 | static struct nf_queue_handler *queue_handler[NPROTO]; |
18 | nf_queue_outfn_t outfn; | ||
19 | void *data; | ||
20 | } queue_handler[NPROTO]; | ||
21 | |||
22 | static struct nf_queue_rerouter *queue_rerouter; | 19 | static struct nf_queue_rerouter *queue_rerouter; |
23 | 20 | ||
24 | static DEFINE_RWLOCK(queue_handler_lock); | 21 | static DEFINE_RWLOCK(queue_handler_lock); |
25 | 22 | ||
26 | 23 | int nf_register_queue_handler(int pf, struct nf_queue_handler *qh) | |
27 | int 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 | } |
86 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); | 80 | EXPORT_SYMBOL_GPL(nf_unregister_queue_rerouter); |
87 | 81 | ||
88 | void nf_unregister_queue_handlers(nf_queue_outfn_t outfn) | 82 | void 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 | } |
260 | EXPORT_SYMBOL(nf_reinject); | 252 | EXPORT_SYMBOL(nf_reinject); |
261 | 253 | ||
254 | #ifdef CONFIG_PROC_FS | ||
255 | static void *seq_start(struct seq_file *seq, loff_t *pos) | ||
256 | { | ||
257 | if (*pos >= NPROTO) | ||
258 | return NULL; | ||
259 | |||
260 | return pos; | ||
261 | } | ||
262 | |||
263 | static 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 | |||
273 | static void seq_stop(struct seq_file *s, void *v) | ||
274 | { | ||
275 | |||
276 | } | ||
277 | |||
278 | static 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 | |||
295 | static struct seq_operations nfqueue_seq_ops = { | ||
296 | .start = seq_start, | ||
297 | .next = seq_next, | ||
298 | .stop = seq_stop, | ||
299 | .show = seq_show, | ||
300 | }; | ||
301 | |||
302 | static int nfqueue_open(struct inode *inode, struct file *file) | ||
303 | { | ||
304 | return seq_open(file, &nfqueue_seq_ops); | ||
305 | } | ||
306 | |||
307 | static 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 | |||
262 | int __init netfilter_queue_init(void) | 317 | int __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 | ||
848 | static struct nf_queue_handler nfqh = { | ||
849 | .name = "nf_queue", | ||
850 | .outfn = &nfqnl_enqueue_packet, | ||
851 | }; | ||
852 | |||
848 | static int | 853 | static int |
849 | nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | 854 | nfqnl_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 | ||
1100 | cleanup: | 1102 | cleanup: |
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); |