aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter/nfnetlink_queue.c
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-06-07 12:13:39 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2012-06-16 15:09:02 +0200
commit9cb0176654a7dc33a32af8a0bc9e0b2f9f9ebb0f (patch)
treed4945c63214441653bcd3f0ea3b3a15fb031798a /net/netfilter/nfnetlink_queue.c
parent1afc56794e03229fa53cfa3c5012704d226e1dec (diff)
downloadlinux-9cb0176654a7dc33a32af8a0bc9e0b2f9f9ebb0f.tar.gz
netfilter: add glue code to integrate nfnetlink_queue and ctnetlink
This patch allows you to include the conntrack information together with the packet that is sent to user-space via NFQUEUE. Previously, there was no integration between ctnetlink and nfnetlink_queue. If you wanted to access conntrack information from your libnetfilter_queue program, you required to query ctnetlink from user-space to obtain it. Thus, delaying the packet processing even more. Including the conntrack information is optional, you can set it via NFQA_CFG_F_CONNTRACK flag with the new NFQA_CFG_FLAGS attribute. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/netfilter/nfnetlink_queue.c')
-rw-r--r--net/netfilter/nfnetlink_queue.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 630da3d2c62a5..647923ae9230e 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -30,6 +30,7 @@
#include <linux/list.h>
#include <net/sock.h>
#include <net/netfilter/nf_queue.h>
+#include <net/netfilter/nf_conntrack.h>
#include <linux/atomic.h>
@@ -233,6 +234,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
struct sk_buff *entskb = entry->skb;
struct net_device *indev;
struct net_device *outdev;
+ struct nfq_ct_hook *nfq_ct;
+ struct nf_conn *ct = NULL;
+ enum ip_conntrack_info uninitialized_var(ctinfo);
size = NLMSG_SPACE(sizeof(struct nfgenmsg))
+ nla_total_size(sizeof(struct nfqnl_msg_packet_hdr))
@@ -266,6 +270,17 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
break;
}
+ /* rcu_read_lock()ed by __nf_queue already. */
+ nfq_ct = rcu_dereference(nfq_ct_hook);
+ if (nfq_ct != NULL && (queue->flags & NFQA_CFG_F_CONNTRACK)) {
+ ct = nf_ct_get(entskb, &ctinfo);
+ if (ct) {
+ if (!nf_ct_is_untracked(ct))
+ size += nfq_ct->build_size(ct);
+ else
+ ct = NULL;
+ }
+ }
skb = alloc_skb(size, GFP_ATOMIC);
if (!skb)
@@ -389,6 +404,24 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
BUG();
}
+ if (ct) {
+ struct nlattr *nest_parms;
+ u_int32_t tmp;
+
+ nest_parms = nla_nest_start(skb, NFQA_CT | NLA_F_NESTED);
+ if (!nest_parms)
+ goto nla_put_failure;
+
+ if (nfq_ct->build(skb, ct) < 0)
+ goto nla_put_failure;
+
+ nla_nest_end(skb, nest_parms);
+
+ tmp = ctinfo;
+ if (nla_put_u32(skb, NFQA_CT_INFO, htonl(ctinfo)))
+ goto nla_put_failure;
+ }
+
nlh->nlmsg_len = skb->tail - old_tail;
return skb;
@@ -632,6 +665,7 @@ static const struct nla_policy nfqa_verdict_policy[NFQA_MAX+1] = {
[NFQA_VERDICT_HDR] = { .len = sizeof(struct nfqnl_msg_verdict_hdr) },
[NFQA_MARK] = { .type = NLA_U32 },
[NFQA_PAYLOAD] = { .type = NLA_UNSPEC },
+ [NFQA_CT] = { .type = NLA_UNSPEC },
};
static const struct nla_policy nfqa_verdict_batch_policy[NFQA_MAX+1] = {
@@ -732,6 +766,7 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
struct nfqnl_instance *queue;
unsigned int verdict;
struct nf_queue_entry *entry;
+ struct nfq_ct_hook *nfq_ct;
queue = instance_lookup(queue_num);
if (!queue)
@@ -750,6 +785,19 @@ nfqnl_recv_verdict(struct sock *ctnl, struct sk_buff *skb,
if (entry == NULL)
return -ENOENT;
+ rcu_read_lock();
+ nfq_ct = rcu_dereference(nfq_ct_hook);
+ if (nfq_ct != NULL &&
+ (queue->flags & NFQA_CFG_F_CONNTRACK) && nfqa[NFQA_CT]) {
+ enum ip_conntrack_info ctinfo;
+ struct nf_conn *ct;
+
+ ct = nf_ct_get(entry->skb, &ctinfo);
+ if (ct && !nf_ct_is_untracked(ct))
+ nfq_ct->parse(nfqa[NFQA_CT], ct);
+ }
+ rcu_read_unlock();
+
if (nfqa[NFQA_PAYLOAD]) {
if (nfqnl_mangle(nla_data(nfqa[NFQA_PAYLOAD]),
nla_len(nfqa[NFQA_PAYLOAD]), entry) < 0)